[STM32F1] 同样的CAN通信代码,在103RC中正常,下载到103RB就不正常了。

[复制链接]
1971|4
 楼主| trouvan 发表于 2017-3-21 21:10 | 显示全部楼层 |阅读模式
同样的代码,在RC中,可以正常接收,进入中断。但RB中就死活进不去。
用的引脚都是PA11 PA12,看手册,在RC中和RB中这两个引脚都是一样的。CAN的收发引脚。

103RC是256KB的flash。
103RB是128KB的flash。

中断向量用的是:USB_LP_CAN1_RX0_IRQn,RC用的启动文件是hd.s,RB的启动文件用的md.s,hd.s都试过,也是不行。

实在是没招了,试了好几块RB的芯片,全部不行,一换RC的就好使。

完整代码 can.c
  1. #include "can.h"

  2. static void (*msg_rcv_callback)(CanRxMsg *can_rx_msg);
  3. static CanRxMsg g_can_rx_msg;
  4. can_callback_struct can_cb_array[256];

  5. /* 函数名:void can_init(void *)
  6. * 功能:can总线初始化
  7. * 参数:
  8. * 返回值:初始化成功则返回1
  9. */
  10. int can_init(int number)
  11. {
  12.     int i;
  13.        
  14.         int check_out_ID;
  15.     CAN_InitTypeDef can_init_struct;
  16.         CAN_FilterInitTypeDef can_FilterInitTypeDef;
  17.        
  18.     can_gpio_config();
  19.     CAN_DeInit(CANX);
  20.     CAN_StructInit(&can_init_struct);
  21.     can_init_struct.CAN_TTCM = DISABLE;  //非时间触发通信模式
  22.     can_init_struct.CAN_AWUM = DISABLE;  //睡眠模式通过软件唤醒
  23.     can_init_struct.CAN_ABOM = DISABLE;  //软件自动离线管理
  24.     can_init_struct.CAN_NART = DISABLE;   //禁止报文自动传送
  25.     can_init_struct.CAN_RFLM = DISABLE;  //报文不锁定,新的覆盖旧的
  26.     can_init_struct.CAN_TXFP = ENABLE;  //优先级由报文标识符决定
  27.     can_init_struct.CAN_Mode = CAN_MODE_X;     //模式设置
  28.     can_init_struct.CAN_SJW  = CAN_SJW_X;     //同步跳跃宽度
  29.     can_init_struct.CAN_BS1  = CAN_BS1_X; //范围CAN_BS1_1tq ~ CAN_BS1_16tq
  30.     can_init_struct.CAN_BS2  = CAN_BS2_X; //范围CAN_BS1_1tq ~ CAN_BS1_16tq
  31.     can_init_struct.CAN_Prescaler = CAN_PRESCALER_X;  //分频系数(Fdiv)CAN_PRESCALER_X + 1
  32.     CAN_Init(CANX,&can_init_struct);
  33.      

  34.         check_out_ID = number<<9;

  35.         can_FilterInitTypeDef.CAN_FilterNumber = 0;
  36.         can_FilterInitTypeDef.CAN_FilterMode = CAN_FilterMode_IdMask;
  37.         can_FilterInitTypeDef.CAN_FilterScale = CAN_FilterScale_32bit;
  38.         can_FilterInitTypeDef.CAN_FilterFIFOAssignment = CAN_FilterFIFO0;
  39.        
  40.         if(number != 0){
  41.                 can_FilterInitTypeDef.CAN_FilterMaskIdLow = 0x0000;
  42.                 can_FilterInitTypeDef.CAN_FilterMaskIdHigh = 0xF<<9;
  43.                 can_FilterInitTypeDef.CAN_FilterIdLow = 0x0000;
  44.                 can_FilterInitTypeDef.CAN_FilterIdHigh = check_out_ID;//屏蔽部分ID
  45.         }else{
  46.                 can_FilterInitTypeDef.CAN_FilterMaskIdLow = 0x0000;
  47.                 can_FilterInitTypeDef.CAN_FilterMaskIdHigh = 0;
  48.                 can_FilterInitTypeDef.CAN_FilterIdLow = 0x0000;
  49.                 can_FilterInitTypeDef.CAN_FilterIdHigh = 0;
  50.         }
  51.         can_FilterInitTypeDef.CAN_FilterActivation = ENABLE;
  52.        
  53.         CAN_FilterInit(&can_FilterInitTypeDef);
  54.        
  55.        
  56.        
  57. //    CAN1->FMR |= 1; //过滤器组工作在初始化模式  
  58. //    CAN1->FMR &= 0xffffc0ff;//对FMR寄存器中CAN2SB[5:0]进行清零
  59. //    CAN1->FMR |= (14<<8);  //CAN2的过滤器组从14开始  
  60. //    CAN1->FM1R &= ~(1<<0);//过滤器组14的寄存器工作在屏蔽模式  
  61. //    CAN1->FS1R |= (1<<0);//过滤器组14为单个32位寄存器
  62. //    CAN1->FFA1R = 0x00000000;//全部关联到FIFO0
  63. //       
  64. //    CAN1->FA1R &= ~(1<<0);//禁用过滤器组0
  65. //    CAN1->sFilterRegister[0].FR1 &= 0x00000000;  
  66. //    CAN1->sFilterRegister[0].FR2 &= 0x00000000;  
  67. //    CAN1->sFilterRegister[0].FR1 |= CAN_FILTER_ID;  
  68. //    CAN1->sFilterRegister[0].FR2 |= CAN_FILTER_MASK;  
  69. //    CAN1->FA1R |= (1<<0);//使能过滤器组0

  70. //    CAN1->FMR &= ~1; //过滤器组正常工作
  71.     CAN_ITConfig(CANX,CAN_IT_FMP0,ENABLE);  //FIFO0消息挂号中断允许

  72.     for(i = 0;i < 256;i++){
  73.         can_cb_array[i].can_id = i;
  74.         can_cb_array[i].msg_rcv_callback = 0;
  75.     }
  76.     can_nvic_config();
  77.     return 1;
  78. }

  79. /* 函数名:int can_add_callback(u8 can_id,void *msg_rcv_callback_func)
  80. * 功能:增加对应标识符的CALLBACK函数
  81. * 参数:u8 can_id,接收消息的CALLBACK函数对应的标识符
  82.          void *msg_rcv_callback_fuc 邮件接收回调函数的指针,每当接收到所需要的
  83. *       消息时会自动调用该函数。注意:这里是在接收中断里调用这个函数的,所以该
  84. *       函数不宜执行太久。如果该函数指针为NULL,则不使用邮件接收中断。
  85. * 返回值:-1,已经存在函数
  86. *          1,成功增加函数
  87. */
  88. int can_add_callback(u8 can_id,void *msg_rcv_callback_func){
  89.     if(can_cb_array[can_id].msg_rcv_callback != 0){
  90.         return -1;
  91.     }
  92.     can_cb_array[can_id].msg_rcv_callback = msg_rcv_callback_func;
  93.     return 1;
  94. }

  95. void can_gpio_config(){
  96.        
  97.     GPIO_InitTypeDef gpio_init_stru;
  98.     gpio_init_stru.GPIO_Mode = GPIO_Mode_IPU;
  99.     gpio_init_stru.GPIO_Speed = GPIO_Speed_50MHz;
  100.     gpio_init_stru.GPIO_Pin = GPIO_Pin_11;
  101.         GPIO_Init(GPIOA,&gpio_init_stru);
  102.        
  103.         gpio_init_stru.GPIO_Mode = GPIO_Mode_AF_PP;
  104.     gpio_init_stru.GPIO_Pin = GPIO_Pin_12;
  105.     GPIO_Init(GPIOA,&gpio_init_stru);
  106. }

  107. /* 函数名:void can_nvic_config()
  108. * 功能:设置can的中断控制器nvic
  109. * 参数:
  110. * 返回值:
  111. */
  112. void can_nvic_config(){
  113.     NVIC_InitTypeDef nvic_init_struct;

  114.     nvic_init_struct.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  115.     nvic_init_struct.NVIC_IRQChannelPreemptionPriority = CAN1_NVIC_IRQPP;
  116.     nvic_init_struct.NVIC_IRQChannelSubPriority = CAN1_NVIC_IRQSP;
  117.     nvic_init_struct.NVIC_IRQChannelCmd = ENABLE;
  118.     NVIC_Init(&nvic_init_struct);
  119. }

  120. /* 函数名:int can_send_msg()
  121. * 功能:can发送一组数据
  122. * 参数:u8  can_id 数据包的标识符
  123. *       u8* msg 数据数组
  124. *       u8  len 数据数组长度,最大为8
  125. * 返回值:-1,表示发送失败
  126. *         1 ,表示发送成功
  127. */
  128. int can_send_msg(u8 can_id,u8 *msg,u8 len){
  129.     CanTxMsg tx_msg;
  130.     u8 mbox;
  131.     u16 i = 0;

  132.     tx_msg.StdId = can_id;
  133.     tx_msg.IDE = CAN_Id_Standard;   //使用标准标识符
  134.     tx_msg.RTR = CAN_RTR_Data;   //消息类型为数据帧
  135.     tx_msg.DLC = len;   //消息长度
  136.     for(i = 0;i < len;i++){
  137.         tx_msg.Data[i] = msg[i];
  138.     }
  139.     mbox = CAN_Transmit(CANX,&tx_msg);  //开始发送消息
  140.     i = 0;
  141.     while((CAN_TransmitStatus(CANX,mbox) == CAN_TxStatus_Failed) && (i < 0xfff))i++;
  142.     if(i >= 0xfff) return -1;
  143.     return 1;
  144. }
  145. /*
  146. *can1总线接受中断
  147. *
  148. */

  149. void USB_LP_CAN1_RX0_IRQHandler(void){
  150.     if(CAN_GetITStatus(CANX,CAN_IT_FMP0) != RESET){
  151.         CAN_Receive(CANX,CAN_FIFO0,&g_can_rx_msg);
  152.         if(can_cb_array[g_can_rx_msg.StdId].msg_rcv_callback != 0){
  153.             (can_cb_array[g_can_rx_msg.StdId].msg_rcv_callback)(&g_can_rx_msg);
  154.         }
  155.         CAN_ClearITPendingBit(CANX,CAN_IT_FMP0);
  156.     }
  157. }



