当前位置:   article > 正文

CAN_TxStatus_Pending报错问题

CAN_TxStatus_Pending报错问题

        最近用STM32F407最小电路板测试CAN通讯遇到点小问题:回环模式测试没有问题的基础上,两块相同的最小系统板之间也可以通讯。但把其中一块板子换成USB转CAN分析仪时(或者其他板子),怎么也调不通。

        思考良久,硬件测试正常,没找到问题。逼得没办法,将CANH和CANL接到滤波器(此时在两块STM32F407最小系统板之间正常收发信息),测试波特率,才找到根源:不知什么时候,将外部时钟的系统频率由336MHz调成了360MHz,结果就导致CAN一直发送失败...

详情如下:

CAN.h代码:

  1. #ifndef __CAN1_H
  2. #define __CAN1_H
  3. #include "stm32f4xx.h" // Device header
  4. void CAN1_Init(void);
  5. void CAN1_SetMsg(CanTxMsg* Send_CAN1_Msg);
  6. void CAN1_Send(CanTxMsg* TxMessage);
  7. void CAN1_RX0_IRQHandler(void);
  8. #endif

CAN.c代码

  1. #include "CAN1.h"
  2. // CAN1_RX PA11
  3. // CAN1_TX PA12 APB1总线 42MHz
  4. extern CanRxMsg Recv_CAN1_Msg;
  5. uint8_t t = 6;
  6. void CAN1_Init(void)
  7. {
  8. //开启CAN1和GPIO时钟
  9. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
  10. RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
  11. //引脚复用为CAN1
  12. GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1);
  13. GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);
  14. //配置GPIO引脚
  15. GPIO_InitTypeDef GPIO_InitStructure;
  16. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
  17. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  18. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  19. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  20. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  21. GPIO_Init(GPIOA,&GPIO_InitStructure);
  22. //CAN1初始化配置
  23. CAN_InitTypeDef CAN_InitStructure;
  24. CAN_DeInit(CAN1);
  25. CAN_StructInit(&CAN_InitStructure);
  26. //CAN最大频率为1MHz。APB1频率为42MHz,波特率 = 42M/预分频/(1+BS1+BS2)
  27. //在本案例中,波特率 = 42M/6/(1+4+2) = 1M
  28. //如果想让波特率 = 500k,可以设置预分频为12,或者增加BS1和BS2的值
  29. CAN_InitStructure.CAN_Prescaler = 12; //预分频,APB1总线42MHz
  30. CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
  31. CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  32. CAN_InitStructure.CAN_SJW = CAN_SJW_2tq;
  33. CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; //CAN模式选择
  34. // CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;
  35. CAN_InitStructure.CAN_ABOM = ENABLE; //自动离线
  36. CAN_InitStructure.CAN_AWUM = ENABLE; //自动唤醒
  37. CAN_InitStructure.CAN_NART = DISABLE; //禁止自动重发送,消息只发送一次
  38. CAN_InitStructure.CAN_RFLM = DISABLE; //FIFO满了后,覆盖前一条
  39. CAN_InitStructure.CAN_TTCM = DISABLE; //时间戳。不需要时间戳
  40. CAN_InitStructure.CAN_TXFP = DISABLE; //发送FIFO优先级。按照请求的时间,不是标识符
  41. CAN_Init(CAN1,&CAN_InitStructure);
  42. //CAN过滤器配置
  43. CAN_FilterInitTypeDef CAN_FilterInitStructure;
  44. CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //是否激活筛选器
  45. CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
  46. //参考CAN 发送邮箱标识符寄存器 (CAN_TIxR),最低三位是功能码,所以需要左移3bit
  47. CAN_FilterInitStructure.CAN_FilterIdHigh = ((((uint32_t)0x199 << 3 )| CAN_ID_STD | CAN_RTR_DATA)&0xFFFF0000)>>16;
  48. CAN_FilterInitStructure.CAN_FilterIdLow = (((uint32_t)0x199 << 3 )| CAN_ID_STD | CAN_RTR_DATA)&0xFFFF;
  49. CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
  50. CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
  51. CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; //工作在掩码模式
  52. CAN_FilterInitStructure.CAN_FilterNumber = 8; //设置筛选器的编号,0~13
  53. CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; //筛选器的尺寸
  54. CAN_FilterInit(&CAN_FilterInitStructure);
  55. //配置CAN中断
  56. CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
  57. //中断配置
  58. NVIC_InitTypeDef NVIC_InitStructure;
  59. NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  60. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  61. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  62. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  63. NVIC_Init(&NVIC_InitStructure);
  64. }
  65. //设置要发送的数据
  66. void CAN1_SetMsg(CanTxMsg* Send_CAN1_Msg)
  67. {
  68. if(t>9)
  69. t = 6;
  70. Send_CAN1_Msg->ExtId = 0; //此处采用标准报文格式,因此不用给ExtId赋值
  71. Send_CAN1_Msg->IDE = CAN_ID_STD;
  72. Send_CAN1_Msg->RTR = CAN_RTR_DATA;
  73. Send_CAN1_Msg->StdId = 0x199; //设置标准ID为0x1314
  74. Send_CAN1_Msg->DLC = 8;
  75. for(uint8_t i = 0;i<8;i++)
  76. {
  77. Send_CAN1_Msg->Data[i] = t+i;
  78. }
  79. t++;
  80. }
  81. void CAN1_RX0_IRQHandler(void)
  82. {
  83. if(CAN_GetITStatus(CAN1,CAN_IT_FMP0) == SET)
  84. {
  85. //接收数据后,系统会自动清除中断标志位。
  86. //如果没有接收函数,中断标志位一直保持为1,导致程序卡死
  87. CAN_Receive(CAN1,CAN_FIFO0,&Recv_CAN1_Msg);
  88. }
  89. //不用单独清除标志位。CAN_ClearITPendingBit函数没有CAN_IT_FMP0这个变量
  90. // CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
  91. }

