STM32中CAN通信:简单的CAN发送代码和滤波器配置方法(16位和32位)
我要用标准帧进行CAN通信,却找不到相关的例子,只好自己摸索,现在大致知道怎么配置,先放一下代码:
代码:
CAN.c的代码:
#include "stm32f10x.h"
uint32_t Rx_COB_ID=0x0000;
void CAN1_Init(void)
{
//时钟使能,低速总线APB1和低速总线APB2;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);//CAN端口重映射
//GPIO初始化;
GPIO_InitTypeDef GPIO_InitStructure;//PB8,对应CAN_RX,上拉输入GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);//PB9,对应CAN_TX,复用推挽输出GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//CAN初始化;
CAN_DeInit(CAN1); //将外设CAN的全部寄存器重设为缺省值
CAN_InitTypeDef CAN_InitStructure;
CAN_InitStructure.CAN_ABOM = DISABLE;//用来使能或者失能自动离线管理, ENABLE 或者 DISABLE。
CAN_InitStructure.CAN_AWUM = DISABLE;//用来使能或者失能自动唤醒模式, ENABLE 或者 DISABLE。
CAN_InitStructure.CAN_NART = DISABLE;//用来使能或者失能非自动重传输模式, ENABLE 或者 DISABLE。
CAN_InitStructure.CAN_RFLM = DISABLE;//用来使能或者失能接收 FIFO 锁定模式, ENABLE 或者 DISABLE。
CAN_InitStructure.CAN_TTCM = DISABLE;//用来使能或者失能时间触发通讯模式,ENABLE 或者 DISABLE。
CAN_InitStructure.CAN_TXFP = DISABLE;//用来使能或者失能发送 FIFO 优先级, ENABLE 或者 DISABLE。
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//CAN 的工作模式
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//定义了重新同步跳跃宽度(SJW),即在每位中可以延长或缩短多少个时间单位的上限
CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;//设定了时间段 1 的时间单位数目
CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;//设定了时间段 2 的时间单位数目
CAN_InitStructure.CAN_Prescaler = 12;//设定了一个时间单位的长度,它的范围是 1 到 1024
CAN_Init(CAN1,&CAN_InitStructure);
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE); //FIFO0消息挂号中断允许
//CAN Fliter初始化
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber=1; //指定过滤器为1
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //指定过滤器为标识符屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit; //过滤器位宽为16位
CAN_FilterInitStructure.CAN_FilterIdHigh=(Rx_COB_ID<<5)|0x18; //过滤器标识符的高8位值
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; //过滤器标识符的低16位值
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(Rx_COB_ID<<5)|0x18;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
因为我用的PB8、PB9引脚,所以要开启AFIO时钟,进行重映射;
CAN.h的代码:
#ifndef __CAN_H
#define __CAN_H
void CAN1_Init(void);
#endif
main.h的代码:
#include "stm32f10x.h"
#include "Delay.h"
#include "CAN.h"
extern uint32_t Rx_COB_ID;
int main(void)
{
uint8_t arr[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
uint8_t i;
CAN1_Init();
CanTxMsg TxMessage; //一个结构体,用来定义发送报文的
TxMessage.StdId=Rx_COB_ID; //标准ID
TxMessage.ExtId=0; //扩展ID,不使用扩展帧,写0
TxMessage.IDE=CAN_ID_STD; //标准帧还是扩展帧
TxMessage.RTR=CAN_RTR_DATA; //数据帧还是远程帧
TxMessage.DLC=8; //待传输数据长度
for(i=0;i<8;i++)
{
TxMessage.Data[i]=arr[i];
}
CAN_Transmit(CAN1,&TxMessage);
Delay_ms(200);
}
上面代码用处不大,只有发送,没有接受和中断,只是方便我举个例子,主要讲这一段:
//CAN Fliter初始化
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber=1; //指定过滤器为1
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //指定过滤器为标识符屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit; //过滤器位宽为16位
CAN_FilterInitStructure.CAN_FilterIdHigh=(Rx_COB_ID<<5); //过滤器标识符的高8位值
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; //过滤器标识符的低16位值
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
滤波器配置:
CAN_FilterNumber
CAN_FilterNumber 指定了待初始化的过滤器,它的范围是 1 到 13。
我选的是16位,屏蔽模式;(库函数)
通过寄存器设置CAN_FS1R的相应FSCx位,可以配置一个过滤器组的位宽(32位还是16位),通过寄存器设置CAN_FMR的FBMx位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式或屏蔽位模式。(寄存器)
u16 CAN_FilterIdHigh; 放第一个COB_ID,位置要左移5位
u16 CAN_FilterIdLow; 放第二个COB_ID,位置要左移5位
u16 CAN_FilterMaskIdHigh; 放第一个屏蔽码,对应上面的第一个COB_ID
u16 CAN_FilterMaskIdLow; 放第二个屏蔽码,对应上面的第二个COB_ID
这个要解释一下:
比如假设第一个
COB_ID是0x201,左移5位,是因为这个寄存器从第5位开始放COB_ID,又因为RTR是数据帧,使用0,IDE是标准帧,使用0,就不用对这两位做什么配置了,默认就是0;
第一个屏蔽码,假设为0x7FC,0b111 1111 1100;二进制是11位,对应上面STID[10:0]的11位;
把COB_ID的十六进制0x201,写成二进制0b010 0000 0001,屏蔽码的1对应的位置必须一样,屏蔽码的0的位置可以随便写;
这样,允许通过的COB_ID有0b010 0000 0000,0b010 0000 0011,0b010 0000 0001,0b010 0000 0010,对应的十六进制数就是0x200,0x203,0x201,0x202;
第二个COB_ID与屏蔽码的关系也一样;不写也可以;
最后选一个邮箱:
两个链接,超级全面详细的讲解:
【HAL库】STM32F407—-CAN通信—-过滤器配置_can过滤器_根号五的博客-CSDN博客
STM32 CAN通讯滤波器几种模式的设置_stm32can过滤器设置-CSDN博客
作者:再望断天涯