以下代码本人测试通过的,可以参考如下:
u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode,u8 dev_index)
{
u32 id;
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN1_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTB时钟
/********** CAN1 TX PIN ***************/
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
/********** CAN1 RX PIN ***************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO
/* Remap CAN1 GPIOs */
//GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE); //CAN1 重映射 PB8 ,PB9
/* CAN1 and CAN2 Periph clocks enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //使能CAN1时钟
CAN_DeInit(CAN1);
//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= mode; //模式设置: mode:0,普通模式;1,回环模式; //
//设置波特率
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
CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1
/* CAN1 filter init */
id = dev_index;
id <<= 19;
id |= 0x90000004;
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=id>>16;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=id;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xb7f8;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0006;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
id = 0x10000004;
CAN_FilterInitStructure.CAN_FilterNumber=1; //过滤器1
CAN_FilterInitStructure.CAN_FilterIdHigh=id>>16;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=id;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xb7f8;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0006;
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN1_RX0_INT_ENABLE
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);
#endif
return 0;
}
//////////////////////////////////////////////////////////////////////////////////
//CAN2初始化
//tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
//tbs2:时间段2的时间单元.范围:1~8;
//tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
//注意以上参数任何一个都不能设为0,否则会乱.
//波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);
//mode:0,普通模式;1,回环模式;
//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);
//则波特率为:36M/((1+8+7)*5)=450Kbps
//返回值:0,初始化OK;
// 其他,初始化失败;
u8 CAN2_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
u32 id;
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN2_RX1_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PORTB时钟
/********** CAN2 TX PIN ***************/
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
/********** CAN2 RX PIN ***************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化IO
/* Remap CAN2 GPIOs */
//GPIO_PinRemapConfig(GPIO_Remap_CAN2, ENABLE); //CAN2 重映射 PB5 ,PB6
/* CAN2 Periph clocks enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE); //使能CAN2时钟
CAN_DeInit(CAN2);
//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= mode; //模式设置: mode:0,普通模式;1,回环模式; //
//设置波特率
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
CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //
CAN_Init(CAN2, &CAN_InitStructure); // 初始化CAN2
/* CAN2 filter init */
id = 0x00000004;
CAN_FilterInitStructure.CAN_FilterNumber=14; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
CAN_FilterInitStructure.CAN_FilterIdHigh=id>>16;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=id;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x8000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0006;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO1;//过滤器0关联到FIFO1
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
id = 0x80000004;
CAN_FilterInitStructure.CAN_FilterNumber=15; //过滤器1
CAN_FilterInitStructure.CAN_FilterIdHigh=id>>16;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=id;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x8000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0006;
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN2_RX1_INT_ENABLE
CAN_ITConfig(CAN2,CAN_IT_FMP1,ENABLE);//FIFO1消息挂号中断允许.
NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
return 0;
}
#if CAN1_RX0_INT_ENABLE //使能RX0中断
//中断服务函数
void CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
int i=0;
Can1_Led_pluse();
CAN_Receive(CAN1, 0, &RxMessage);
/*********************数据入列*******************************/
CAN1_Rev_rear = (CAN1_Rev_rear+1)%MAXLEN;
CAN1_Rev_buf[CAN1_Rev_rear].ID_00 = RxMessage.ExtId;
CAN1_Rev_buf[CAN1_Rev_rear].ID_01 = RxMessage.ExtId>>8;
CAN1_Rev_buf[CAN1_Rev_rear].ID_02 = RxMessage.ExtId>>16;
CAN1_Rev_buf[CAN1_Rev_rear].ID_03 = RxMessage.ExtId>>24;
CAN1_Rev_buf[CAN1_Rev_rear].len = RxMessage.DLC; //读数据长度
CAN1_Rev_buf[CAN1_Rev_rear].mailbox_index = RxMessage.FMI; //过滤器匹配序号
for(i=0;i<CAN1_Rev_buf[CAN1_Rev_rear].len;i++)
{
CAN1_Rev_buf[CAN1_Rev_rear].buf = RxMessage.Data; //收数据
}
CAN1_Rev_num ++;
if(CAN1_Rev_num>MAXLEN)
{
CAN1_Rev_num = MAXLEN;
CAN1_Rev_front = CAN1_Rev_rear;
}
}
#endif
#if CAN2_RX1_INT_ENABLE //使能RX0中断
//中断服务函数
void CAN2_RX1_IRQHandler(void)
{
CanRxMsg RxMessage;
int i=0;
Can2_Led_pluse();
CAN_Receive(CAN2, 1, &RxMessage);
/*********************数据入列*******************************/
CAN2_Rev_rear = (CAN2_Rev_rear+1)%MAXLEN;
CAN2_Rev_buf[CAN2_Rev_rear].ID_00 = RxMessage.ExtId;
CAN2_Rev_buf[CAN2_Rev_rear].ID_01 = RxMessage.ExtId>>8;
CAN2_Rev_buf[CAN2_Rev_rear].ID_02 = RxMessage.ExtId>>16;
CAN2_Rev_buf[CAN2_Rev_rear].ID_03 = RxMessage.ExtId>>24;
CAN2_Rev_buf[CAN2_Rev_rear].len = RxMessage.DLC; //读数据长度
CAN2_Rev_buf[CAN2_Rev_rear].mailbox_index = RxMessage.FMI; //过滤器匹配序号
for(i=0;i<CAN2_Rev_buf[CAN2_Rev_rear].len;i++)
{
CAN2_Rev_buf[CAN2_Rev_rear].buf = RxMessage.Data; //收数据
}
CAN2_Rev_num ++;
if(CAN2_Rev_num>MAXLEN)
{
CAN2_Rev_num = MAXLEN;
CAN2_Rev_front = CAN2_Rev_rear;
}
}
#endif
|