can 初始化:
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;
u16 StdIdArray[10] ={0x7e0,0x7e1,0x7e2,0x7e3,0x7e4,0x7e5,0x7e6,0x7e7,0x7e8,0x7e9}; //定义一组标准CAN ID
u16 mask,num,tmp,i;
#if CAN_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);//使能PORTD时钟,使能功能复用时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
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_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化IO
GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理 //
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= 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
#if 1
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=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
#endif
/*
CAN_FilterInitStructure.CAN_FilterNumber = 2; //使用过滤器2
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList; //配置为掩码模式
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit; //设置为32位宽
CAN_FilterInitStructure.CAN_FilterIdHigh =(StdIdArray[0]<<5); //验证码可以设置为StdIdArray[]数组中任意一个,这里使用StdIdArray[0]作为验证码
CAN_FilterInitStructure.CAN_FilterIdLow =(StdIdArray[1]<<5);
CAN_FilterInitStructure.CAN_FilterMaskIdHigh =(StdIdArray[2]<<5);
CAN_FilterInitStructure.CAN_FilterMaskIdLow =(StdIdArray[3]<<5); //只接收数据帧
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0; //设置通过的数据帧进入到FIFO0中
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
*/
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN_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;
}
can发送(标准帧):
//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
//len:数据长度(最大为8)
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
// 其他,失败;
u8 Can_Send_Msg(u8* msg,u8 len)
{
u8 mbox;
u16 i=0;
CanTxMsg TxMessage;
TxMessage.StdId=0x123; // 标准标识符为0
TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
TxMessage.IDE=0; // 使用扩展标识符
TxMessage.RTR=0; // 消息类型为数据帧,一帧8位
TxMessage.DLC=len; // 发送两帧信息
for(i=0;i<8;i++)
TxMessage.Data[i]=msg[i]; // 第一帧信息
mbox= CAN_Transmit(CAN1, &TxMessage);
i=0;
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
if(i>=0XFFF)return 1;
return 0;
}
can接收:
//can口接收数据查询
//buf:数据缓存区;
//返回值:0,无数据被收到;
// 其他,接收的数据长度;
u8 Can_Receive_Msg(u8 *buf)
{
u32 i;
CanRxMsg RxMessage;
if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据
for(i=0;i<8;i++)
buf[i]=RxMessage.Data[i];
return RxMessage.DLC;
}
can接收中断处理函数:
u16 kkk[13]; //用来给主函数接收数据的buf
u8 idd;
volatile u8 can_finish_flag;//接收已完成标志
#if CAN_RX0_INT_ENABLE //使能RX0中断
//中断服务函数
void CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
CAN_Receive(CAN1, 0, &RxMessage);
kkk[0] = RxMessage.StdId;
kkk[1] = RxMessage.ExtId;
kkk[2] = RxMessage.IDE;
kkk[3] = RxMessage.RTR;
kkk[4] = RxMessage.DLC;
for(idd=5;idd<13;idd++){
kkk[idd]=RxMessage.Data[idd-5];
}
can_finish_flag = 1;
}
#endif
主函数:
u8 canbuf[8]={0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08};
u8 i;
uart_init(115200);//串口1初始化
CAN_STB();//低电平工作模式,高电平休眠模式
CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_8tq,CAN_BS2_3tq,6,CAN_Mode_Normal);//36M/(1+8+3)*6=500K
CAN2_Mode_Init(CAN_SJW_1tq,CAN_BS1_8tq,CAN_BS2_3tq,6,CAN_Mode_Normal);//36M/(1+8+3)*6=500K
#if SEND_CAN_EXAMPLE
while(1){
//CAN1
Can_Send_Msg(canbuf,8);
//CAN2
Can2_Send_Msg(canbuf,8);
USART_SendData(USART1, 0x55);//向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)!=SET);//等待发送结束
}
#endif//end send can example
#if RECEIVE_CAN_EXAMPLE
while(1){
while (can_finish_flag == 0)
;
can_finish_flag = 0;
for(i=0 ; i<13 ; i++){
USART_SendData(USART1, kkk[i]);//向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)!=SET);//等待发送结束
}
}
#endif//end receive can example