STM32中CAN通信:简单的CAN发送代码和滤波器配置方法(16位和32位)

         我要用标准帧进行CAN通信,却找不到相关的例子,只好自己摸索,现在大致知道怎么配置,先放一下代码:

代码:

CAN.c的代码:

#include "stm32f10x.h"   


uint32_t Rx_COB_ID=0x0000;


void CAN1_Init(void)
{
	
	//时钟使能,低速总线APB1和低速总线APB2;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);//CAN端口重映射
	
	//GPIO初始化;
	
	GPIO_InitTypeDef GPIO_InitStructure;//PB8,对应CAN_RX,上拉输入GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);//PB9,对应CAN_TX,复用推挽输出GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	

	//CAN初始化;
	
	CAN_DeInit(CAN1);  //将外设CAN的全部寄存器重设为缺省值
	CAN_InitTypeDef CAN_InitStructure;
	CAN_InitStructure.CAN_ABOM = DISABLE;//用来使能或者失能自动离线管理, ENABLE 或者 DISABLE。
	CAN_InitStructure.CAN_AWUM = DISABLE;//用来使能或者失能自动唤醒模式, ENABLE 或者 DISABLE。
	CAN_InitStructure.CAN_NART = DISABLE;//用来使能或者失能非自动重传输模式, ENABLE 或者 DISABLE。
	CAN_InitStructure.CAN_RFLM = DISABLE;//用来使能或者失能接收 FIFO 锁定模式, ENABLE 或者 DISABLE。
	CAN_InitStructure.CAN_TTCM = DISABLE;//用来使能或者失能时间触发通讯模式,ENABLE 或者 DISABLE。
	CAN_InitStructure.CAN_TXFP = DISABLE;//用来使能或者失能发送 FIFO 优先级, ENABLE 或者 DISABLE。
	CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//CAN 的工作模式
	CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//定义了重新同步跳跃宽度(SJW),即在每位中可以延长或缩短多少个时间单位的上限
	CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;//设定了时间段 1 的时间单位数目
	CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;//设定了时间段 2 的时间单位数目
	CAN_InitStructure.CAN_Prescaler = 12;//设定了一个时间单位的长度,它的范围是 1 到 1024
    
	CAN_Init(CAN1,&CAN_InitStructure);

	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);		//FIFO0消息挂号中断允许

	//CAN Fliter初始化
	
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
	CAN_FilterInitStructure.CAN_FilterNumber=1;                     //指定过滤器为1
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   //指定过滤器为标识符屏蔽位模式
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;  //过滤器位宽为16位
    CAN_FilterInitStructure.CAN_FilterIdHigh=(Rx_COB_ID<<5)|0x18; //过滤器标识符的高8位值
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;	//过滤器标识符的低16位值
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(Rx_COB_ID<<5)|0x18;            
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;             
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;     
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;           
    CAN_FilterInit(&CAN_FilterInitStructure);
	


}

         因为我用的PB8、PB9引脚,所以要开启AFIO时钟,进行重映射;

CAN.h的代码:

#ifndef __CAN_H
#define __CAN_H

void CAN1_Init(void);

#endif

main.h的代码:

#include "stm32f10x.h"
#include "Delay.h"
#include "CAN.h"

extern uint32_t Rx_COB_ID;



int main(void)
{
	
	uint8_t arr[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
	uint8_t i;
	
	CAN1_Init();
	
	CanTxMsg   TxMessage;        //一个结构体,用来定义发送报文的
	TxMessage.StdId=Rx_COB_ID;    //标准ID
	TxMessage.ExtId=0;            //扩展ID,不使用扩展帧,写0
	TxMessage.IDE=CAN_ID_STD;    //标准帧还是扩展帧
	TxMessage.RTR=CAN_RTR_DATA;    //数据帧还是远程帧
	TxMessage.DLC=8;               //待传输数据长度

	for(i=0;i<8;i++)
	{			
		TxMessage.Data[i]=arr[i];
	}	
	
	CAN_Transmit(CAN1,&TxMessage);
	Delay_ms(200);

	
}

        上面代码用处不大,只有发送,没有接受和中断,只是方便我举个例子,主要讲这一段:

	//CAN Fliter初始化
	
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
	CAN_FilterInitStructure.CAN_FilterNumber=1;                     //指定过滤器为1
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   //指定过滤器为标识符屏蔽位模式
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;  //过滤器位宽为16位
    CAN_FilterInitStructure.CAN_FilterIdHigh=(Rx_COB_ID<<5); //过滤器标识符的高8位值
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;	//过滤器标识符的低16位值
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;            
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;             
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;     
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;           
    CAN_FilterInit(&CAN_FilterInitStructure);


滤波器配置:

CAN_FilterNumber

CAN_FilterNumber 指定了待初始化的过滤器,它的范围是 1 到 13。

        我选的是16位,屏蔽模式;(库函数)

        通过寄存器设置CAN_FS1R的相应FSCx位,可以配置一个过滤器组的位宽(32位还是16位),通过寄存器设置CAN_FMR的FBMx位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式或屏蔽位模式。(寄存器)

       

u16 CAN_FilterIdHigh; 放第一个COB_ID,位置要左移5位

u16 CAN_FilterIdLow; 放第二个COB_ID,位置要左移5位

u16 CAN_FilterMaskIdHigh; 放第一个屏蔽码,对应上面的第一个COB_ID

u16 CAN_FilterMaskIdLow; 放第二个屏蔽码,对应上面的第二个COB_ID

这个要解释一下:

        
比如假设第一个
COB_ID是0x201,左移5位,是因为这个寄存器从第5位开始放COB_ID,又因为RTR是数据帧,使用0,IDE是标准帧,使用0,就不用对这两位做什么配置了,默认就是0;

        第一个屏蔽码,假设为0x7FC,0b111 1111 1100;二进制是11位,对应上面STID[10:0]的11位;

        把COB_ID的十六进制0x201,写成二进制0b010 0000 0001,屏蔽码的1对应的位置必须一样,屏蔽码的0的位置可以随便写;

        这样,允许通过的COB_ID有0b010 0000 0000,0b010 0000 0011,0b010 0000 0001,0b010 0000 0010,对应的十六进制数就是0x200,0x203,0x201,0x202;

        第二个COB_ID与屏蔽码的关系也一样;不写也可以;

        最后选一个邮箱:

        

        

两个链接,超级全面详细的讲解:

【HAL库】STM32F407—-CAN通信—-过滤器配置_can过滤器_根号五的博客-CSDN博客

STM32 CAN通讯滤波器几种模式的设置_stm32can过滤器设置-CSDN博客

作者:再望断天涯

物联沃分享整理
物联沃-IOTWORD物联网 » STM32中CAN通信:简单的CAN发送代码和滤波器配置方法(16位和32位)

发表评论