CAN 使用示例
一、回环测试
例程路径:ls_sdk\examples\peripheral\can\CAN_LoopBack
1.1、功能说明
本示例演示了如何使用单个开发板来验证CAN收发功能。回环模式下,芯片自发自收,可以通过逻辑分析仪抓取到 CAN_TX 引脚输出的波形,CAN_RX 不会接收外部输入的信号。
硬件上面 CAN_TX\CAN_RX 悬空即可,不需要接其它任何器件。
1.2、软件配置
初始化IO
void pinmux_bxcan_init(uint8_t txd,uint8_t rxd);
配置CAN外设的工作模式、位时序以及波特率
static void CAN_Mode_config(void) { Can_Handle.Instance = BXCAN; Can_Handle.pTxMsg = &TxMessage; Can_Handle.pRxMsg = &RxMessage; //关闭时间触发通信模式使能 Can_Handle.Init.TTCM = DISABLE; //自动离线管理 Can_Handle.Init.ABOM = ENABLE; //使用自动唤醒模式 Can_Handle.Init.AWUM = ENABLE; //禁止报文自动重传 DISABLE-打开自动重传 Can_Handle.Init.NART = DISABLE; //接收 FIFO 锁定模式 DISABLE-溢出时新报文会覆盖原有报文 Can_Handle.Init.RFLM = DISABLE; //发送 FIFO 优先级 DISABLE-优先级取决于报文标示符 Can_Handle.Init.TXFP = DISABLE; //使用回环模式 Can_Handle.Init.Mode = CAN_MODE_LOOPBACK; //重新同步跳跃宽度1个时间单元 Can_Handle.Init.SJW = CAN_SJW_1TQ; /* ss=1 bs1=4 bs3=3 位时间宽度为 (1+4+3)=8tq */ //时间段1占用了4个时间单元 Can_Handle.Init.BS1 = CAN_BS1_4TQ; //时间段2占用了2个时间单元 Can_Handle.Init.BS2 = CAN_BS2_3TQ; //分频系数配成7,实际为(7+1)=8分频 Can_Handle.Init.Prescaler = 7; /* CAN的时钟频率为 SDK_HCLK_MHZ/2=32MHz, CAN波特率:32/(1+4+3)/(7+1) = 500 Kbps*/ if(HAL_CAN_Init(&Can_Handle) != HAL_OK) { LOG_I("CAN INIT ERROR"); while(1); } }
配置筛选器的工作方式
static void CAN_Filter_Config(void)
{
CAN_FilterConfTypeDef CAN_FilterInitStructure = {0};
uint32_t flt_id = 0;
//使用筛选器组0
CAN_FilterInitStructure.FilterNumber = 0;
//工作在掩码模式
CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDLIST;
//筛选器位宽为单个32位
CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
//配置要筛选的ID
flt_id = CAN_Fill_32Bit_FilterId(CAN_ID,CAN_IDE,CAN_RTR_DATA);
//要筛选的ID高16位
CAN_FilterInitStructure.FilterIdHigh = (flt_id & 0xFFFF0000) >> 16;
//要筛选的ID低16位
CAN_FilterInitStructure.FilterIdLow = flt_id & 0xFFFF;
//筛选器高16位每位必须匹配
CAN_FilterInitStructure.FilterMaskIdHigh = 0xFFFF;
//筛选器低16位每位必须匹配
CAN_FilterInitStructure.FilterMaskIdLow = 0xFFFF;
//筛选器被关联到 FIFO0
CAN_FilterInitStructure.FilterFIFOAssignment = CAN_FILTER_FIFO0;
//使能筛选器
CAN_FilterInitStructure.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&Can_Handle, &CAN_FilterInitStructure);
}
设置发送的报文
按照接收筛选的要求,填写好需要发送的报文后,调用 HAL_CAN_Transmit_IT / HAL_CAN_Transmit 即可把该报文存储到发送邮箱,然后通过 CAN 外设发送出去。
接收报文
中断方式接收
提前通过调用 HAL_CAN_Receive_IT 来配置准备接收,当CAN接收的报文经过筛选器后会被存储到指定的FIFO中,并产生中断,应用上面会收到回调函数
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan) { uint32_t id_tmp = 0, ide_temp = 0, dlc_tmp = 0; ide_temp = hcan->pRxMsg->IDE; dlc_tmp = hcan->pRxMsg->DLC; if (ide_temp == CAN_ID_EXT) { id_tmp = hcan->pRxMsg->ExtId; } else { id_tmp = hcan->pRxMsg->StdId; } LOG_I("ID:0x%x,IDE:%d,DLC:%d", id_tmp, ide_temp, dlc_tmp); LOG_I("\r\nCAN IT RECV DATA:"); LOG_HEX(Can_Handle.pRxMsg->Data,8); Init_RxMes(); // 为接收下一包数据做好准备 HAL_CAN_Receive_IT(&Can_Handle, CAN_FIFO0); }
轮询方式接收
在需要接收数据的地方直接调用HAL_CAN_Receive即可,在接收完成的时候会返回HAL_OK。
1.3、下载验证
将编译好的程序下载到开发板,运行程序,查看输出的log,如果能看到打印出接收的数据,则表示测试通过。
二、双机通讯
例程路径:ls_sdk\examples\peripheral\can\CAN_Normal
2.1、功能说明
本示例演示了如何使用两块开发板进行CAN通讯。需要将芯片的CAN_TX 和CAN_RX两个引脚与CAN收发器相连,收发器使用CANH及CANL引脚连接到CAN总线网络中。
2.2、软件配置
与回环模式下的配置基本一致,只有模式不同
Can_Handle.Init.Mode = CAN_MODE_NORMAL;
2.3、下载验证
将编译好的程序下载到开发板,运行程序,查看输出的log,如果两块板子能看到打印出接收的数据,则表示测试通过。