文章目录

  • 背景知识
  • 修改说明
  • 修改一
    • 现象描述
    • 原因分析
    • 解决思路
    • 修改内容
    • 运行结果
  • 修改二
    • 现象描述
    • 原因分析
    • 解决思路
    • 修改内容
    • 运行结果
  • 修改三
    • 现象描述
    • 原因分析
    • 解决思路
    • 修改内容
    • 运行结果
  • 修改四
    • 现象描述
    • 原因分析
    • 解决思路
    • 修改内容
    • 运行结果
  • 修改五
    • 现象描述
    • 原因分析
    • 解决思路
    • 修改内容
    • 运行结果

背景知识

stm32f105芯片和gd32f305芯片都有2个内部CAN,stm32f105芯片是CAN1和CAN2,gd32f305芯片是CAN0和CAN1,stm32f105芯片的CAN1和gd32f305芯片的CAN0是对应关系,stm32f105芯片的CAN2和gd32f305芯片的CAN1是对应关系。

为了描述方便和避免误解,如果没有特殊说明,用CANa来表述stm32f105芯片的CAN1和gd32f305芯片的CAN0,用CANb来表述stm32f105芯片的CAN2和gd32f305芯片的CAN1。用stm代称stm32f105芯片,用gd代称gd32f305芯片。

stm和gd对CAN寄存器的命名完全不同,但是寄存器的地址排列次序是一致的,并且寄存器内部的字段位置也一致。比如:
stm的CAN 主控制寄存器 (CAN_MCR,地址偏移量: 0x00),包含字段RESET、TTCM、ABOM、AWUM、NART、RFLM、TXFP、SLEEP、INRQ。
gd的CAN 控制寄存器 (CAN_CTL,地址偏移量: 0x00),包含字段DFZ(新增)、SWRST、TTC、ABOR、AWU、ARD、RFOD、TFO、SLPWMOD、IWMOD。

修改说明

STM_HAL库版本:2016。
所有的代码修改都在// zyb begin 和 // zyb end之间。
目前的代码修改兼容stm和gd。

修改一

现象描述

使用gd芯片,程序调用stm32f1xx_hal_can.c的HAL_CAN_Init函数返回错误。

原因分析

stm和gd在初始化后,位CAN_MCR.SLEEP都默认为1。

HAL_CAN_Init函数在运行代码SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ)后,会等待位CAN_MSR.INAK置1,如果等待时间超时,则HAL_CAN_Init函数返回错误。

stm在位CAN_MCR.INRQ被置1后,位CAN_MSR.INAK不受位MCR.SLEEP影响,也被置1;而gd只有在位CAN_MCR.SLEEP为0时,位CAN_MCR.INRQ被置1后,位CAN_MSR.INAK才能被置1。

解决思路

在HAL_CAN_Init函数调用代码SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ)前清零MCR.SLEEP为0。

修改内容

在HAL_CAN_MspInit函数的最后加上代码:

CLEAR_BIT(canHandle->Instance->MCR, CAN_MCR_SLEEP);

或者在调用HAL_CAN_Init函数前,调用HAL_CAN_WakeUp函数。

运行结果

stm和gd都能够正常初始化CAN。

修改二

现象描述

gd在连续调用stm32f1xx_hal_can.c中的HAL_CAN_AddTxMessage函数发送2包数据时,只能发送第1包数据,第2包数据无法发送到CAN总线上。

原因分析

2个芯片的文档描述有不同。
stm的CAN发送状态寄存器CAN_TSR的邮箱号CODE[1:0]字段描述:
当有至少1个发送邮箱为空时,邮箱号为下一个空的发送邮箱号。
当所有的发送邮箱都为空时,邮箱号为优先级最低的那个发送邮箱号。

对应的gd的CAN发送状态寄存器 (CAN_TSTAT)的邮箱号NUM[1:0]字段描述:
当发送 FIFO 不满时,NUM 表示下一个将要发送的邮箱号。
当发送 FIFO 满时,NUM 表示最后一个将要发送的邮箱号。

查看STM_HAL库的HAL_CAN_AddTxMessage函数,相关代码为:
transmitmailbox = (tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos;
查看gd32库的can_message_transmit函数,相关代码为:

   if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){mailbox_number = CAN_MAILBOX0;}else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){mailbox_number = CAN_MAILBOX1;}else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){mailbox_number = CAN_MAILBOX2;}else{mailbox_number = CAN_NOMAILBOX;}

