STM32F412 精简版本 功能完整。来说一下CAN外设的配置以及收发。
HAL库发展到现在BUG越来越少,大大减少了用户的开发量,但是缺点明显,代码量庞大。效率不高。
配置CAN总线首先要明确APB1的外设时钟,通过APB1的时钟来选择CAN的波特率。
BaudRate = APBCLK/BRP*(1+BS1+BS2);
BaudRate为CAN总线上的波特率。
配置CAN总线有以下几个注意事项:
1.CAN_HandleTypeDef中的AutoBusOff 参数为自动离线管理。
当错误帧超过255的时候就会离线,设置此参数ENABLE 就可以在总线挂起时清零重新ongoing。
2. CAN_FilterTypeDef 中的SlaveStartFilterBank 为从过滤器配置,用来选择从过滤器的寄存器号
当选择双CAN模式的时候,这个参数要跟CAN2的filternumber 一致。
CAN启动过程需要如下几个函数
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs);
CAN发送的时候需要如下函数:
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);
注意一下最后一个参数 uint32_t *pTxMailbox ,这个pTxMailbox 在头文件中为32位的无符号整型,需要强制转换为指针。
CAN接收的时候需要如下函数:
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
特别的一点最新的HAL库跟以前的CAN的配置不同,ST将接收发送的数据帧的数据部分分离出来,需要用户自己定义。
定义一个DLC长度的数组就可以,如下:
typedef struct
{
uint8_t Data[8];
}CAN_RecvMsg;
完整的启动过程:
初始化完毕之后
开启CAN:HAL_CAN_Start(&hcan1);
开启挂起中段允许:HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
发送数据:
void CAN_TRANSMIT(void)
{
TxMessage1.DLC=8;
TxMessage1.StdId=0x018;
TxMessage1.ExtId=0x00002018;
TxMessage1.IDE=CAN_ID_EXT;
TxMessage1.RTR=CAN_RTR_DATA;
uint8_t TR_BUF[8]="20180411";
if(HAL_CAN_AddTxMessage(&hcan1,&TxMessage1,TR_BUF,(uint32_t*)CAN_TX_MAILBOX0)!=HAL_OK)
{
printf("發送失敗");
}
}
接收数据:(双CAN,两个接收邮箱)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance==CAN1)
{
HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&RxMessage1,can_recvmsg.Data);
printf("\r\n%s",can_recvmsg.Data);
}
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance==CAN2)
{
HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO1,&RxMessage1,can_recvmsg.Data);
printf("\r\n%s",can_recvmsg.Data);
}
}
|