CAN的一般配置步骤:
① 配置相关引脚的复用功能,使能相应时钟
RCC_APBnPeriphClockCmd();//使能CAN和GPIOA时钟
GPIO_Init();//配置PA11为上拉输入(CAN_RX),PA12位复用输出(CAN_TX)
② 设置CAN工作模式及波特率等
CAN的主控制寄存器CAN_MCR(32位),高16位保留,[14:8]位保留
l 位16—DBF,调试冻结位;0:在调试时,CAN照常工作1:在调试时,冻结CAN的接收/发送。仍然可以正常地读写和控制接收FIFO。 l 位15—RESET, bxCAN软件复位;0:本外设正常工作;1:对bxCAN进行强行复位,复位后bxCAN进入睡眠模式(FMP位和CAN_MCR寄存器被初始化为其复位值)。此后硬件自动对该位清’0’。 l 位7—TTCM,时间触发通信模式;1:开启;0:关闭。 l 位6—ABOM,自动离线(Bus-Off)管理,决定CAN硬件在什么条件下可以退出离线状态。0:离线状态的退出过程是,软件对CAN_MCR寄存器的INRQ位进行置’1’随后清’0’后,一旦硬件检测到128次11位连续的隐性位,则退出离线状态;1:一旦硬件检测到128次11位连续的隐性位,则自动退出离线状态。 l 位5—AWUM,自动唤醒模式;决定CAN处在睡眠模式时由硬件还是软件唤醒;0:睡眠模式通过清除CAN_MCR寄存器的SLEEP位,由软件唤醒;1:睡眠模式通过检测CAN报文,由硬件自动唤醒。唤醒的同时,硬件自动对CAN_MSR寄存器的SLEEP和SLAK位清0。 l 位4—NART,禁止报文自动重传;1:CAN报文只被发送1次,不管发送的结果如何;0:0:按照CAN标准,CAN硬件在发送报文失败时会一直自动重传直到发送成功。 l 位3—RFLM,接收FIFO锁定模式;0:在接收溢出时FIFO未被锁定,当接收FIFO的报文未被读出,下一个收到的报文会覆盖原有的报文;1:在接收溢出时FIFO被锁定,当接收FIFO的报文未被读出,下一个收到的报文会被丢弃。 l 位2—TXFP,发送FIFO优先级;当有多个报文同时在等待发送时,该位决定这些报文的发送顺序0:优先级由报文的标识符来决定;1:优先级由发送请求的顺序来决定。 l 位1—SLEEP,睡眠模式请求。 l 位0—INRQ,初始化请求位。
CAN位时序寄存器CAN_BTR(32位),位[29:26]、[23]、[15:10]保留;
l 位31—SILM,静默模式(用于调试)。 l 位30—LBKM,环回模式(用于调试)。 l 位[25:24]—SJW[1:0], 重新跳跃宽度,CAN硬件在每位中可以延长或缩短多少个时间单位,tBJW=tCAN*(SJW[1:0]+1)。 l 位[22:20]—TS2[2:0],时间段2。 l 位[19:16]—TS1[1:0],时间段1. l 位[9:0]—BRP[9:0],被波特率分频器。
先进入初始化模式,然后进行设置,最后退出初始化模式。
CAN_Init(CAN1,&CAN_InitStructure);//使用结构体
typedef struct
{
uint16_t CAN_Prescaler;//设置分频系数
uint8_t CAN_Mode;//模式设置
uint8_t CAN_SJW;//设置重新同步跳跃宽度
uint8_t CAN_BS1;//设置时间段1占用的时间单位
uint8_t CAN_BS2;//设置时间段2占用的时间单位
FunctionalState CAN_TTCM;//是否为时间触发通信模式
FunctionalState CAN_ABOM;//是否为软件自动离线
FunctionalState CAN_AWUM;//是否为睡眠模式通过软件唤醒
FunctionalState CAN_NART;//是否开启报文自动传送
FunctionalState CAN_RFLM;//是否锁定报文,锁定即新的不覆盖旧的
FunctionalState CAN_TXFP;//优先级是否由报文标识符决定
} CAN_InitTypeDef;
③ 设置滤波器
CAN过滤器模式寄存器CAN_FM1R,位[13:0]—FBMx,过滤器模式选择;0:过滤器组x的2个32位寄存器工作在标识符屏蔽位模式;1:过滤器组x的2个32位寄存器工作在标识符列表模式。
CAN过滤器位宽寄存器CAN_FS1R,位[13:0]—FSCx,过滤器位宽设置;0:过滤器位宽为2个16位;1:单个32位。
CAN过滤器FIFO关联寄存器CAN_FFA1R,位[13:0]—FFAx,过滤器关联设置,0:过滤器关联到FIFO0;1:关联到FIFO1.
CAN过滤器激活寄存器CAN_FA1R。
CAN的过滤器组i的寄存器x CAN_FiRx,用来设置过滤器位。
进入初始化,然后设置,激活滤波器,最后退出初始化
CAN_FilterInit();//使用结构体
typedef struct
{
uint16_t CAN_FilterIdHigh;//设置32位ID高位
uint16_t CAN_FilterIdLow;//设置32位ID低位 uint16_t CAN_FilterMaskIdHigh;//设置32位mask id高位 uint16_t CAN_FilterMaskIdLow;//设置32位mask id低位 uint16_t CAN_FilterFIFOAssignment;//设置FIFO和过滤器的关联关系 uint8_t CAN_FilterNumber;//设置初始化的过滤器组 uint8_t CAN_FilterMode;//设置过滤器组的模式 uint8_t CAN_FilterScale;//设置过滤器组的位宽 FunctionalState CAN_FilterActivation;//是否激活过滤器 } CAN_FilterInitTypeDef;
至此CAN就可以开始工作了,初始化结束。
④ 发送/接收消息
CAN发送邮箱标识符寄存器CAN_TIxR(x=0~2),
l 位[31:21]—STID[10:0]/EXID[28:0],标准标识符或扩展标识符。 l 位[20:3]—EXID[17:0],扩展标识符的低字节。 l 位2—IDE,标识符选择,标准还是扩展。 l 位1—RTR,远程发送请求。 l 位0—TXRQ,发送数据请求,软件置1,请求发送邮箱里的数据;数据发送完成时,邮箱为空,由硬件置0。
CAN发送邮箱数据长度和时间戳寄存器CAN_TDTxR(X=0~2), 位[15:9]保留,位[7:4]保留。
l 位[31:16]—TIME[15:0],报文时间戳,在发送该报文SOF的时刻,16位定时器的值。 l 位8—TGT,发送时间戳,只有在CAN处于时间触发通信模式,该位才有效。 l 位[3:0]—DLC[3:0],发送数据长度。
CAN发送邮箱高/低字节数据寄存器CAN_TDLxR[x=0~2],该寄存器存储要发送的的数据,只存储4个字节,高低一共8个。
CAN_Transmit(CAN1,&TxMessage);//发送消息,使用结构体
typedef struct
{
uint32_t StdId;//设置标准标识符
uint32_t ExtId;//设置扩展标识符
uint8_t IDE;//标识符选择
uint8_t RTR;//数据帧还是远程帧
uint8_t DLC;//要发送的数据长度
uint8_t Data[8];//发送的数据数组
} CanTxMsg;
CAN接收FIFO邮箱标识符寄存器CAN_RIxR(x=0/1),用来保存接收到的报文标识符等信息,通过读该寄存器来获取相关信息;各位描述与CAN_TIxR类似,只有0位保留。
CAN接收FIFO邮箱数据长度和时间戳寄存器CAN_RDTxR、CAN接收FIFO邮箱高/低字节数据寄存器CAN_RDH/LxR。
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//接收消息,使用结构体
typedef struct
{
uint32_t StdId;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t Data[8];
uint8_t FMI;
} CanRxMsg;
⑤ ⑤ CAN状态获取
这里主要用到了以下几个:
CAN_TransmitStaus();//消息的状态
CAN_MessagePending();//是否接收到数据
CAN_GetFlagStaus();//获取CAN位的状态
使用到的库函数文件是stm32f10x_can相关文件。
11月6、7日
|