STM32_CAN接收
实验平台:
bxCAN简介
基本扩展CAN外设又称bxCAN,可与CAN网络进行交互。
筛选器
筛选器组的配置如下图所示:
接收状态
接收FIFO的状态如下图所示:
bxCAN共有四个专用的中断向量,如下图所示:
图中红框为接收相关的中断,对应接收到、接收满、上溢三种接收状态,以FIFO0中断为例:
中断接收程序
本程序采用的CAN1接口,采用筛选器0,并关联到FIFO1,采用FMP0位产生中断,采集四路电机的转子角度、转速、电流和温度。
h文件
#include "sys.h"
#include "stm32f4xx_can.h"//电机ID
typedef enum
{CAN_Motor1_RX_ID = 0x201,CAN_Motor2_RX_ID = 0x202,CAN_Motor3_RX_ID = 0x203,CAN_Motor4_RX_ID = 0x204,
}CAN_Message_ID;//电机测量值
typedef struct
{uint16_t real_angle; //转子机械角度[0,8191]对应[0,360°]int16_t real_rpm; //转子转速int16_t real_current; //实际转矩电流int8_t real_temp; //电机温度
}Motor_Measure_t;extern Motor_Measure_t Motor_Chassis[];u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);
void get_motor_measure(Motor_Measure_t *ptr, CanRxMsg* RxMessage);
c文件
#include "can.h"Motor_Measure_t Motor_Chassis[4] = {0};u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure;CAN_FilterInitTypeDef CAN_FilterInitStructure;NVIC_InitTypeDef NVIC_InitStructure;//使能相关时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//初始化GPIOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_8| GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOB, &GPIO_InitStructure);//引脚复用映射配置GPIO_PinAFConfig(GPIOB,GPIO_PinSource8,GPIO_AF_CAN1);GPIO_PinAFConfig(GPIOB,GPIO_PinSource9,GPIO_AF_CAN1);//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; //模式设置 CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tqCAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tqCAN_InitStructure.CAN_BS2=tbs2; //Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tqCAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1 //过滤器配置CAN_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位掩码,不对任何位进行匹配,将接收任意ID的消息CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0; //筛选器0关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活筛选器CAN_FilterInit(&CAN_FilterInitStructure); //初始化筛选器CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);return 0;
}//中断服务函数
void CAN1_RX0_IRQHandler(void)
{CanRxMsg RxMessage;u8 i = 0;if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET) //中断发生,接收到消息{CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0); //清除中断标志CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); //读取消息数据i = RxMessage.StdId - CAN_Motor1_RX_ID; //得到电机编号:0、1、2、3get_motor_measure(&Motor_Chassis[i], &RxMessage); //将4个电机的测量值存入结构体数组中}
}//电机测量值处理函数
void get_motor_measure(Motor_Measure_t *ptr, CanRxMsg* RxMessage)
{ptr->real_angle = (uint16_t)(RxMessage->Data[0]<<8 | RxMessage->Data[1]);ptr->real_rpm = (uint16_t)(RxMessage->Data[2]<<8 | RxMessage->Data[3]);ptr->real_current = (int16_t)(RxMessage->Data[4]<<8 | RxMessage->Data[5]);ptr->real_temp = RxMessage->Data[6];
}