解决思路

修改STM_HAL库的HAL_CAN_AddTxMessage函数中处理CODE[1:0]字段的代码,调整为和gd32库的can_message_transmit函数中类似的代码。

修改内容

把代码

 transmitmailbox = (tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos;

修改为如下代码:

 if(CAN_TSR_TME0 == (tsr & CAN_TSR_TME0)){transmitmailbox = 0;}else if(CAN_TSR_TME1 == (tsr & CAN_TSR_TME1)){transmitmailbox = 1;}else if(CAN_TSR_TME2 == (tsr & CAN_TSR_TME2)){transmitmailbox = 2;}else{transmitmailbox = 3;}

运行结果

stm和gd都能够连续发送2包CAN数据。

修改三

现象描述

同样的代码,stm能够正常发送和接收can数据,但是gd的CANa能成功发送数据,却接收不到CAN总线上的数据。

原因分析

查看2个芯片的文档。stm的CAN过滤器寄存器CAN_FMR的字段CAN2SB[5:0]和gd的CAN过滤器控制寄存器CAN_FCTL的字段HBC1F[5:0],是对应关系。stm和gd的文档描述基本一致。

CAN_FMR.AN2SB[5:0]的描述:
CAN2(CANb)过滤器单元开始位置。
CAN2SB[5:0]=28d,所有过滤器都能被CAN1(CANa)使用。
CAN2SB[5:0]=0d,所有过滤器都不能被CAN1(CANa)使用。

CAN_FCTL.HBC1F[5:0]的描述:
CAN1(CANb)过滤器单元起始位置。
这些位用来定义CAN1(CANb)过滤器起始位置。CAN0(CANa)可以用编号为0HBC1F-1过滤器,CAN1(CANb)可以用编号为HBC1F27过滤器。当这些位的值为0,CAN0(CANa)将没有过滤器可以使用。当这些位的值为28时,CAN1(CANb)将没有过滤器可以使用。

使用stm调试程序时,发现CAN_FMR.CAN2SB[5:0]被置为0,按照文档描述,CANa将接收不到数据,但实际运行程序却可以接收到数据。

使用gd调试程序时,发现CAN_FCTL.HBC1F[5:0]被置为0,按照文档描述,CANa将接收不到数据,实际运行程序也接收不到数据。

继续调试程序,发现2个芯片在上电复位后,CAN_FMR.CAN2SB[5:0]和CAN_FCTL.HBC1F[5:0]的初始值都为14(0x0E)。

继续分析代码,发现在调用HAL_CAN_ConfigFilter函数前,没有对sFilterConfig1.SlaveStartFilterBank赋值,因为sFilterConfig1被定义为全局变量,所以sFilterConfig1.SlaveStartFilterBank = 0,导致调用HAL_CAN_ConfigFilter函数后CAN_FMR.CAN2SB[5:0]被置为0。

结论:stm芯片的行为和文档描述不相符,可能是stm芯片的bug。

解决思路

在调用HAL_CAN_ConfigFilter函数前,添加相关代码初始化sFilterConfig1.SlaveStartFilterBank为正确的值。

修改内容

在调用HAL_CAN_ConfigFilter函数前,添加如下代码:sFilterConfig1.SlaveStartFilterBank = 14;

运行结果

stm和gd都能够正常收发CANa数据。

修改四

现象描述

调整了“修改三”的部分代码后,发现gd不能正常收发CANb数据。

原因分析

原代码中,没有调用HAL_CAN_ConfigFilter函数配置CANb的过滤器,估计是CAN_FMR.CAN2SB[5:0]被正确配置后,影响到了CANb的默认过滤器。

解决思路

添加配置CANb过滤器的相关代码。

修改内容

添加配置CANb过滤器的相关代码,并且把sFilterConfig2.FilterBank赋值为15,表示使用过滤器15,和sFilterConfig2.SlaveStartFilterBank = 14相匹配。

运行结果

stm和gd都能够正常收发CANb数据。

修改五

现象描述

使用gd,原程序在连续调用stm32f1xx_hal_can.c中的HAL_CAN_AddTxMessage函数发送4包数据时,只能成功发送第1、2、4包数据,第3包数据无法发送到CAN总线上。

原因分析

原代码中,发现在调用HAL_CAN_AddTxMessage函数前,程序会调用HAL_CAN_IsTxMessagePending函数判断当前发送邮箱是否为空(通过CAN_TSR.TMEx是否为1来判断),如果不为空,则继续调用HAL_CAN_IsTxMessagePending函数判断,直到当前发送邮箱为空或者超时计数到0为止,超时计数值初始总数为200。如果最后超时计数值到0,则调用HAL_CAN_AbortTxRequest函数终止当前邮箱的数据发送。

代码如下(已做简化):

 UINT32 timeout = 200;while (HAL_CAN_IsTxMessagePending(&hcan1, dockTxMailBox) == TRUE && (timeout--)){if (timeout == 0){HAL_CAN_AbortTxRequest(&hcan1, dockTxMailBox);}}

使用stm调试,发现将超时计数值调整为<190,背板也出现和gd一样的情况,背板只能发送第1、2、4包数据;将超时计数值调整为190~300,程序会触发超时条件调用HAL_CAN_AbortTxRequest函数,但是能完整发送第1、2、3、4包数据;将超时计数值调整为>300,程序不会触发超时条件,说明当前邮箱的数据已经成功发送,也就不会调用HAL_CAN_AbortTxRequest函数终止当前邮箱的数据发送。

使用gd调试,发现将超时计数值调整为<255,背板只能发送第1、2、4包数据;将超时计数值调整为255~395,程序会触发超时条件调用HAL_CAN_AbortTxRequest函数,但是能完整发送第1、2、3、4包数据;将超时计数值调整为>395,程序不会触发超时条件,说明当前邮箱的数据已经成功发送,也就不会调用HAL_CAN_AbortTxRequest函数终止当前邮箱的数据发送。

根据上述分析和调试,得出异常原因:由于程序先判断当前发送邮箱是否为空和超时判断,条件满足再终止当前邮箱的数据发送,这个过程有一个时间差,就会出现如下描述的情况,在程序调用HAL_CAN_AbortTxRequest函数终止当前邮箱的数据发送前(通过置位CAN_TSR.ABRQx来终止),实际当前邮箱的数据正好刚刚发送完。使用stm,虽然程序会触发超时条件,但是因为上述情况,实际程序并没有真正的终止当前邮箱的数据发送,背板工作正常。使用gd,因为gd在同主频下的运行速度比stm快,原程序中200的超时计数值不能让程序在终止当前邮箱的数据发送前把数据完整的发送出去,也就是说HAL_CAN_AbortTxRequest函数起作用了,待发送的数据真正被终止了。

解决思路

原程序中的超时计数值200太小,刚好在临界范围内,根据测试的结果,使用gd超时计数值至少要设置成>400。

修改内容

在dcan_dock::can_tx_api函数中把UINT32 timeout = 200;修改成UINT32 timeout = 10000;
在dcan_pump2::can_tx_api函数中把UINT32 timeout = 500;修改成UINT32 timeout = 10000;
在canspi::transmit函数中把uint32_t timeout = 500;修改成uint32_t timeout = 10000;

这个修改并不完美,超时计数值没有考虑CAN波特率,芯片时钟频率和芯片厂家不同等因素。目前CAN使用的波特率是500kHz,考虑到以后可能会使用较小波特率,所以把超时计数定了个较大值10000。

运行结果

stm和gd都能够正常发送多包数据。

stm32f105移植到gd32f305笔记相关推荐

  1. 嵌入式算法移植优化学习笔记5——CPU,GPU,TPU,NPU都是什么

    嵌入式算法移植优化学习笔记5--CPU,GPU,TPU,NPU都是什么 一.什么是CPU? 二.什么是GPU? 三.什么是NPU? 四.什么是TPU? 附: 随着AI的广泛应用,深度学习已成为当前AI ...

  2. UCOS-II移植ARM的笔记

    UCOS-II移植ARM的笔记(转贴) UCOS-II的移植需要提供2,3个文件分别介绍如下: 一:OS_CPU.H 1 与编译器有关的数据类型 经典的全局变量定义,可以套用,简洁明了实用性好. #i ...

  3. wifi(rtl8188eu)移植及调试笔记

    /* * Dave/nova_wangwenbo@126.com */ wifi移植及调试笔记 一.rtl8188eu 1.修改设备树: 添加wifi ap电源控制引脚 WIFI,power_ap_g ...

  4. jz2440-uboot-201204版本移植【学习笔记】【原创】

    平台:jz2440 作者:庄泽彬(欢迎转载,请注明作者) 说明:韦东山二期视频学习笔记 交叉编译工具:arm-linux-gcc (GCC)4.3.2 PC环境:ubuntu18.04 一.uboot ...

  5. STM32F105 USART1/USART3 调试笔记

    由103系列向105系列移植 目录 由103系列向105系列移植 故障现象:USART1乱码 故障排除:时钟和外部晶振的适配调整 外部晶振配置 时钟配置 故障现象:USART3收发均无效 故障排除:端 ...

  6. STM32移植UCGUI3.90笔记

    在MDK环境下,终于将3.90版本的UCGUI移植到STM32下了,在网上看到的都是例程代码,很少看到有关于在STM32下移植UCGUI的教程方法,为了方便大家,特写此移植方法,大家可以借鉴(有错误之 ...

  7. HI3515海思开发板移植3G模块笔记

    硬件平台: 海思Hi3515 Linux 3G模块: 1.移动模块:ZTE M305(TD-SCDMA) 2.联通模块:HUAWEI EM770W(WCDMA) 3.电信模块:HUAWEI EM660 ...

  8. 关于MCU M4内核移植FreeRTOS的笔记

    本次使用华大HC32F460的MCU移植了FreeRTOS,使用的平台是IAR. 废话不多说,先来看看移植 需要的资源. 1.开发平台EWARM-CD-8401-21539. 2.IAR注册机. 3. ...

  9. 《全面掌握Linux C语言嵌入式系统移植教程》学习笔记(Liunx速查简明)

    全面掌握Linux C语言嵌入式系统移植教程学习笔记(Liunx速查简明) 笔记前言: P3: shell命令简明 P4: vi /vim编辑器入门 P5:vi /vim编辑器扩展 P8: gcc编译 ...

最新文章

  1. Hbase 技术细节笔记(上)
  2. 一台服务器能承载多少用户_一台入门级服务器能为你的办公应用带来哪些效率?评测告诉你...
  3. python 渗透框架_Python渗透测试框架:PytheM
  4. ++ba--运算结果解析
  5. 鼠标移入时闪闪发光的效果
  6. 使用反射获得jar包中的类、方法、参数、返回值类型,然后动态加载jar包运行方法
  7. mysql按日期查询数据_mysql按日期查询数据
  8. Java基础学习(3)-泛型
  9. python进行接口请求,第一个接口返回的数据作为第二个参数的入参
  10. 使用人工智能加快海底数据处理-从粗略过滤到精细智能数据筛选
  11. BUUCTF Reverse/findKey
  12. css 剪辑图片_css实现图片剪裁
  13. 教你用python制作证件照片啦学会再也不用跑去照相馆拍照了~
  14. 关于python程序格式框架以下选项中描述错误的是_关于Python程序格式框架的描述,以下选项中错误的是...
  15. 超神学院的宇宙天体计算机,正文 第一章:银河之力被一分为二
  16. 小试牛刀-利用AST平坦化一段瑞数代码
  17. helm create configmap error: ConfigMap in version “v1“ cannot be handled as a ConfigMap
  18. 交换机设备登录账号权限1_交换机上配置RADIUS登录认证
  19. 解决 Docker容器因 iptables无法启动的问题
  20. 充气娃娃什么感觉?Python 告诉你!

热门文章

  1. python统计中文字符数量
  2. 【NHOI2018】跳伞登山赛
  3. h5调用微信,微博等分享
  4. 免费临时邮箱,一次性邮箱
  5. Java毕设项目共享充电宝系统(java+VUE+Mybatis+Maven+Mysql)
  6. CSS实现水平垂直居中的方式有哪些?
  7. Ubuntu离线安装网卡驱动
  8. 【宏】【DEBUG宏】
  9. data单复数一样吗_data和datum谁是单数形式,谁是复数形式?
  10. php上传图片按钮不灵,ctrl键失灵怎么办