打印
[STM32F1]

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

[复制链接]
1637|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
#include "can.h"

static void (*msg_rcv_callback)(CanRxMsg *can_rx_msg);
static CanRxMsg g_can_rx_msg;
can_callback_struct can_cb_array[256];

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

        check_out_ID = number<<9;

        can_FilterInitTypeDef.CAN_FilterNumber = 0;
        can_FilterInitTypeDef.CAN_FilterMode = CAN_FilterMode_IdMask;
        can_FilterInitTypeDef.CAN_FilterScale = CAN_FilterScale_32bit;
        can_FilterInitTypeDef.CAN_FilterFIFOAssignment = CAN_FilterFIFO0;
       
        if(number != 0){
                can_FilterInitTypeDef.CAN_FilterMaskIdLow = 0x0000;
                can_FilterInitTypeDef.CAN_FilterMaskIdHigh = 0xF<<9;
                can_FilterInitTypeDef.CAN_FilterIdLow = 0x0000;
                can_FilterInitTypeDef.CAN_FilterIdHigh = check_out_ID;//屏蔽部分ID
        }else{
                can_FilterInitTypeDef.CAN_FilterMaskIdLow = 0x0000;
                can_FilterInitTypeDef.CAN_FilterMaskIdHigh = 0;
                can_FilterInitTypeDef.CAN_FilterIdLow = 0x0000;
                can_FilterInitTypeDef.CAN_FilterIdHigh = 0;
        }
        can_FilterInitTypeDef.CAN_FilterActivation = ENABLE;
       
        CAN_FilterInit(&can_FilterInitTypeDef);
       
       
       
//    CAN1->FMR |= 1; //过滤器组工作在初始化模式  
//    CAN1->FMR &= 0xffffc0ff;//对FMR寄存器中CAN2SB[5:0]进行清零
//    CAN1->FMR |= (14<<8);  //CAN2的过滤器组从14开始  
//    CAN1->FM1R &= ~(1<<0);//过滤器组14的寄存器工作在屏蔽模式  
//    CAN1->FS1R |= (1<<0);//过滤器组14为单个32位寄存器
//    CAN1->FFA1R = 0x00000000;//全部关联到FIFO0
//       
//    CAN1->FA1R &= ~(1<<0);//禁用过滤器组0
//    CAN1->sFilterRegister[0].FR1 &= 0x00000000;  
//    CAN1->sFilterRegister[0].FR2 &= 0x00000000;  
//    CAN1->sFilterRegister[0].FR1 |= CAN_FILTER_ID;  
//    CAN1->sFilterRegister[0].FR2 |= CAN_FILTER_MASK;  
//    CAN1->FA1R |= (1<<0);//使能过滤器组0

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

    for(i = 0;i < 256;i++){
        can_cb_array[i].can_id = i;
        can_cb_array[i].msg_rcv_callback = 0;
    }
    can_nvic_config();
    return 1;
}

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

void can_gpio_config(){
       
    GPIO_InitTypeDef gpio_init_stru;
    gpio_init_stru.GPIO_Mode = GPIO_Mode_IPU;
    gpio_init_stru.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_init_stru.GPIO_Pin = GPIO_Pin_11;
        GPIO_Init(GPIOA,&gpio_init_stru);
       
        gpio_init_stru.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio_init_stru.GPIO_Pin = GPIO_Pin_12;
    GPIO_Init(GPIOA,&gpio_init_stru);
}

/* 函数名:void can_nvic_config()
* 功能:设置can的中断控制器nvic
* 参数:
* 返回值:
*/
void can_nvic_config(){
    NVIC_InitTypeDef nvic_init_struct;

    nvic_init_struct.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
    nvic_init_struct.NVIC_IRQChannelPreemptionPriority = CAN1_NVIC_IRQPP;
    nvic_init_struct.NVIC_IRQChannelSubPriority = CAN1_NVIC_IRQSP;
    nvic_init_struct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvic_init_struct);
}

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

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

void USB_LP_CAN1_RX0_IRQHandler(void){
    if(CAN_GetITStatus(CANX,CAN_IT_FMP0) != RESET){
        CAN_Receive(CANX,CAN_FIFO0,&g_can_rx_msg);
        if(can_cb_array[g_can_rx_msg.StdId].msg_rcv_callback != 0){
            (can_cb_array[g_can_rx_msg.StdId].msg_rcv_callback)(&g_can_rx_msg);
        }
        CAN_ClearITPendingBit(CANX,CAN_IT_FMP0);
    }
}



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

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


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

#define CANX CAN1
#define CAN_ID CAN1_ID



typedef struct{
    u16 can_id;
    void (*msg_rcv_callback)(CanRxMsg *can_rx_msg);
}can_callback_struct;

int can_init(int number);
void can_gpio_config(void);
void can_nvic_config(void);
int can_send_msg(u8 can_id,u8 *msg,u8 len);  //发送邮箱
int can_rcv_msg(void);   //接收信息
int can_add_callback(u8 can_id,void *msg_rcv_callback_func);
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?

使用特权

评论回复
5
trouvan|  楼主 | 2017-3-22 23:27 | 只看该作者
xmshao 发表于 2017-3-22 17:25
RB RC硬件上是一样的。只是FLASH容量的差异。

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

多谢提醒!
问题解决了!说来惭愧,之前调试某个问题把一个预编译头给删除了。是因为它的问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

61

帖子

1

粉丝