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

对GPIO口进行设置

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

static void CAN2_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;/*外设时钟设置*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);//#define GPIO_Remap_CAN2             ((uint32_t)0x00200040) GPIO_PinRemapConfig(GPIO_Remap_CAN2, DISABLE);   //复用功能
/* Configure CAN pin: RX */                                           GPIO_InitStructure.GPIO_Pin   = CANRX2_PORTBIT;GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;                // 上拉输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(CANRX2_PORT, &GPIO_InitStructure);/* Configure CAN pin: TX  */                                                 GPIO_InitStructure.GPIO_Pin   = CANTX2_PORTBIT;GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;             // 复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_Init(CANTX2_PORT, &GPIO_InitStructure);
}

设置中断优先级

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

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

模式配置

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

static void CAN2_Mode_Config(void)
{CAN_InitTypeDef        CAN_InitStructure;/************************CAN通信参数设置**********************************//*CAN寄存器初始化*/CAN_DeInit(CAN2);CAN_StructInit(&CAN_InitStructure);/*CAN单元初始化*/CAN_InitStructure.CAN_TTCM=DISABLE;               //MCR-TTCM  时间触发通信模式使能CAN_InitStructure.CAN_ABOM=ENABLE;               //MCR-ABOM  自动离线管理 CAN_InitStructure.CAN_AWUM=ENABLE;              //MCR-AWUM  自动唤醒模式CAN_InitStructure.CAN_NART=DISABLE;              //MCR-NART  禁止报文自动重传   DISABLE-自动重传CAN_InitStructure.CAN_RFLM=DISABLE;             //MCR-RFLM  接收FIFO 锁定模式  DISABLE-溢出时新报文会覆盖原有报文  CAN_InitStructure.CAN_TXFP=ENABLE;             //MCR-TXFP  发送FIFO优先级 DISABLE-优先级取决于报文标示符 CAN_InitStructure.CAN_Mode =CAN_Mode_Normal;   //正常发送模式/* CAN 波特率 = RCC_APB1Periph_CAN / Prescaler / (SJW + BS1 + BS2);SJW = synchronisation_jump_width BS = bit_segment本例中 RCC_APB1Periph_CAN = 28MHZ     设置CAN波特率为125KbpsCAN 波特率 = 28 / 16 / (1 + 11 + 2) / = 125Kbps*/CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;CAN_InitStructure.CAN_Prescaler = 16;CAN_Init(CAN2, &CAN_InitStructure);
}

工作方式

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;          //过滤器组0CAN_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 ;             //过滤器被关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;         //使能过滤器CAN_FilterInit(&CAN_FilterInitStructure);/*CAN通信中断使能*/CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);}

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

应用层的接收和发送

1、发送
在接收到完整的数据包并按照要求解析数据打包好应答数据包时,可以通过库函数进行发送

if(  ucCmd == OK ){i=CAN_Transmit(CAN1, &TxMessage);   if((CAN_TransmitStatus( CAN1,i) == CAN_TxStatus_Failed )){ucCmd = CAN_TransmitStatus( CAN1,i);}  }

2、接收
接收处理直接在中断函数中进行


