关于STM32F105 双CAN口通信的一些学习心得

在项目中用到stm32f105芯片,需要使用到两个CAN口进行通讯,以下是在运行调试过程中出现的问题以及一些解决方法和学习心得。

对GPIO口进行设置

在这里RX使用的是上拉输入,TX是推免输出。这里需要注意的是,在对外设时钟进行设置的时候需要考虑一下CAN口的主从模式。105芯片的CAN2口是从bxCAN,它不能直接的访问SRAM存储器。所以如果在项目中只需要使用CAN2的话,在进行GPIO口外设时钟设置的时候,需要将CAN1的时钟也使能。 如果两个CAN口都有使用到,那么在进行CAN2口设置的时候使能2口的外设时钟就可以了。

设置中断优先级

这里的设置就比较简单,没有什么需要特别注意的地方。设置中断通道、优先级以及子优先级,最后使能中断

    static void CAN_NVIC_Config(void)
    {
       	NVIC_InitTypeDef NVIC_InitStructure;
       /* Configure one bit for preemption priority */
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    	/* 中断设置 */
    	NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;	   //CAN1 RX0中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;			   //子优先级为2
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    }

模式配置

先对相关的寄存器进行初始化。这里主要提一下CAN_MODE以及波特率(CAN_SJW、CAN_BS1、CAN_BS2、CAN_Prescaler)设置时候的一些注意事项

工作方式

CAN口主要有以下几种工作方式,它们的特点如下:

  1. 正常模式(CAN_Mode_Normal):可以正常的接收和发送报文
  2. 环回模式(CAN_Mode_LoopBack):将CAN口发送的报文当做接收的报文并保存(如果可以通过接收过滤)在接收邮箱里。环回模式可以避免外部影响,用于自测试。
  3. 静默模式(CAN_Mode_Silent):可以正常的接收数据帧和远程帧,智能发出隐性位,而不能真正的发出报文。所以,静默模式通常用于分析CAN总线活动,而不会对总线造成影响。
  4. 环回静默模式(CAN_Mode_Silent_LoopBack):该模式可用于“热自测试”,像环回模式那样测试CAN口,但却不会影响CANTX和CANRX所连接的整个CAN系统。在环回静默模式下,CANRX引脚与CAN总线断开,同时CANTX引脚被驱动到隐性位状态

波特率设置

波特率的计算公式如下:
CAN 波特率 = RCC_APB1Periph_CAN / Prescaler / (SJW + BS1 + BS2);
RCC_APB1Periph_CAN是CAN控制器外设挂载的APB总线频率;
CAN_Prescaler是CAN预分频系数,设置范围为0-1024;
SJW一般固定为1;
注意以上参数任何一个都不能设为0,否则会乱

过滤器配置

  1. 过滤器号:STM32F105芯片复位后默认的0-13号过滤寄存器可以定向到CAN1的 FIFO1或者FIFO0,14-17号定向到CAN2的FIFO1或者FIFO0
  2. 过滤模式分为两种。IDMask(标识符屏蔽位模式),特点是不够精准有时候不期望的ID也会通过过滤器,但是允许通过的ID个数会比较多最多无上限;IDList(标识符列表屏蔽模式),特点是可以精准的过滤ID但是数量有限。以下是本人根据CAN2配置的一个过滤器的例程:

  void CAN2_Filter_Config(void)
     {
     
        uint32_t ExtIdArray[4]={ 0x12040080 , 0x12040081 , 0x12000080 , 0x12000081 };
        CAN_FilterInitTypeDef  CAN_FilterInitStructure;
        uint32_t Mask =0 , temp=0 , i=0;
     	/*CAN过滤器初始化*/
        /* STM32F105复位后默认的0-13号过滤寄存器可以定向到CAN1的FIFO0或FIFO1,14-17号定向到CAN2的FIFO0或FIFO1*/
     	CAN_FilterInitStructure.CAN_FilterNumber = 14;			//过滤器组0
        CAN_FilterInitStructure.CAN_FilterMode   =  CAN_FilterMode_IdMask;	//工作在标识符屏蔽位模式
     	CAN_FilterInitStructure.CAN_FilterScale  = CAN_FilterScale_32bit;	//过滤器位宽为单个32位。
     	/* 使能报文标示符过滤器按照标示符的内容进行比对过滤,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */
 
     CAN_FilterInitStructure.CAN_FilterIdHigh= ( (ExtIdArray[0]<<3)&0xFFFF0000 )>>16 ;				//要过滤的ID高位 
     CAN_FilterInitStructure.CAN_FilterIdLow= ((ExtIdArray[0]<<3) |CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位 
     //计算屏蔽码,ExtIdArray[0]为验证码
     Mask = 0x1FFFFFFF;
     for( i=0;i<4;i++)
     {
         temp = ExtIdArray[i]^(~ExtIdArray[0]);
         Mask &= temp;
     }
     Mask <<=3;
     //计算出的 Mask中置1的位表示与ExtIdArray[0]一样,置0的位表示不关心
     CAN_FilterInitStructure.CAN_FilterMaskIdHigh= (Mask>>16)&0xFFFF;			//过滤器高16位每位必须匹配 
     CAN_FilterInitStructure.CAN_FilterMaskIdLow= Mask&0xFFFF;			//过滤器低16位每位必须匹配
 	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;				//过滤器被关联到FIFO0
 	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能过滤器
 	CAN_FilterInit(&CAN_FilterInitStructure);
 	/*CAN通信中断使能*/
 	CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);
 }

这只是针对位屏蔽,过滤拓展帧的一个例程,更详细的知识点,可以参照下面这位博主写的博客
https://blog.csdn.net/bonson2004/article/details/68942442

你可能感兴趣的:(关于STM32F105 双CAN口通信的一些学习心得)