HAL库——CAN通信的中断接收

一:CAN协议基础

CAN:Controller Area Network,控制器局域网络。这方面的参考资料很多,不详细写了。说几个在开发过程的特点:

  • CAN总线上所有连接节点并没有地址的概念,通过发送数据中的标识符ID进行区分,多个单元同时发送消息时也通过标识符的优先级来仲裁优先发送方。
  • CAN总线的信号是通过两根信号线之间的电压差值来确定信号类型,显性电平对应逻辑0,隐形电平对应逻辑1。(这部分都是由硬件电路实现的)
  • CAN协议包括数据帧、遥控帧、错误帧、过载帧、间隔帧。重点关注数据帧,包括:帧起始、仲裁段、控制段、数据段、CRC段、ACK段、帧结束。
  • CAN通信是一种半双工、异步通信。       
                                                    

CAN的位时序,在手册上看到的解释如下:

“位时序逻辑将监视串行总线,执行采样并调整采样点,在调整采样点时,需要在起始位边沿进行同步并后续的边沿进行再同步” 

然而,CAN通信并不是同步通信,一开始看到同步的时候就有点不理解了。后来想了想,这里的同步说的是在进行信号的采样时,保证在该开始采样的位置启动采样,在结束位置完成采样,不会因为数据量过多,采样时出现相位偏移的问题。

位时序和CAN通信的波特率是相关联的,所以这部分是必须要理解的,主要有一下几个概念:

  • 位速率:发送单元在非同步情况下每秒钟发送的位数
  • 标准位包括4段:同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)、相位缓冲段2(PBS2);在STM32中分为3段:同步段(SYNC_SEG)、时间段1(BS1)、时间段2(BS2)。(*BS1=PTS+PBS1)
  • 1位分为4个段,每个段有若干个最小时间单位Tq组成
  • 波特率:每秒传输码元个数(注意和比特率的区别)
  • 位速率=1/波特率

HAL库——CAN通信的中断接收_第1张图片

图中,NominalBitTime表示位速率;BRP[9:0]存储分频器的值;时钟为APB1时钟。

二:CubeMX中相关配置

  • 选择芯片型号及封装类型
  • 配置RCC系统时钟,在Clock Configuration中可以在蓝色框中直接输入目标频率,回车后系统可以自动配置分频器和倍频器的值
  • 初始化CAN相关的参数并使能CAN的接收中断
  • 在NVIC中断向量中可以配置所有中断的优先级
  • 完成以上配置后,便可以在project manager中设置IDE类型,如果不能使用最新的固件库版本,记得不要勾选”use latest available version",选择已安装的固件库版本
  • 生成工程,完成! 

注:CubeMX不会生成CAN滤波器相关的初始化配置,需要在IDE中自己编写

三:keil MDK5中相关配置 

F4 V1.24.0版本固件库完成CAN接收中断的补充内容如下:

  • 由于CubeMX不会初始化过滤器,因此需要首先完成过滤器的配置 
void filter1_init(void)
{
	CAN_FilterTypeDef filter1;
	filter1.FilterBank=1;//滤波器编号
	filter1.FilterMode=CAN_FILTERMODE_IDMASK;//掩码模式
	filter1.FilterScale=CAN_FILTERSCALE_32BIT;
	filter1.FilterIdHigh=0x0000;
	filter1.FilterIdLow=0x0000;
	filter1.FilterMaskIdHigh=0x0000;
	filter1.FilterMaskIdLow=0x0000;
	filter1.FilterFIFOAssignment=CAN_FILTER_FIFO0;//FIFO0
	filter1.FilterActivation=ENABLE;
	
	if(HAL_CAN_ConfigFilter(&hcan1,&filter1)!=HAL_OK)
	{
		Error_Handler();
	}
}

 

  • 相关初始化,启动CAN1
void can1_start(void)
{
	MX_CAN1_Init();//CAN参数初始化
	filter1_init();//滤波器初始化
        HAL_CAN_Start(&hcan1);//启动CAN1
	HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);//使能中断
      
	
}
  • 编写中断回调函数(驱动文件中有默认的回调弱函数,函数名称保持一致)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance==CAN1)
	{
		HAL_CAN_GetRxMessage(&hcan1,CAN_FILTER_FIFO0,&rxheader1,msg);//获取数据
	}

}

这部分的函数和以往版本固件库的函数差别很大,接收数据的数组msg不再是之前放在结构体中,不需要自己定义,而是完全交给开发者自定义,函数的参数变化也很大,具体的内容可以查看驱动文件的说明。


以上基本完成了CubeMX没有帮我们做的事情,从这个例程可以看出hal库+CubeMX的强大。


另外,再说一下,实现CAN中断接收的程序执行过程:

  • FIFO 0 挂起中断触发中断请求: HAL_CAN_IRQHandler(&hcan1);
  • 判断中断类型,调用回调函数:HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
  • 回调函数的处理主要有两种方式:一种是立即执行读取FIFO数据,释放FIFO,不影响下次触发中断;另外一种是关闭CAN接收中断,之后读取FIFO数据,此时不会再触发接收中断。

注:CAN通信的接收也可以通过轮询的方式实现,在hal库的驱动文件中有对应的API可供调用


以上就是,我在做CAN中断接收数据的部分总结,有误的地方欢迎指正~~ 

你可能感兴趣的:(HAL库)