头文件 can.h
  1. #define CAN1_ID 0x12     //stm的CAN总线的标识符

  2. #define CAN_MODE_X CAN_Mode_Normal  //模式
  3. //CAN总线时序和速率配置(此时配为1Mbps)
  4. #define CAN_SJW_X CAN_SJW_1tq
  5. #define CAN_BS1_X CAN_BS1_3tq   //时间段1的时间单元
  6. #define CAN_BS2_X CAN_BS2_2tq   //时间段2的时间单元
  7. #define CAN_PRESCALER_X 6     //分频系数
  8. /* tq = (CAN_PRESCALER_X + 1)*tpclk
  9. * 速率 = 1/((CAN_SJW_X + CAN_BS1_X + CAN_BS2_X)*tq)
  10. */


  11. //过滤器设置(32位)
  12. #define CAN_FILTER_ID 0x00000000   //如果都为0,则接收任意标识符的数据包
  13. #define CAN_FILTER_MASK 0x00000000
  14. //中断优先级设置
  15. #define CAN1_NVIC_IRQPP 1              //CAN1中断抢断优先级
  16. #define CAN1_NVIC_IRQSP 1              //CAN1中断子优先级

  17. #define CANX CAN1
  18. #define CAN_ID CAN1_ID



  19. typedef struct{
  20.     u16 can_id;
  21.     void (*msg_rcv_callback)(CanRxMsg *can_rx_msg);
  22. }can_callback_struct;

  23. int can_init(int number);
  24. void can_gpio_config(void);
  25. void can_nvic_config(void);
  26. int can_send_msg(u8 can_id,u8 *msg,u8 len);  //发送邮箱
  27. int can_rcv_msg(void);   //接收信息
  28. int can_add_callback(u8 can_id,void *msg_rcv_callback_func);
  29. void USB_LP_CAN1_RX0_IRQHandler(void);



 楼主| trouvan 发表于 2017-3-22 12:53 | 显示全部楼层