main.c代码

  1. #include "stm32f4xx.h" // Device header
  2. #include "Delay.h"
  3. #include "CAN1.h"
  4. CanTxMsg Send_CAN1_Msg;
  5. CanRxMsg Recv_CAN1_Msg;
  6. uint8_t Mail_Box = 0;
  7. int main(void)
  8. {
  9. //NVIC为内核中断,函数在misc.c和misc.h文件中
  10. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  11. CAN1_Init();
  12. CAN1_RX0_IRQHandler();
  13. while(1)
  14. {
  15. //设置要发送的数据
  16. CAN1_SetMsg(&Send_CAN1_Msg);
  17. //获取发送的邮箱号。如果没有空的邮箱,返回CAN_TxStatus_NoMailBox
  18. Mail_Box = CAN_Transmit(CAN1,&Send_CAN1_Msg);
  19. if(Mail_Box != CAN_TxStatus_NoMailBox)
  20. {
  21. //检测发送状态,一直等到发送成功
  22. while(CAN_TransmitStatus(CAN1,Mail_Box) != CAN_TxStatus_Ok);
  23. //此处延时是为了让CAN收发器将收到的数据转换为电平,传送到总线
  24. delay_ms(1000);
  25. }
  26. else
  27. return 0;
  28. //此处延时只是单纯防止发送过快
  29. delay_ms(1000);
  30. }
  31. }

起初,代码运行时出现的问题:每次运行,都会卡在

while(CAN_TransmitStatus(CAN1,Mail_Box) != CAN_TxStatus_Ok);这一行,经检测,CAN_TransmitStatus(CAN1,Mail_Box)函数的返回值是CAN_TxStatus_Pending,也就是发送不成功

于是怀疑是代码有问题。调成回环模式测试,正常,用两个相同的板子测试,也是正常的

但每次接到USB转CAN分析仪就卡住,差点以为是分析仪坏掉了。于是用STM32F107板子写了个代码测试,也会卡住。猜测是波特率对不上,导致发送错误,于是用示波器测试频率(方法:将CANH接到示波器探头,将CANL接到示波器地端。按自动检测按钮。注意需要把程序中的两个延时注释掉),果然和计算数值不对。按照上面的计算,波特率应该是500kHz,实测是541.6KHz。

查stm32f4xx.h文件,HSE_VALUE数值和实际晶振相同

于是逐个检查system_stm32f4xx.c文件中的各个参数,最终发现,PLL_N的数值不知什么时候被改成了360

(检查方法,双击选中,右键,点击Go To Definition Of "PLL_N",调到PLL_N定义处)

一时大意,搞得这么麻烦,吸取教训了...

(以上代码亲测有效,供大家参考。芯片是stm32f407zgt6,外部晶振8MHz)

整体接线

USB转CAN分析仪,通电后,红灯亮起,如果通讯成功,绿灯+红灯同时亮,如上图(红灯小,拍不出来)

USB转CAN分析仪的软件界面以及通讯结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/802533
推荐阅读
相关标签
  

闽ICP备14008679号