F103—固件库
配置
GPIO
参照示例程序。
中断
参照示例程序。
工作模式
参照示例程序。
过滤器
用于设置硬件过滤器,只有ID符合的数据才会进入邮箱。
发送
设置发送报文
void CAN_SetMsg(CanTxMsg *TxMessage)
{
uint8_t ubCounter = 0;
//TxMessage.StdId=0x00;
TxMessage->ExtId = 0x1314; //使用扩展ID
TxMessage->IDE = CAN_ID_EXT; //扩展模式
TxMessage->RTR = CAN_RTR_DATA; //发送内容为数据
TxMessage->DLC = 8; //数据长度8个字节
for (ubCounter = 0; ubCounter < 8; ubCounter++)
{
TxMessage->Data[ubCounter] = ubCounter; //设置发送的数据
}
}
此函数的主要作用是用来设置TxMessage,为库函数的发送做准备。
调用库发送函数
uint8_t CAN_Transmit(CAN_TypeDef *CANx, CanTxMsg *TxMessage)
分析一下此处的结构体CAN_TypeDef ,发送函数会自动选择空闲的发送邮箱进行消息的填充,然后设置ID、DLC、数据区,最后进行发送,在实际的应用中,我们只需要把TxMessage设置好,传给库函数即可。
typedef struct
{
__IO uint32_t MCR;
__IO uint32_t MSR;
__IO uint32_t TSR;
__IO uint32_t RF0R;
__IO uint32_t RF1R;
__IO uint32_t IER;
__IO uint32_t ESR;
__IO uint32_t BTR;
uint32_t RESERVED0[88];
CAN_TxMailBox_TypeDef sTxMailBox[3];
CAN_FIFOMailBox_TypeDef sFIFOMailBox[2];
uint32_t RESERVED1[12];
__IO uint32_t FMR;
__IO uint32_t FM1R;
uint32_t RESERVED2;
__IO uint32_t FS1R;
uint32_t RESERVED3;
__IO uint32_t FFA1R;
uint32_t RESERVED4;
__IO uint32_t FA1R;
uint32_t RESERVED5[8];
CAN_FilterRegister_TypeDef sFilterRegister[14];
} CAN_TypeDef;
接收
CAN信息的接收一般使用中断的方式
void CAN_RX_IRQHandler(void)
{
CAN_Receive(CANx, CAN_FIFO0, &RxMessage);//从邮箱中读取报文
//判断接收数据的ID
if((RxMessage.ExtId == 0x1314) && (RxMessage.IDE == CAN_ID_EXT) && (RxMessage.DLC == 8) )
{
flag = 1; //RxMessage.Data即接收的应用数据
}
else
{
flag = 0;
}
}
F427—HAL库
以横机机架板的CAN通讯为例,进行程序分层分析。
CAN的发送部分
先分析一下自行构建的结构体
typedef struct _CAN_MSG
{
UINT32 id;
UINT8 len;
UINT16 data[4];
} CAN_MSG;
根据此结构体构造的函数
CANx_SendNormalData(CAN_HandleTypeDef* hcan, CAN_MSG *smsg)
HAL库提供的函数需要填帧头、数据、邮箱编号,构建的函数入口参数更加简洁,自行构建的函数与超时判断的功能组合成上层的CAN发送函数。
CAN的接收部分
中断中调用HAL_CAN_GetRxMessage函数,将自行定义的结构体赋值,根据数据判断进行相应的操作,有些消息经过判断后来不及操作,这些消息会通过can_queue_push放入队列中,上层的CAN接收消息函数就是使用can_queue_pop弹出消息。
RT1052的fsl库
发送函数
u8 CAN2_Send_Msg(u8* msg,u8 len)
{
u8 ret=0;
can2_txframe.format=kFLEXCAN_FrameFormatStandard; //帧使用标准格式
can2_txframe.type=kFLEXCAN_FrameTypeData; //帧类型为数据帧
can2_txframe.id=FLEXCAN_ID_STD(can2_rxid); //标准ID
can2_txframe.length=len; //数据长度
//设置帧中的数据区域
can2_txframe.dataByte0=msg[0];
can2_txframe.dataByte1=msg[1];
can2_txframe.dataByte2=msg[2];
can2_txframe.dataByte3=msg[3];
can2_txframe.dataByte4=msg[4];
can2_txframe.dataByte5=msg[5];
can2_txframe.dataByte6=msg[6];
can2_txframe.dataByte7=msg[7];
//调用库中的发送函数
if(FLEXCAN_TransferSendBlocking(CAN2,TX_BUFFER_NUM,&can2_txframe)==kStatus_Success)
ret=0;
else ret=1;
return ret;
}
接收函数
void CAN2_IRQHandler(void)
{
if (FLEXCAN_GetMbStatusFlags(CAN2, 1 << RX_BUFFER_NUM)) //判断邮箱缓冲区是否收到数据
{
FLEXCAN_ClearMbStatusFlags(CAN2, 1 << RX_BUFFER_NUM); //清除中断标志
FLEXCAN_ReadRxMb(CAN2, RX_BUFFER_NUM, &can2_rxframe); //读取数据
can2_rxcomplete = true; //设置标志位
}
__DSB();
}
自行设计一个接收函数,将消息帧数据中的应用数据提取到自定义的buffer中。
u8 CAN2_Receive_Msg(u8 *buf)
{
u8 datalen = 0;
if(can2_rxcomplete == true)
{
can2_rxcomplete = false;
buf[0] = can2_rxframe.dataByte0;
buf[1] = can2_rxframe.dataByte1;
buf[2] = can2_rxframe.dataByte2;
buf[3] = can2_rxframe.dataByte3;
buf[4] = can2_rxframe.dataByte4;
buf[5] = can2_rxframe.dataByte5;
buf[6] = can2_rxframe.dataByte6;
buf[7] = can2_rxframe.dataByte7;
datalen = can2_rxframe.length;
}
else
{
datalen = 0;
}
return datalen;
}