之前在调试stm32f4-CAN通信中,接收多个ID设备信息时,用到了阻塞比较,而未用到中断接收,这会导致系统中连接多个CAN设备时,程序中CAN接收数据大幅丢包的情况,因此后来更正了CAN中断接收部分程序,现记录如下:
volatile int can_complete=false;//接收完成中断
//结构体
typedef struct
{
u32 id;
u32 can_id;//can设备ID
int update;//数据是否有更新
u8 len;//数据长度
u8 data[8];//存储数据
}can_recieve_s;
//接收can设备数量
#define MAX_NUMBER 10
static can_recieve_s can_recieve[MAX_NUMBER]={0};
void CAN_MODE_INIT(//)
{
//
CAN底层配置
//
//can设备ID匹配
can_recieve[0].can_id=0x01;
can_recieve[1].can_id=0x02;
can_recieve[2].can_id=0x03;
can_recieve[3].can_id=0x04;
can_recieve[4].can_id=0x05;
can_recieve[5].can_id=0x06;
can_recieve[6].can_id=0x07;
can_recieve[7].can_id=0x08;
can_recieve[8].can_id=0x09;
can_recieve[9].can_id=0x0A;
//
for(i=0;i<MAX_NUMBER;i++)
{
can_recieve[i].update=0;
}
//
//安装can中断函数
//
}
//can接收中断函数
void ProcessIRQSrc_CAN1(void)
{
u8 index=0;
CanRxMsg RxMessage;
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据
for(index=0;index<MAX_NUMBER;index++)
{
if(RxMessage.StdId==can_recieve[index].can_id)
{
//数据有更新
can_recieve[index].update=1;
//填充数据
can_recieve[index].data[0]=RxMessage.Data[0];
can_recieve[index].data[1]=RxMessage.Data[1];
can_recieve[index].data[2]=RxMessage.Data[2];
can_recieve[index].data[3]=RxMessage.Data[3];
can_recieve[index].data[4]=RxMessage.Data[4];
can_recieve[index].data[5]=RxMessage.Data[5];
can_recieve[index].data[6]=RxMessage.Data[6];
can_recieve[index].data[7]=RxMessage.Data[7];
can_recieve[index].len=RxMessage.DLC;
break;
}
}
can_complete=true;//标记读取完成
}
//can接收读取函数,将接收的数据存储到*buf中,长度为*len,
//id为期望can设备ID。返回状态ret=1;接收失败 ret=0;接收成功
long can_read_id(u8 *buf , u16 *len , u32 id)
{
u8 datalen=0;
long ret=0;
u8 index=0;
//标准数据帧
CanRxMsg RxMessage;
RxMessage.IDE=CAN_ID_Standard;
RxMessage.RTR=CAN_RTR_Data;
//如果数据有更新
if(can_complete==true)
{
//遍历数组
for(index=0;index<MAX_NUMBER;index++)
{
if(id==can_recieve[index].can_id)
{
if( can_recieve[index].update==1)
{
datalen=can_recieve[index].len;
//填充数据,转移数据
buf[0]=can_recieve[index].data[0];
buf[1]=can_recieve[index].data[1];
buf[2]=can_recieve[index].data[2];
buf[3]=can_recieve[index].data[3];
buf[4]=can_recieve[index].data[4];
buf[5]=can_recieve[index].data[5];
buf[6]=can_recieve[index].data[6];
buf[7]=can_recieve[index].data[7];
//数据转移完毕
can_recieve[index].update=0;
ret=0;
}
else
{
//接收失败状态传递
datalen=0;
ret=1;
}
break;
}
}
can_complete=faule;//标记清零
}
else
{
//接收失败状态传递
datalen=0;
ret=1;
}
*len=datalen;
//返回ret
return ret;
}
应用以上CAN接收函数,在实际系统中,连接多个CAN设备,确实大幅减少了数据的丢包现象。即采用中断接收+读取函数的方式,可以很好地解决多级设备连接的数据接收问题。