顶一下………………
jjlink 发表于 2017-3-22 14:05 | 显示全部楼层
楼主,在DeBug下,查看一下:Peripherals->can->Controller
查看一下相应的寄存器的值有没有写进去?
如波特率对不对?
在:查看一下:Peripherals->can->Filters  查看滤波器设置正确与否?
收发时,可以查看:Peripherals->can->Transmit Mailbox 或者Receive Mailbox查看收发器内容等等。
确认上述没问题之后,可以将CAN模式设为回环模式:CAN_Mode_LoopBack
尝试自发自收,看能否进入中断?以及相应的数据是否又正常?

以上~~供参考~~祝早日调试成功。



xmshao 发表于 2017-3-22 17:25 | 显示全部楼层
RB RC硬件上是一样的。只是FLASH容量的差异。

估计是你代码方面的问题。

RB的启动文件是用md.s, RC的启动文件是hd.s. 编译时相关的启动文件和宏配置要选择正确。

另外,你程序量多大?基于RC的程序量是否超过了128K?
 楼主| trouvan 发表于 2017-3-22 23:27 | 显示全部楼层
xmshao 发表于 2017-3-22 17:25
RB RC硬件上是一样的。只是FLASH容量的差异。

估计是你代码方面的问题。

多谢提醒!
问题解决了!说来惭愧,之前调试某个问题把一个预编译头给删除了。是因为它的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

61

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部