void CAN2_RX0_IRQHandler(void) //USB_LP_CAN2_RX0_IRQHandler(void)
{CAN_Receive(CAN2, CAN_FIFO0, &Rx2Message);CAN2_RX_FLAG=1;     //设置的接收完成标志,再上层的应用解析函数根据这个位去解析数据
}

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

  1. 单片机实验——十六路抢答器 ,抢答器是一种应用十分广泛的设备,在各种竞赛、抢答场合中,它能迅速、客观地分辨出最先获得发言权的选手。本设计采用矩阵键盘节省输入的I/O口,带有奇偶校验的双单片通信。

    1.实验内容与要求 抢答器是一种应用十分广泛的设备,在各种竞赛.抢答场合中,它能迅速.客观地分辨出最先获得发言权的选手.本设计采用矩阵键盘节省输入的I/O口,带有奇偶校验的双单片通信,确保发送的正确接 ...

  2. 自由口通信模式下计算机读写PLC存储区的程序

    自由口通信模式下计算机读写PLC存储区的程序 2008-8-20 8:51:00 来源: 摘 要:本文介绍了在自由口通信模式下,用计算机读写S7-200 PLC存储区内相邻的多个字节数据的通信程序设计 ...

  3. ubuntu c++检测usb口事件变化_拆解报告:美式双USBA口充电插座

    ----- 充电头网拆解报告 第1441篇 ----- 最近充电头网拿到了一款美式插座,这款产品相比常规墙插插座,除了配有两个双脚AC插口外,还有两个USB-A接口,支持直接插上数据线即可为两台设备进 ...

  4. STC51-串口通信

    1 并行与串行基本通信方式 随着单片机系统的广泛应用和计算机网络技术的普及,单片机的通信功能愈来愈显得重要.单片机通信是指单片机与计算机或单片机与单片机之间的信息交换,通常单片机与计算机之间的通信我们 ...

  5. 20.串行口通信原理及操作流程

    c 第六章:串行口通信原理及操作流程 6.1并行与串行基本通行方式 单片机通信是指单片机与计算机或单片机与单片机之间的信息交换,后者的通信通常用的较多. 通信有并行和串行龄种方式,在单片机系统以及现代 ...

  6. 移动端与PHP服务端接口通信流程设计(基础版)

    为什么80%的码农都做不了架构师?>>>    针对 --->非开放性平台 --->公司内部产品 接口特点汇总: 1.因为是非开放性的,所以所有的接口都是封闭的,只对公司 ...

  7. android音频调制通讯,android音频口通信(一)——2FSK信号调制

    转载请注明文章出处和作者! 作者:大熊(Xandy) 一.前言 之前一直都在博客园混(地址:http://www.cnblogs.com/xl19862005),最近才搬家至CSDN,由于前几个月刚换 ...

  8. C# 操作并口类,并口通信

    c#已提供了串口通信组件SerialPort,但是C#并没有提供直接的并口通信组件,只好通过调用API来与并口通信 代码 1 using System; 2  using System.Runtime ...

  9. 串口通信 校验码_一文读懂S7-200 SMART自由口通信!

    学习S7-200 SMART时了解到,基于RS485接口可实现一下几种通信: 1)modbus RTU通信 2)PPI协议通信 3)USS协议通信 4)自由口通信 何为自由口通信呢? 前三种通信必须要 ...

最新文章

  1. 2022-2028年中国BOPET薄膜行业市场全景调查及投资前景预测报告
  2. unity 平移图片_Unity 两张背景的切换平移
  3. textarea 聚焦后边框_textarea焦点的用法实现获取焦点清空失去焦点提示效果
  4. ant-design-pro使用服务器数据接口代理配置
  5. 在laravel5.8中集成swoole组件----用协程实现的服务端和客户端(nginx配置篇章)
  6. mysql有dataguard吗_Oracle查看是否搭建DataGuard
  7. 047、JVM实战总结:高级工程师的硬核技能:JVM的Full GC日志应该怎么看?
  8. c++ post请求_Golang GinWeb框架5绑定请求字符串/URI/请求头/复选框/表单类型
  9. 这么多年被第三方接入坑的那些事。。。关于md5签名和sha1证书的坑
  10. TMS320C55x汇编语言编程
  11. 利用百度OCR实现验证码自动识别
  12. iOS NSURLSession
  13. SAP UI5 在 PC 端浏览器和移动设备使用摄像头进行条形码扫描的几种解决方案介绍
  14. 实习日记一:jdk的安装和环境变量配置,IDEA和mysql的安装
  15. 用c#实现简单的登录和注册功能
  16. 矩形波的傅里叶级数及代码
  17. cs224w(图机器学习)2021冬季课程学习笔记15 Frequent Subgraph Mining with GNNs
  18. C# System命名空间表
  19. 好看的菜单导航色彩搭配
  20. Calander 的小程序 简单日历的制作

热门文章

  1. 【ThreeJS基础教程-材质纹理篇】3.1 纹理知识进阶
  2. unity3D用什么语言开发好?
  3. 前端js、功能性工具插件网站(持续更新,欢迎分享)
  4. 用keras采用DCGAN网络生成三国群英传7的人物头像
  5. php 字符串编码方式转换,PHP 字符串编码的转换
  6. 计算机快捷方式后缀名,电脑快捷键-文件扩展名详解.doc
  7. ansible防火墙firewalld设置
  8. c语言单片机自动浇花系统,LLAKG:Arduino 自动浇花系统(第3集:C语言程序升级与功能优化)...
  9. ZJCTF-Triple Language Write up
  10. python -m pip install --upgrade pip更新pip报错终极解决方法