采集ADC、GPS经纬坐标、温湿度数据、大气压数据通过CAN方式发送给主设备端,帧ID按照如下定义:

我尼玛一个标准帧ID位数据是11位,扩展帧才是11+18=29位,它说最开头的是四位是真类型,并给我如下解释:

它把帧的定义当成了字节2和字节3的拼接了(整体的报文识别码),对于STM32帧ID设置是直接赋值,也就是它给我的帧ID需要左移5位才是实际帧ID。不多说直接上代码!波特率500kbs!
初始化部分:
cpp
void Can_Btl(u32 btl)
{
switch(btl)
{
case btl_5k :CAN_Mode_Init(CAN_SJW_2tq,CAN_BS1_6tq,CAN_BS2_4tq,600,CAN_Mode_Normal);break;
case btl_10k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_5tq,CAN_BS2_3tq,400,CAN_Mode_Normal);break;
case btl_20k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,300,CAN_Mode_Normal);break;
case btl_25k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,240,CAN_Mode_Normal);break;
case btl_40k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,150,CAN_Mode_Normal);break;
case btl_50k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,120,CAN_Mode_Normal);break;
case btl_62_5k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,96,CAN_Mode_Normal);break;
case btl_80k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,75,CAN_Mode_Normal);break;
case btl_100k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,60,CAN_Mode_Normal);break;
case btl_125k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,48,CAN_Mode_Normal);break;
case btl_200k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,30,CAN_Mode_Normal);break;
case btl_250k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,24,CAN_Mode_Normal);break;
case btl_400k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_5tq,CAN_BS2_3tq,10,CAN_Mode_Normal);break;
case btl_500k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,12,CAN_Mode_Normal);break;
case btl_666k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_4tq,CAN_BS2_4tq,6,CAN_Mode_Normal);break;
case btl_800k :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_5tq,CAN_BS2_3tq,5,CAN_Mode_Normal);break;
case btl_1M :CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,6,CAN_Mode_Normal);break;
}
}
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);//ʹÄÜPORTAʱÖÓ
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//ʹÄÜCAN1ʱÖÓ
GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
GPIO_InitStructure.GPIO_Pin = CAN_HIGH;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍì
GPIO_Init(CAN_GPIO, &GPIO_InitStructure); //³õʼ>>¯IO
GPIO_InitStructure.GPIO_Pin = CAN_LOW;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//ÉÏÀÊäÈë
GPIO_Init(CAN_GPIO, &GPIO_InitStructure);//³õʼ>>¯IO
//CANµ¥ÔªÉèÖÃ
CAN_InitStructure.CAN_TTCM=DISABLE; //·Çʱ¼ä´¥·¢Í¨ÐÅģʽ //
CAN_InitStructure.CAN_ABOM=ENABLE; //Èí¼þ×Ô¶¯ÀëÏß¹ÜÀí //
CAN_InitStructure.CAN_AWUM=DISABLE; //˯Ãßģʽͨ¹ýÈí¼þ>>½ÐÑ(Çå³ýCAN->MCRµÄSLEEPÎ>>)//
CAN_InitStructure.CAN_NART=ENABLE; //½ûÖ¹±¨ÎÄ×Ô¶¯´<<ËÍ //
CAN_InitStructure.CAN_RFLM=DISABLE; //±¨ÎIJ>>Ëø¶¨,еĸ²¸Ç¾ÉµÄ //
CAN_InitStructure.CAN_TXFP=DISABLE; //ÓÅÏȼ¶Óɱ¨Îıêʶ·û¾ö¶¨ //
CAN_InitStructure.CAN_Mode= mode; //ģʽÉèÖ㺠mode:0,ÆÕͨģʽ;1,>>Ø>>·Ä£Ê½; //
//ÉèÖò¨ÌØÂÊ
CAN_InitStructure.CAN_SJW=tsjw; //ÖØÐÂͬ²½ÌøÔ¾¿í¶È(Tsjw)Ϊtsjw+1¸öʱ¼äµ¥Î>> CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1¸öʱ¼äµ¥Î>>CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1¸öʱ¼äµ¥Î>>CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=brp; //·ÖƵϵÊý(Fdiv)Ϊbrp+1 //
CAN_Init(CAN1, &CAN_InitStructure); // ³õʼ>>¯CAN1
CAN_FilterInitStructure.CAN_FilterNumber=0; //¹ýÂËÆ÷0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32Î>>
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32Î>>ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32Î>>MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//¹ýÂËÆ÷0¹ØÁªµ½FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //¼¤>>î¹ýÂËÆ÷0
CAN_FilterInit(&CAN_FilterInitStructure);//Â˲¨Æ÷³õʼ>>¯
#if CAN_RX0_INT_ENABLE
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0ÏûÏ¢¹ÒºÅÖжÏÔÊÐí.
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // Ö÷ÓÅÏȼ¶Îª1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // ´ÎÓÅÏȼ¶Îª0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
return 0;
}
采集及发送部分:
cpp
#define STD_ID_PID (0x1020>>5)//0x0081
#define STD_ID_BASE (0x2020>>5)//0x0101
#define STD_ID_LONG (0x4020>>5)//0x0201
#define STD_ID_LAT (0x8020>>5)//0x0401
while(1)
{
if(sys_timer._1s_beat){//todo 1s freq things
bme280GetData(&rel_data.bmp280_press,&bmp280_temper,&bmp280_humidity,&bmp280_asl);
Analysis_GPS();
SHT30_Read_Humiture(&sht30_temp,&sht30_humidity);
rel_data.area_temper = sht30_temp*1.0f/10;
rel_data.area_humi = sht30_humidity*1.0f/10;
//>>ù±¾ÐÅÏ¢·¢ËÍ
can_buff[0] = ((STD_ID_BASE&0xff00)>>8);
can_buff[1] = ((STD_ID_BASE&0x00ff)>>0);
can_buff[2] = (sht30_temp&0xff00)>>8;//ζÈ
can_buff[3] = (sht30_temp&0x00ff)>>0;
can_buff[4] = (sht30_humidity&0xff00)>>8;//ʪ¶È
can_buff[5] = (sht30_humidity&0x00ff)>>0;
can_buff[6] = ((u16)rel_data.bmp280_press&0xff00)>>8;//´óÆøѹ
can_buff[7] = ((u16)rel_data.bmp280_press&0x00ff)>>0;
can_buff[8] = 0x00;
can_buff[9] = 0x00;
Can_Send_Msg(can_buff,sizeof(can_buff));
//¾¶ÈÐÅÏ¢·¢ËÍ
can_buff[0] = ((STD_ID_LONG&0xff00)>>8);
can_buff[1] = ((STD_ID_LONG&0x00ff)>>0);
memcpy(&can_buff[2],(void *)&rel_data.longitude,sizeof(double));
Can_Send_Msg(can_buff,sizeof(can_buff));
//γ¶ÈÐÅÏ¢·¢ËÍ
can_buff[0] = ((STD_ID_LAT&0xff00)>>8);
can_buff[1] = ((STD_ID_LAT&0x00ff)>>0);
memcpy(&can_buff[2],(void *)&rel_data.latitude,sizeof(double));
Can_Send_Msg(can_buff,sizeof(can_buff));
sys_timer._1s_beat = false;
}
if(sys_timer._500ms_beat){//todo 500ms freq things
sys_timer._500ms_beat = false;
}
if(sys_timer._50ms_beat){
Get_Adc_Num();
adc_buf[adc_cnt++] = rel_data.adc_val;
if(adc_cnt==4){//Íê³ÉÒ>>°ü£¬´ò°ü·¢×ß-ͳÒ>>°´ÕÕ´ó¶ËÐò
can_buff[0] = ((STD_ID_PID&0xff00)>>8);
can_buff[1] = ((STD_ID_PID&0x00ff)>>0);
can_buff[2] = (adc_buf[0]&0xff00)>>8;
can_buff[3] = (adc_buf[0]&0x00ff)>>0;
can_buff[4] = (adc_buf[1]&0xff00)>>8;
can_buff[5] = (adc_buf[1]&0x00ff)>>0;
can_buff[6] = (adc_buf[2]&0xff00)>>8;
can_buff[7] = (adc_buf[2]&0x00ff)>>0;
can_buff[8] = (adc_buf[3]&0xff00)>>8;
can_buff[9] = (adc_buf[3]&0x00ff)>>0;
Can_Send_Msg(can_buff,sizeof(can_buff));
adc_cnt = 0;
}
sys_timer._50ms_beat = 0;
}
}
u8 Can_Send_Msg(u8* msg,u8 len)
{
u8 mbox;
u16 i=0;
CanTxMsg TxMessage;
TxMessage.StdId=msg[0]<<8|msg[1]; // ±ê×¼±êʶ·û 11Î>>
TxMessage.ExtId=1; // ÉèÖÃÀ©Õ¹±êʾ·û
TxMessage.IDE=CAN_Id_Standard; // ±ê×¼Ö¡
TxMessage.RTR=CAN_RTR_Data; // Êý¾ÝÖ¡
TxMessage.DLC=8; // Òª·¢Ë͵ÄÊý¾Ý³¤¶È
for(i=0;i<8;i++)
TxMessage.Data[i]=msg[i+2];
mbox= CAN_Transmit(CAN1, &TxMessage);
i=0;
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //µÈ´ý·¢ËͽáÊø
if(i>=0XFF)
return 1;
return 0;
}
接收中断处理部分,此处没做帧ID过滤设置,没做接收数据处理设置:
cpp
CanRxMsg RxMessage;
void USB_LP_CAN1_RX0_IRQHandler(void)
{
uint8_t i;
CAN_Receive(CAN1, 0, &RxMessage);
if(RxMessage.StdId>>8==0x01){
paramx_can.Rev_ID = RxMessage.StdId & 0xFF;
switch(RxMessage.Data[0]){
default:break;
}
}
}
运行效果如下:
AD数据帧,1s发送5次,间隔200ms,一包包含4个数据,正好是50ms采集一次