STM32F107属于STMF10x系列的互联型产品,所以配有2个CAN模块即CAN1和CAN2。CAN模块正常工作模式和测试模式,且测试模式又分为环回模式、静默模式和环回静默模式,但一般都使用正常工作模式,所以在此仅介绍正常工作模式相关配置。
一、来说说CAN模块的配置步骤:
1、初始化CAN相关GPIO口;
2、初始化CAN控制器;
3、初始化CAN过滤器;
4、初始化CAN中断;
5、添加CAN中断接收函数;
二、CAN1部分具体代码如下(库函数版本为V3.50):
1、初始化CAN1相关GPIO口:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
2、初始化CAN1控制器:
CAN_DeInit(CAN1); //默认初始化配置
CAN_StructInit(&CAN_InitStructure);//CAN初始化结构图初始化
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理
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; //模式设置: 普通模式;
//设置波特率
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //SJW = 1tq
CAN_InitStructure.CAN_BS1=CAN_BS1_3tq; //Tbs1 = 3tq
CAN_InitStructure.CAN_BS2=CAN_BS2_5tq; //Tbs2 = 5tq
CAN_InitStructure.CAN_Prescaler=8; //分频系数8,即波特率为36M/((1+3+5)*8)= 500k,其中36M为PCLK1
CAN_Init(CAN1, &CAN_InitStructure); //初始化CAN1
3、初始化CAN1过滤器:
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0,选择范围0 - 13
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位宽
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化
4、初始化CAN1中断:
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);
5、添加CAN1中断接收函数:
void CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
CAN_Receive(CAN1, CAN_Filter_FIFO0, &RxMessage);
/*此处可添加接收消息处理逻辑*/
}
三、CAN2部分的具体代码:
CAN2与CAN1大同小异,相关配置步骤也是一样,指示具体配置参数有所差别,这里只列出不同之处:
1、初始化CAN2相关GPIO口: 与CAN1配置类似
2、初始化CAN2控制器:与CAN1配置相同
3、初始化CAN2过滤器:
CAN_FilterInitStructure.CAN_FilterNumber=14; //过滤器14,选择范围14 - 27
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位宽
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0
CAN_SlaveStartBank(14);//配置CAN2起始过滤器为14,此配置只当芯片有CAN2模块时才需要
CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化,通过库函数可得知这里实际是配置CAN1相关寄存器,因CAN2不能直接访问SRAM,所以利用CAN1的寄存器来间接访问。
4、初始化CAN2中断:
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 = 1; // 从优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
5、添加CAN2中断接收函数;
void CAN2_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
CAN_Receive(CAN2, CAN_Filter_FIFO0, &RxMessage);
/*此处可添加接收消息处理逻辑*/
}
到此代码部分已差不多,但以上内容均指示说明了一个大概过程与配置,具体为何这样配置需配合官方文档和其它相关资料分析。