总结一些最近做项目对CAN通信的过滤器配置的理解;
- 这里我使用STM32F105系列的芯片,有2路CAN,我使用的是CAN2,过滤器可以设置从15开始,当然,从1开始也是没有问题的;
- 当设置了CAN过滤器,表示只能接收指定ID的数据,其他ID发送过来的数据,不再触发CAN中断,可以进一步提高系统的稳定性。当CAN总线上数据比较多的时候,是很有必要的。
具体配置如下:
CAN_SlaveStartBank(15); // can2筛选器组从15开始
CAN_FilterInitStructure.CAN_FilterNumber=15;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
//表示只能接收接收方ID为0x11,发送方ID为0x14的数据,具体看通信协议
CAN_FilterInitStructure.CAN_FilterIdHigh=0x1114;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
如果要设置多个过滤器,继续配置如下:
CAN_FilterInitStructure.CAN_FilterNumber=16;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x1113;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
以此类推。
3. 单独使用CAN2的时候必须开启先CAN1的时钟,否则收不到数据;
CAN完整的初始化代码(注意F105系列的CAN2时钟使能部分):
//CAN模式初始化
//参数 tsjw :重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//参数 tbs2 :时间段2的时间单元. 范围:CAN_BS2_1tq~CAN_BS2_8tq;
//参数 tbs1 :时间段1的时间单元. 范围:CAN_BS1_1tq ~CAN_BS1_16tq
//参数 brp ;波特率分频器.范围:1~1024; tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//示例:Fpclk1的时钟在初始化的时候设置为36M,如果设置 CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);
//则波特率为:(pclk1/((tsjw+tbs2+tbs1)*brp)) = 36Mhz/18/4 = 500Kbits
//参数 mode :模式设置: mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//CAN普通模式初始化, 波特率500Kbps
//返回值:0,初始化OK;
// 其他,初始化失败;
//这里我使用正常模式;CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_4tq,CAN_BS2_7tq,6,CAN_Mode_Normal);//正常模式
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
GPIO_InitTypeDef GPIO_InitStructure; //声明结构体
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;//CAN接收RX0中断使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PORTB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //新增 注意
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);//使能CAN2时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化IO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化IO
//CAN单元设置
CAN_InitStructure.CAN_TTCM = DISABLE;//禁止时间触发通信模式
CAN_InitStructure.CAN_ABOM = ENABLE; /* 自动离线禁止,自动离线:一旦硬件监控到128次11个隐性位,就自动退出离线状态。在这里要软件设定后才能退出 */
// CAN_InitStructure.CAN_ABOM = DISABLE;//软件对CAN_MCR寄存器的INRQ位进行置1后清0后,一旦硬件检测到128次11位连续的隐形位,就退出离线状态(软件自动离线管理)
CAN_InitStructure.CAN_AWUM = DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)???
CAN_InitStructure.CAN_NART = DISABLE; /* 报文重传, 如果错误一直传到成功止,否则只传一次 */
// CAN_InitStructure.CAN_NART = ENABLE;//禁止报文自动传送
CAN_InitStructure.CAN_RFLM = DISABLE;//报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP = ENABLE; /* 发送优先级 0---由标识符决定 1---由发送请求顺序决定 */
// CAN_InitStructure.CAN_TXFP = DISABLE;//发生FIFO的优先级由报文的标识符决定
CAN_InitStructure.CAN_Mode = mode;//模式设置: mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//设置波特率
CAN_InitStructure.CAN_SJW = tsjw;//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1 = tbs1;//Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2 = tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
//(pclk1/((1+8+9)*4)) = 36Mhz/18/4 = 500Kbits
//(pclk1/((1+4+7)*6)) = 36Mhz/18/4 = 500Kbits
CAN_InitStructure.CAN_Prescaler = brp;
CAN_Init(CAN2, &CAN_InitStructure);
#if 1
//待优化
CAN_SlaveStartBank(15); // can2筛选器组从15开始
CAN_FilterInitStructure.CAN_FilterNumber=15;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x1114;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_FilterInitStructure.CAN_FilterNumber=16;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x1113;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_FilterInitStructure.CAN_FilterNumber=17;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x1115;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_FilterInitStructure.CAN_FilterNumber=18;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x1116;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
#endif
CAN_ITConfig(CAN2,CAN_IT_FMP0,ENABLE); //FIFO0消息挂号中断允许.
NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn; //优先级配置,比较特殊 USB_LP_CAN1_RX0_IRQn
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 挂号中断, 进入中断后读fifo的报文函数释放报文清中断标志 */
NVIC_Init(&NVIC_InitStructure);
}