一、项目背景
随着物联网的发展,生活中带有网络的电器,很是方便。也有此也对网络控制产生了兴趣,接触嵌入式底层驱动和硬件设计方面的较多,对网络控制还不是很了解,一直想要尝试下使用物联网平台和嵌入式硬件的通信控制。感谢物联网开发平台提供的如软硬件资源,来实现我这个想法,接收设备的CAN通信数据,远程发送到腾讯云的物联网开发平台IoT Expolorer。
二、硬件部分
2.1、实现这个小项目使用的硬件有如下:
a、wifi模块
b、TencentOs-Tiny开发板
c、CAN通信转换模块
d、CAN终端调试设备
2.2、硬件框图
开发板通过CAN通信转换模块接收CAN设备的帧数据,解析和数据处理后,经WIFI模块将数据发送到腾讯云平台,无线终端可在物联网开发平台或腾讯连连小程序上看到。
2.3、硬件连接实物图
三、软件部分
3.1、CAN驱动底层msp2515.c
代码语言:javascript复制//mcp2515.c
#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_debug_console.h"
#include "fsl_gpio.h"
#include "mcp2515.h"
#include "led.h"
uint8_t id[4]={0x05,0x08,0x05,0x82}; //发送的ID地址
uint8_t rxdat[10];
gpio_pin_config_t mcp2515_output_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
gpio_pin_config_t mcp2515_input_config = {kGPIO_DigitalInput, 0, kGPIO_NoIntmode};
gpio_pin_config_t can_int_config = {kGPIO_DigitalInput, 0, kGPIO_IntFallingEdge, };
//端口初始化
void mcp2515_port_init(void)
{
GPIO_PinInit(E53_SPI_SCK, E53_SPI_SCK_PIN, &mcp2515_output_config); //CAN_SCK
GPIO_PinInit(E53_SPI_MOSI, E53_SPI_MOSI_PIN, &mcp2515_output_config); //CAN_MOSI
GPIO_PinInit(E53_SPI_MISO, E53_SPI_MISO_PIN, &mcp2515_input_config); //CAN_MISO
GPIO_PinInit(CAN_CS, CAN_CS_PIN, &mcp2515_output_config); //CAN_CS
//中断设置
EnableIRQ(EXAMPLE_CAN_IRQ);
GPIO_PinInit(EXAMPLE_CAN_GPIO, EXAMPLE_CAN_GPIO_PIN, &can_int_config);
//使能GPIO中断
GPIO_PortEnableInterrupts(EXAMPLE_CAN_GPIO, 1U << EXAMPLE_CAN_GPIO_PIN);
}
void EXAMPLE_CAN_IRQHandler(void)
{
GPIO_PortClearInterruptFlags(EXAMPLE_CAN_GPIO, 1U << EXAMPLE_CAN_GPIO_PIN);
CAN_Receive(rxdat);
CAN_Eint_Clear();
E53_GPIO3_TOG();
SDK_ISR_EXIT_BARRIER;
}
void dels(uint32_t tt)
{
uint32_t ds=0;
for(;ds<tt;ds );
}
uint8_t SPI_Read(void)
{
uint8_t n=8;
uint8_t tdata;
E53_SPI_SCK_LOW();
while(n--)
{
dels(100);
E53_SPI_SCK_HIGH();
tdata=tdata<<1;
if( 1 == GPIO_PinRead(E53_SPI_MISO, E53_SPI_MISO_PIN))
tdata=tdata|0x01;
else
tdata=tdata&0xfe;
E53_SPI_SCK_LOW();
}
return tdata;
}
void SPI_Write(uint8_t ch)
{
uint8_t n=8;
E53_SPI_SCK_LOW();
while(n--)
{
E53_SPI_SCK_LOW();
dels(100);
if((ch&0x80)==0x80)
{
E53_SPI_MOSI_HIGH();
}
else
{
E53_SPI_MOSI_LOW();
}
dels(100);
E53_SPI_SCK_HIGH();
dels(100);
ch=ch<<1;
}
}
void SPI_ByteWrite(uint8_t addr, uint8_t value)
{
CAN_CS_LOW();
SPI_Write(CAN_WRITE);
SPI_Write(addr);
SPI_Write(value);
CAN_CS_HIGH();
}
uint8_t SPI_ByteRead(uint8_t addr)
{
uint8_t tempdata;
CAN_CS_LOW();
SPI_Write(CAN_READ);
SPI_Write(addr);
tempdata=SPI_Read();
CAN_CS_HIGH();
return tempdata;
}
void SPI_Reset(void)
{
CAN_CS_LOW();
SPI_Write(CAN_RESET);
CAN_CS_HIGH();
}
void SPI_BitModityMcp2515(uint8_t addr, uint8_t mask, uint8_t udata)
{
CAN_CS_LOW();
SPI_Write(CAN_BIT_MODIFY);
SPI_Write(addr);
SPI_Write(mask);
SPI_Write(udata);
CAN_CS_HIGH();
return;
}
//写连续N个字节数据
void SPI_WriteRegister(uint8_t addr, uint8_t *dat, uint8_t length)
{
uint8_t i;
CAN_CS_LOW();
SPI_Write(CAN_WRITE);
SPI_Write(addr);
for (i=0; i<length ;i )
{
SPI_Write(*dat );
}
CAN_CS_HIGH();
}
//MCP2515初始化
void Init_MCP2515(void)
{
uint8_t temp[4] = { 0, 0, 0, 0 };
mcp2515_port_init();
SPI_Reset();
dels(1000);
SPI_BitModityMcp2515(CANCTRL,0xE0,0x80);
SPI_ByteWrite(CNF1,CAN_100Kbps);
SPI_ByteWrite(CNF2,0x80|PHSEG1_3TQ|PRSEG_1TQ);
SPI_ByteWrite(CNF3,PHSEG2_3TQ);
SPI_ByteWrite(CANINTF,0x00);
SPI_ByteWrite(CANINTE,0x01);
SPI_ByteWrite(RXB0CTRL,0x60);
SPI_ByteWrite(RXB1CTRL,0x60);
SPI_ByteWrite(RXF0SIDH,0x01);
SPI_ByteWrite(RXF0SIDL,0x08);
SPI_ByteWrite(RXF0EID8,0x05);
SPI_ByteWrite(RXF0EID0,0x11);
SPI_ByteWrite(RXM0SIDH,0xff);
SPI_ByteWrite(RXM0SIDL,0xff);
SPI_ByteWrite(RXM0EID8,0xff);
SPI_ByteWrite(RXM0EID0,0xff);
// SPI_WriteRegister( RXF0SIDH, temp, 4 );
SPI_WriteRegister( RXF1SIDH, temp, 4 );
SPI_WriteRegister( RXF2SIDH, temp, 4 );
SPI_WriteRegister( RXF3SIDH, temp, 4 );
SPI_WriteRegister( RXF4SIDH, temp, 4 );
SPI_WriteRegister( RXF5SIDH, temp, 4 );
// SPI_WriteRegister( RXM0SIDH, temp, 4 );
SPI_WriteRegister( RXM1SIDH, temp, 4 );
SPI_ByteWrite( BFPCTRL, 0 );
SPI_ByteWrite( TXRTSCTRL, 0 );
SPI_BitModityMcp2515(CANCTRL,0xE0,0x00);
}
void CAN_Send(uint8_t *CAN_TX_Buf)
{
SPI_BitModityMcp2515(TXB0CTRL,0x08,0x00);
SPI_ByteWrite(TXB0SIDH,id[0]);
SPI_ByteWrite(TXB0SIDL,id[1]);
SPI_ByteWrite(TXB0EID8,id[2]);
SPI_ByteWrite(TXB0EID0,id[3]);
SPI_ByteWrite(TXB0DLC,DLC_8);
SPI_ByteWrite(TXB0D0,CAN_TX_Buf[0]);
SPI_ByteWrite(TXB0D1,CAN_TX_Buf[1]);
SPI_ByteWrite(TXB0D2,CAN_TX_Buf[2]);
SPI_ByteWrite(TXB0D3,CAN_TX_Buf[3]);
SPI_ByteWrite(TXB0D4,CAN_TX_Buf[4]);
SPI_ByteWrite(TXB0D5,CAN_TX_Buf[5]);
SPI_ByteWrite(TXB0D6,CAN_TX_Buf[6]);
SPI_ByteWrite(TXB0D7,CAN_TX_Buf[7]);
CAN_CS_LOW();
SPI_Write(CAN_RTS | 0x01);
CAN_CS_HIGH();
}
void CAN_Receive(uint8_t *CAN_RX_Buf)
{
CAN_RX_Buf[0]=SPI_ByteRead(RXB0D0);
CAN_RX_Buf[1]=SPI_ByteRead(RXB0D1);
CAN_RX_Buf[2]=SPI_ByteRead(RXB0D2);
CAN_RX_Buf[3]=SPI_ByteRead(RXB0D3);
CAN_RX_Buf[4]=SPI_ByteRead(RXB0D4);
CAN_RX_Buf[5]=SPI_ByteRead(RXB0D5);
CAN_RX_Buf[6]=SPI_ByteRead(RXB0D6);
CAN_RX_Buf[7]=SPI_ByteRead(RXB0D7);
SPI_ByteWrite(CANINTF,0);
//while(SPI_ByteRead(CANINTF)!=0);
}
void CAN_Eint_Clear(void)
{
SPI_ByteWrite(CANINTF,0);
}
3.2、MQTT腾讯云上传部分程序
代码语言:javascript复制void mqttclient_task(void)
{
int error;
int lightness = 0;
int dat[10];
mqtt_client_t *client = NULL;
mqtt_message_t msg;
k_event_flag_t match_flag;
char host_ip[20];
memset(&msg, 0, sizeof(msg));
#ifdef USE_ESP8266
esp8266_sal_init(esp8266_port);
esp8266_join_ap("TP-LINK_0F58", "hhyf1bhhyf1b");
#endif
#ifdef USE_EC600S
ec600s_sal_init(HAL_UART_PORT_0);
#endif
mqtt_log_init();
client = mqtt_lease();
tos_event_create(&report_result_event, (k_event_flag_t)0u);
/* Domain Format: <your product ID>.iotcloud.tencentdevices.com */
tos_sal_module_parse_domain("C161S8COPH.iotcloud.tencentdevices.com",host_ip,sizeof(host_ip));
/*
These infomation is generated by mqtt_config_gen.py tool in "TencentOS-tinytools" directory.
*/
mqtt_set_port(client, "1883");
mqtt_set_host(client, host_ip);
mqtt_set_client_id(client, "C161S8COPHCAN_DEVICE");
mqtt_set_user_name(client, "C161S8COPHCAN_DEVICE;12010126;6SFTL;1647175200");
mqtt_set_password(client, "aa2a5bc2a3ba7c40959f7f07d925b402163424ea;hmacsha1");
mqtt_set_clean_session(client, 1);
error = mqtt_connect(client);
//MQTT_LOG_D("mqtt connect error is %#0x", error);
error = mqtt_subscribe(client, "$thing/down/property/C161S8COPH/CAN_DEVICE", QOS0, tos_topic_handler);
//MQTT_LOG_D("mqtt subscribe error is %#0x", error);
while (1) {
memset(&msg, 0, sizeof(msg));
//lightness=rxdat[0];
dat[0]=rxdat[0];
dat[1]=rxdat[1];
dat[2]=rxdat[2];
snprintf(report_buf, sizeof(report_buf), REPORT_DATA_TEMPLATE, dat[0]);
msg.qos = QOS0;
msg.payload = (void *) report_buf;
error = mqtt_publish(client, "$thing/up/property/C161S8COPH/CAN_DEVICE", &msg);
//MQTT_LOG_D("mqtt publish error is %#0x", error);
snprintf(report_buf, sizeof(report_buf), REPORT_DATA2_TEMPLATE, dat[1]);
msg.qos = QOS0;
msg.payload = (void *) report_buf;
error = mqtt_publish(client, "$thing/up/property/C161S8COPH/CAN_DEVICE", &msg);
snprintf(report_buf, sizeof(report_buf), REPORT_DATA3_TEMPLATE, dat[2]);
msg.qos = QOS0;
msg.payload = (void *) report_buf;
error = mqtt_publish(client, "$thing/up/property/C161S8COPH/CAN_DEVICE", &msg);
tos_event_pend(&report_result_event,
report_success|report_fail,
&match_flag,
TOS_TIME_FOREVER,
TOS_OPT_EVENT_PEND_ANY | TOS_OPT_EVENT_PEND_CLR);
if (match_flag == report_success) {
printf("report to Tencent IoT Explorer successrn");
}else if (match_flag == report_fail){
printf("report to Tencent IoT Explorer failrn");
}
tos_task_delay(1000);
}
}
3.3、程序源码
gitee地址:https://gitee.com/gtizhanghui/rt1062-tencentos.git
三、程序运行
3.1、CAN发送数据
程序运行CAN通信一直以1S间隔向外发送帧数据,表示CAN通信正常。手动发送CAN数据命令。
3.2、物联网数据监测平台接收的数据
3.3、手机腾讯连连小程序接收的数据
四、后记
通过此次活动实践后,对TencentOS Tiny和腾讯的网络平台有了了解,由于时间原因和对物联网传输的MQTT协议的了解不够深入,还有功能没有实现,自己设计的E53板有转CAN和RS485模块,只实现了CAN通信功能,后续在深入学习MQTT和TencentOS系统后,继续完善更多的功能。