stm32f103can总线过滤器配置

CAN过滤器的配置(f103 hal1.8 系列)

can的过滤器的配置是对can接收到的报文进行过滤的配置,在STM32芯片中,可以对can的报文进行过滤,从而省略cpu的处理过程。

can的过滤模式

f103中为应用程序提供了14个位宽可变、可配置的过滤器组,每个过滤器组由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。
每个过滤器组的位宽都可以单独设置,以满足应用程序的不同需求。根据位宽的不同,可以配置为1个32位过滤器和2个16位过滤器。
can过滤器还可以分为屏蔽位模式和标识符列表模式。
其中:

  1. 标识符屏蔽位模式:FxR0为标识符匹配值,FxR1为屏蔽码。解释为FxR1中某一位为1,FxR0中相应的位置必须与收到的帧的标识符中的相应位置吻合才能通过过滤器。FxR1中为0的位表示FxR0的相应位可不必与收到的帧进行匹配。例如:标识符寄存器的bit15=0,屏蔽位寄存器的bit15=1,那么接受的Message里面的标识符的bit15必须为0才可能被硬件接受。如果屏蔽位寄存器的bit15=0,Message里面的标识符的bit15无论为什么值,bit15都能匹配通过,当bit0~31位都能通过的时候,这个报文就会被接受;
  2. 标识符列表模式:FR1和FR2都是要匹配的标识符,收到的帧的标识符必须与其中一个吻合才能通过过滤器;
    所有的过滤器都是并联的,一个报文只要能通过一个过滤器就算是有效的。

hal中的解释

在can的过滤器的配置的时候,需要用到结构体中FilterIdHigh,FilterIdLow,FilterMaskIdHigh,FilterMaskIdLow,这几个配置。在标识符列表模式下:ID和maskID在32位模式和16位模式的过滤器中都是代表着一个意思。在屏蔽位模式下,ID代表着标准值,而maskID代表着需要关心ID中的哪些位。其中高对应着高,低对应着低。

stm32f103can总线过滤器配置_第1张图片
其中IDE = 0为标准ID,IDE为1为扩展ID,RTR = 0为代表数据帧,RTR = 1代表远程帧,MASK设置屏蔽码,ID设置标准帧。

使用cube生成代码过程:

1、进行can配置
stm32f103can总线过滤器配置_第2张图片
上图主要的配置是进行can总线波特率的配置,波特率由p、tq1、tq2这三个数值进行确定。
2、进行中断配置stm32f103can总线过滤器配置_第3张图片
使用HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, RxData);可以读取CAN数据(RxMessage 的定义:CAN_RxHeaderTypeDef RxMessage;)
3、生成工程后进行添加过滤器的配置
进行32位过滤器屏蔽位模式设置

HAL_StatusTypeDef CAN_User_Init(CAN_HandleTypeDef *h_can) 
{
  CAN_FilterTypeDef sFilterConfig;
 
  sFilterConfig.FilterBank = 0;   //chenal 0
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //屏蔽模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  //设置为32位模式
  sFilterConfig.FilterIdHigh = 0xC020; //代表着设置的参考ID为0x601
  sFilterConfig.FilterIdLow = 0x0000;//代表着标准ID,而且是数据帧
  //MASK bit 0 means don't care,bit 0 means match 
  sFilterConfig.FilterMaskIdHigh = 0xFFFF;
  sFilterConfig.FilterMaskIdLow = 0xFFFF;//代表着需要符合上述所有的需求才能进行出传递报文
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; //FIFO0的中断和FIFO1的中断是不一样的,这里是把接收到的报文放入到FIFO0中
  sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;   //enable filter
  sFilterConfig.SlaveStartFilterBank = 0;    //为从属can选择开始的过滤库,对于单个CAN实例,这个参数没有意义
}

进行16位过滤器屏蔽位模式配置

HAL_StatusTypeDef CAN_User_Init(CAN_HandleTypeDef *h_can) 
{
  CAN_FilterTypeDef sFilterConfig;
 
  sFilterConfig.FilterBank = 0;   //chenal 0
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //屏蔽模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;  //设置为32位模式
  sFilterConfig.FilterIdHigh = 0xC020; //代表着设置的参考ID为0x601,标准ID,数据帧
  sFilterConfig.FilterIdLow = 0xD020;//代表着设置的参考ID为0x681,标准ID,数据帧
  //MASK bit 0 means don't care,bit 0 means match 
  sFilterConfig.FilterMaskIdHigh = 0xFFFF;//代表着需要是0x601的标准数据帧才能进行通过
  sFilterConfig.FilterMaskIdLow = 0xFFDF;//代表着需要是0x68x的标准数据帧才能通过。
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; //FIFO0的中断和FIFO1的中断是不一样的,这里是把接收到的报文放入到FIFO0中
  sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;   //enable filter
  sFilterConfig.SlaveStartFilterBank = 0;    //为从属can选择开始的过滤库,对于单个CAN实例,这个参数没有意义
}

注意以上只是一个过滤器的配置过程,f103可以进行14组过滤器的配置。

4、发送数据:

/*使用can总线发送数据*/
uint8_t CANx_SendNormalData(CAN_TxHeaderTypeDef TxHeader,uint32_t std_id ,uint8_t *TxData ,uint16_t lengh)
{
    uint32_t TxMailbox; 
	uint8_t  FreeTxNum=0;//用来表示邮箱是否空闲
		
    TxHeader.RTR = CAN_RTR_DATA;
    TxHeader.IDE = CAN_ID_STD;            
    TxHeader.StdId = std_id;
    TxHeader.TransmitGlobalTime = DISABLE;
    TxHeader.DLC = lengh;
		
    FreeTxNum = HAL_CAN_GetTxMailboxesFreeLevel(&hcan);
		while(0==FreeTxNum)
		{
			FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(&hcan);
		}
		
    if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, TxData, &TxMailbox) != HAL_OK)
    {
       /* Transmission request Error */
       Error_Handler();
    }
		return 1;
}

5、接收中断

/*采用接收中断函数*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *h_can)
{
  uint8_t Data[8] = {0};
	uint16_t nodeid = 0;
	HAL_StatusTypeDef	HAL_RetVal;
	uint8_t cmd = 0x2F;
//	uint16_t control_Mode = 0x6060;
	
  if (h_can == &hcan)
  {
    //retrive data by calling HAL_CAN_GetRxMessage
    HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &RxMessage, Data);
		nodeid = RxMessage.StdId;
		//对can1的速度进行接收
		if((nodeid&0x581) == 0x581)
		{
			if(Data[0] == cmd)
			{
				if(Data[1] == 0x60)
				{
					if(Data[2] == 0x60)
					{
						Real_Speed  =(int32_t)((uint32_t)(Data[4]&0xFF)|(uint32_t)((Data[5]<<8)&0xFFFF)|(uint32_t)((Data[6]<<16)&0xFFFF)|(uint32_t)((Data[7]<<24)&0xFFFF));
					}
				}
			}
		}
		if((nodeid&0x582) == 0x582)
		{
			//对can2的速度进行接收
			if(Data[0] == cmd)
			{
				if(Data[1] == 0x60)
				{
					if(Data[2] == 0x60)
					{
						Real_Speed  =(int32_t)((uint32_t)(Data[4]&0xFF)|(uint32_t)((Data[5]<<8)&0xFFFF)|(uint32_t)((Data[6]<<16)&0xFFFF)|(uint32_t)((Data[7]<<24)&0xFFFF));
					}
				}
			}
		}
  }
}

你可能感兴趣的:(stm32,常用接口方式)