AIoT应用创新大赛-基于TencentOS Tiny 的远程CAN数据监控

2022-03-07 13:41:27 浏览数 (1)

一、项目背景

随着物联网的发展,生活中带有网络的电器,很是方便。也有此也对网络控制产生了兴趣,接触嵌入式底层驱动和硬件设计方面的较多,对网络控制还不是很了解,一直想要尝试下使用物联网平台和嵌入式硬件的通信控制。感谢物联网开发平台提供的如软硬件资源,来实现我这个想法,接收设备的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数据命令。

CAN收发CAN收发

3.2、物联网数据监测平台接收的数据

物联网数据平台物联网数据平台

3.3、手机腾讯连连小程序接收的数据

腾讯连连小程序腾讯连连小程序

四、后记

通过此次活动实践后,对TencentOS Tiny和腾讯的网络平台有了了解,由于时间原因和对物联网传输的MQTT协议的了解不够深入,还有功能没有实现,自己设计的E53板有转CAN和RS485模块,只实现了CAN通信功能,后续在深入学习MQTT和TencentOS系统后,继续完善更多的功能。

0 人点赞