STM32 CAN总线通信CAN总线通信详细学习的话这里有个视频教程可以推荐看看,/programs/view/IIuJjM2RIxc做电子的一定要多练勤于动手,做多了就自然而然就手到擒来。
Can.h文件如下:#ifndef __CAN_H#define __CAN_H#include "sys.h"////////////////////////////////////////////////////////////////////////////////////CAN接收RX0中断使能#define CAN_RX0_INT_ENABLE 0 //0,不使能;1,使能.u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);//CAN初始化u8 Can_Send_Msg(u8* msg,u8 len); //发送数据u8 Can_Receive_Msg(u8 *buf); //接收数据#endifCan.c文件如下:#include "can.h"#include "led.h"#include "delay.h"#include "usart.h"//CAN初始化//tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tqCAN_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 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;#if CAN_RX0_INT_ENABLENVIC_InitTypeDef NVIC_InitStructure;#endifRCC_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); //初始化IOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO//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_4tqCAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tqCAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tqCAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32位IDCAN_FilterInitStructure.CAN_FilterIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASKCAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化#if CAN_RX0_INT_ENABLECAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);#endifreturn 0;}#if CAN_RX0_INT_ENABLE //使能RX0中断//中断服务函数void USB_LP_CAN1_RX0_IRQHandler(void){CanRxMsg RxMessage;int i=0;CAN_Receive(CAN1, 0, &RxMessage);for(i=0;i<8;i++)printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);}#endif//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=0x12; // 标准标识符为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口接收数据查询//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总线的滤波等一系列设置可以参考:stm32的can总线的配置如下:????? CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式?????CAN_InitStructure.CAN_ABOM=DISABLE;?????CAN_InitStructure.CAN_AWUM=DISABLE;?????CAN_InitStructure.CAN_NART=DISABLE;//CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)?????? CAN_InitStructure.CAN_RFLM=DISABLE;????? CAN_InitStructure.CAN_TXFP=DISABLE;?????CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;????? //CAN_Mode_LoopBack????? //CAN_Mode_Normal????? CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;?????CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16?????CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8?????CAN_InitStructure.CAN_Prescaler=2;????? CAN_Init(&CAN_InitStructure);?????? /* CAN filter init */????? CAN_FilterInitStructure.CAN_FilterNumber=0;//选择过滤器0????? CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定过滤器被设置为标识符屏蔽模式?????CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//给出过滤器位宽为32位?下面根据设置的参数不同来决定can总线can总线的配置情况:1、对扩展数据帧进行过滤:(只接收扩展数据帧)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<3)&0xFFFF0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;(注:标准帧数据帧、标准远程帧和扩展远程帧均被过滤)2、对扩展远程帧过滤:(只接收扩展远程帧)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<3)&0xFFFF0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;3、对标准远程帧过滤:(只接收标准远程帧)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<21)&0xffff0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;4、对标准数据帧过滤:(只接收标准数据帧)????? CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<21)&0xffff0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;5、对扩展帧进行过滤:(扩展帧不会被过滤掉)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<3)&0xFFFF0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFC;6、对标准帧进行过滤:(标准帧不会被过滤掉)????? CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<21)&0xffff0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<21)|CAN_ID_STD)&0xffff;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFC;注:slave_id为要过滤的id 号。