同样的代码,在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);
|