STM32 CAN使用
来源:互联网 发布:网络歌手什么意思 编辑:程序博客网 时间:2024/06/07 00:56
CAN工作模式:
CAN_Mode_Silent:静默模式,简单理解收到数据不发送应答信号。
在静默模式下,总线必须要有2个或2个以上的节点,才能收到数据,个人理解有应答信号stm32的can内核才认为只是一个完整的数据。
CAN波特率设置:
CAN_InitStructure.CAN_BS1 = tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2 = tbs2; //Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler = brp; //分频系数
BPS = AHB1_CLOCK / (tbs1 + tbs2 + brp + 1);
CAN滤波与FIFO,直接看代码如下:
u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode){int ext_id = 0x000000FF;//期望 想要看到的ID,例如 我先要ID 后2位时FF的数据,那么ext_id = 0x000000FF即可GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure;CAN_FilterInitTypeDef CAN_FilterInitStructure; NVIC_InitTypeDef NVIC_InitStructure; //使能相关时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//使能PORTD时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟 //初始化GPIOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化PD0,PD1 //引脚复用映射配置GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_CAN1); //GPIOD0复用为CAN1GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_CAN1); //GPIOD1复用为CAN1 //CAN单元设置 CAN_InitStructure.CAN_TTCM = DISABLE;//非时间触发通信模式 CAN_InitStructure.CAN_ABOM = DISABLE;//软件自动离线管理 CAN_InitStructure.CAN_AWUM = DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN_InitStructure.CAN_NART = ENABLE;//禁止报文自动传送 CAN_InitStructure.CAN_RFLM = DISABLE;//报文不锁定,新的覆盖旧的 CAN_InitStructure.CAN_TXFP = DISABLE;//优先级由报文标识符决定 CAN_InitStructure.CAN_Mode = mode; //模式设置 CAN_InitStructure.CAN_SJW = tsjw;//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq CAN_InitStructure.CAN_BS1 = tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2 = tbs2;//Tbs2范围CAN_BS2_1tq ~CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler = brp; //分频系数(Fdiv)为brp+1 CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1 //配置过滤器CAN_FilterInitStructure.CAN_FilterNumber = 0; //过滤器0CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; //32位 //设置屏蔽寄存器,这里当标识符寄存器CAN_FilterInitStructure.CAN_FilterIdHigh = ((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节CAN_FilterInitStructure.CAN_FilterIdLow = ((ext_id<<3)& 0xffff) | CAN_ID_EXT; //设置屏蔽寄存器低字节//设置标识符寄存器CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((ext_id<<3)& 0xffff) | CAN_ID_EXT; //设置屏蔽寄存器低字节 CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//过滤器0关联到FIFO0 CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //激活过滤器0 CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);//配置过滤器2ext_id = 0x00000000;CAN_FilterInitStructure.CAN_FilterNumber = 1; //过滤器1CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; //32位 //设置屏蔽寄存器,这里当标识符寄存器CAN_FilterInitStructure.CAN_FilterIdHigh = ((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节CAN_FilterInitStructure.CAN_FilterIdLow = ((ext_id<<3)& 0xffff) | CAN_ID_EXT; //设置屏蔽寄存器低字节//设置标识符寄存器CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((ext_id<<3)& 0xffff) | CAN_ID_EXT; //设置屏蔽寄存器低字节 CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1;//过滤器0关联到FIFO1 CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //激活过滤器0 CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化CAN_ITConfig(CAN1,CAN_IT_FMP1,ENABLE);//FIFO1消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 次优先级为3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);return 0;} u8 CAN2_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode){int ext_id = 0x00000000;//期望 想要看到的ID,例如 我先要ID 后2位时FF的数据,那么ext_id = 0x000000FF即可 GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; NVIC_InitTypeDef NVIC_InitStructure; //使能相关时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能PORTB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);//使能CAN2时钟 //初始化GPIOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化PB12,PB13 //引脚复用映射配置GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_CAN2); //GPIOB12复用为CAN2GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_CAN2); //GPIOB13复用为CAN2 //CAN单元设置 CAN_InitStructure.CAN_TTCM=DISABLE;//非时间触发通信模式 CAN_InitStructure.CAN_ABOM=DISABLE;//软件自动离线管理 CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN_InitStructure.CAN_NART=ENABLE;//禁止报文自动传送 CAN_InitStructure.CAN_RFLM=DISABLE;//报文不锁定,新的覆盖旧的 CAN_InitStructure.CAN_TXFP=DISABLE;//优先级由报文标识符决定 CAN_InitStructure.CAN_Mode= mode; //模式设置 CAN_InitStructure.CAN_SJW=tsjw;//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 CAN_Init(CAN2, &CAN_InitStructure); // 初始化CAN2 //配置过滤器 CAN_FilterInitStructure.CAN_FilterNumber=14; //过滤器14 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 //设置屏蔽寄存器,这里当标识符寄存器CAN_FilterInitStructure.CAN_FilterIdHigh=((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节CAN_FilterInitStructure.CAN_FilterIdLow=((ext_id<<3)& 0xffff) | CAN_ID_EXT; //设置屏蔽寄存器低字节//设置标识符寄存器CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((ext_id<<3)& 0xffff) | CAN_ID_EXT; //设置屏蔽寄存器低字节 CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器1关联到FIFO1 CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0 CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化CAN_ITConfig(CAN2,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; // 次优先级为1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);return 0;} void CAN1_RX0_IRQHandler(void){CAN_Receive(CAN1, CAN_Filter_FIFO0, &CAN1_RxMessage);CAN_Flag = 1;}void CAN1_RX1_IRQHandler(void){CAN_Receive(CAN1, CAN_Filter_FIFO1, &CAN1_RxMessage);CAN_FIFO1_Flag = 1;} void CAN2_RX0_IRQHandler(void){ CAN_Receive(CAN2, CAN_Filter_FIFO0, &CAN2_RxMessage);CAN2_Flag = 1;}u8 CAN1_Send_Msg(int extid,u8* msg,u8 len){ u8 mbox; u16 i = 0; CanTxMsg TxMessage; TxMessage.StdId = 0x12; // 标准标识符(12位) TxMessage.ExtId = extid; // 设置扩展标示符(29位) TxMessage.IDE = 4; // 使用1为扩展标识符、0为标准标识符 TxMessage.RTR = 0; // 消息类型为数据帧,0为数据帧、1为远程帧 TxMessage.DLC = len; // 发送帧字节数 for(i = 0;i < len;i++) TxMessage.Data[i] = msg[i]; // 第一帧信息 mbox = CAN_Transmit(CAN1, &TxMessage); i = 0; while((CAN_TransmitStatus(CAN1, mbox) == CAN_TxStatus_Failed) && (i < 0XFFF))i++;//等待发送结束 if(i >= 0XFFF)return 1; return 0;}u8 CAN2_Send_Msg(u8* msg,u8 len){ u8 mbox; u16 i=0; CanTxMsg TxMessage; TxMessage.StdId=0x12; // 标准标识符(12位) TxMessage.ExtId=0x0005ffff; // 设置扩展标示符(29位) TxMessage.IDE=4; // 使用1为扩展标识符、0为标准标识符 TxMessage.RTR=0; // 消息类型为数据帧,0为数据帧、1为远程帧 TxMessage.DLC=len; // 发送帧字节数 for(i=0;i=0XFFF)return 1; return 0;}
CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,12,CAN_Mode_Normal);//bsp = APB1_CLK / BRP / (1 + BS2 + BS1) 250kbps
进行初始化
直接看代码中配置滤波器段,首先选择滤波器编号(个人理解在32位标识符屏蔽位模式下CAN1对应滤波器组0 ~13 ,CAN2对应滤波器组14 ~ 27),选择好过滤器后,接着就是设置两个屏蔽寄存器,之后是关键,要把这个滤波器编号对应到FIFO上,只有这样对应FIFO中才能有数据。
代码中写了两个滤波器,分别对应FIFO0和FIFO1,STM32的can在进行筛选时根据滤波器编号从0到13,所以在设置两个滤波器的情况下,第二个要筛选的数对应位数要比第一个少。如,上述代码我要ID=00 00 00 FF的数据单独进入一个中断,那么我就必须使用编号低的滤波器组。
阅读全文
0 0
- STM32 CAN 使用心得!
- STM32 CAN使用
- STM32的CAN总线使用
- 关于STM32中CAN中断的使用
- STM32 CAN
- STM32 CAN
- STM32--CAN
- STM32外围部件使用步骤(USB、CAN、TIM之类)
- 使用stm32的io模拟方式操作can控制器sja1000
- stm32 can波特率
- stm32 can Configuration
- STM32 CAN通信问题
- STM32 CAN 过滤器总结
- stm32的CAN通信
- stm32 CAN过滤器总结
- STM32 CAN通信
- STM32 CAN 控制器
- STM32之CAN控制器
- position:fixed失效问题
- 报数-LintCode
- EventBus的简单实现与log日志的使用
- 数据结构:实验二线性表综合实践⑤间接寻址
- SVN failed to commit: 'xxx\build\xxx' is scheduled for addition, but is missing
- STM32 CAN使用
- Android Studio ListView列表绑定网络JSON数据
- 各大公司Java后端开发面试题总结
- 悟性高还不行,还得有逆向思维
- 构建工具-Gradle简介-1
- 中国首届原型设计大赛在成都举办
- Hadoop 2.6 使用MapReduce实现基于内容的推荐系统
- 前端几个常用简单的开发手册拿走不谢
- HashMap 遍历