(一)配置流程
(1)启用CAN控制器接口时钟
RCC_APB1PeriphClockCmd (RCC_APB1Periph_CAN1,使);for CAN1 and
rcc_apb1peripclockcmd (rcc_apb1perip_can2, ENABLE);对于CAN2
如果你只使用CAN2,必须使能CAN1时钟。
(2)CAN引脚配置
1使用以下函数使能CAN gpio时钟:rcc_ahb1peripclockcmd (rcc_ahb1peri_gpiox, Enable);
2使用以下功能启用引脚复用 GPIO_PinAFConfig (GPIOx GPIO_PinSourcex GPIO_AF_CANx);
3配置这些CAN引脚GPIO_Init ();
(3)初始化和配置CAN使用
CAN_Init()和
CAN_FilterInit()
(4)使用CAN_Transmit()函数发送所需的CAN帧。
(5)使用CAN_TransmitStatus()函数检查CAN帧的传输。
(6)使用CAN_CancelTransmit()函数取消CAN帧的传输。
(7)接收一个CAN帧使用CAN_Receive()函数。
(8)使用CAN_FIFORelease()函数释放接收FIFOs。
(9)返回等待接收的帧数量使用
CAN_MessagePending()函数 .
(10)控制CAN事件可以使用以下两种方法之一:
(++)使用CAN_GetFlagStatus()函数检查CAN标志。
(++)初始化阶段通过CAN_ITConfig()添加中断事件,用CAN_GetITStatus()函数检查事件是否已经发生。在检查一个标志之后,你应该使用CAN_ClearFlag()来清除它。。在检查一个中断事件之后应该使用CAN_ClearITPendingBit()函数清除它。
(二)程序代码
//CAN1初始化
//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+tbs2+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为50M
//则波特率为:50M/((1+7+12)*10)=250Kbps
//返回值:无;
/************************BMS用*********************/
void CAN1_Config_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
//引脚复用映射配置
GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用推挽
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART=DISABLE; //使能报文自动传送
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode= CAN_Mode_Normal; //模式设置: mode:0,普通模式;1,回环模式;
//设置波特率250kbps
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=CAN_BS1_12tq; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; //Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=CAN1_PRESCALER; //分频系数(Fdiv)为brp+1
CAN_Init(CAN1, &CAN_InitStructure); //初始化CAN1
//滤波器配置 只接收0x56F4
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位宽
/*
CAN_FilterInitStructure.CAN_FilterIdHigh=(bms_filter>>13)&0x0007; // 取15~13 3位
CAN_FilterInitStructure.CAN_FilterIdLow=((bms_filter<<3)&0xFFFF)|CAN_ID_EXT;// 取12~0 13位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0007; //32位MASK//0~15 左移3位变为 3~18 0x0FFFF<<3 = 0x7FFF8
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xFFF8|CAN_ID_EXT;
*/
CAN_FilterInitStructure.CAN_FilterIdHigh =0;
CAN_FilterInitStructure.CAN_FilterIdLow =0;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0;
CAN_FilterInitStructure.CAN_FilterMaskIdLow =0;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0
CAN_FilterInit(CAN1,&CAN_FilterInitStructure); //滤波器初始化
//CAN1 NVIC 中断配置
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);
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE); //FIFO0消息挂号中断允许.
}
void CAN2_Config_Init_1(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);//使能CAN1、2时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
//引脚复用映射配置
GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_CAN2); //GPIOB12复用为CAN2
GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_CAN2); //GPIOB13复用为CAN2
GPIO_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); //初始化IO
//CAN单元设置
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART=DISABLE; //使能报文自动传送
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode= CAN_Mode_Normal; //模式设置: mode:0,普通模式;1,回环模式;
//设置波特率250kbps
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=CAN_BS1_12tq; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; //Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=CAN2_PRESCALER; //分频系数(Fdiv)为brp+1
CAN_Init(CAN2, &CAN_InitStructure); //初始化CAN2
CAN_FilterInitStructure.CAN_FilterNumber=14;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(CAN2,&CAN_FilterInitStructure);
CAN_FilterInit(CAN1,&CAN_FilterInitStructure);
CAN_ITConfig(CAN2,CAN_IT_FMP0,ENABLE);
//CAN2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void CAN3_Config_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN3, ENABLE);//使能CAN3时钟
//引脚复用映射配置
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF11_CAN3); //GPIOB3复用为CAN3
GPIO_PinAFConfig(GPIOA,GPIO_PinSource15,GPIO_AF11_CAN3); //GPIOB4复用为CAN3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_15;
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(GPIOA, &GPIO_InitStructure); //初始化IO
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理
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= CAN_Mode_Normal; //模式设置: mode:0,普通模式;1,回环模式;
//设置波特率250kbps
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=CAN_BS1_12tq; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; //Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=CAN3_PRESCALER; //分频系数(Fdiv)为brp+1
CAN_Init(CAN3, &CAN_InitStructure); //初始化CAN3
//暂时不过滤
CAN_FilterInitStructure.CAN_FilterNumber=3; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位宽
CAN_FilterInitStructure.CAN_FilterIdHigh =0;
CAN_FilterInitStructure.CAN_FilterIdLow =0;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0;
CAN_FilterInitStructure.CAN_FilterMaskIdLow =0;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO1;//过滤器3关联到FIFO1
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器3
CAN_FilterInit(CAN3,&CAN_FilterInitStructure); //滤波器初始化
//CAN3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = CAN3_RX1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_ITConfig(CAN3,CAN_IT_FMP1,ENABLE); //FIFO0消息挂号中断允许.
}
(三)使用时注意事项
can1和can3使用时无特殊注意事项,但是CAN2在使用初始化时需要注意与CAN1的不同之处!