stm32H750转RM3508电机(纯实践教程)

引言

因能力有限,该文章为个人只是简单配置操作为培训新人转电机,纯实践教程,理论知识在网上各是,这里不再多赘述。

cubamx配置

有个错误修改(对学习了上一个培训视频的,新建工程或者来学习的也可看看)

在上一个培训视频里配置好串口和定时器中断的工程基础上继续配置can口,但在此之前我们需要改一改时钟树的参数
我们需要把晶振频率设置和板子的一致我们需要把晶振频率设置和板子的一致

can参数设置

对activited勾选后对其basic parammeter参数配置,虽然不修改对设置can波特率没有啥影响,但个人操作下来不这么配置使用之后的函数不会正常运行在这里插入图片描述
fdcan2配置一样,看先前学长的配置不同之处在fdcan2的Message Ram Offset 给了1280

波特率计算配置

在Bit Timings Parameters界面中,需要进行CAN的波特率的配置,在B设置完分频系数 (Prescaler) 后,cubeMX 会自动完成 Time Quantum(简写为 tq)的计算,将 tq 乘以 seg1 (Time Quanta in Bit Segment 1),seg2 (Time Quanta in Bit Segment 1),再加一的和刚好为 1 微秒,对应波特率为 1M,这是 CAN 总线支持的最高通讯速率。
在这里插入图片描述
如图25*(31+8+1)ns=1us
如果发现Prescaler为3
时tq和图里不一样不是25ns
可以试试seg1和seg2换几个参数使normal time for one bit计算出1000ns,也可以在时钟树里修改frcan的分频把tq大小配置为25ns在这里插入图片描述

中断打开并优先分配

这里没啥好说的,can1,can2都是使能interrupt0
在这里插入图片描述
以can1为主can,优先级更高一些
在这里插入图片描述

代码部分

发送数据

完成以上配置后我们生成工程添加新的.c和.h文件来写电机单独的代码
首先需要初始化CAN通信过滤器并使能can控制器和中断

void CAN_Open(FDCAN_HandleTypeDef* can) 
{ 
    FDCAN_FilterTypeDef filter;                   	//< 声明局部变量 can过滤器结构体
	filter.IdType       = FDCAN_STANDARD_ID;       	//< id设置为标准id
	filter.FilterIndex  = 0;                      	//< 设值筛选器的编号,标准id选择0-127
	filter.FilterType   = FDCAN_FILTER_MASK;       	//< 设置工作模式为掩码模式
	filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; 	//< 将经过过滤的数据存储到 fifo0
	filter.FilterID1    = 0x000;                   	//< 筛选器的id
	filter.FilterID2    = 0x000;
	
	HAL_FDCAN_ConfigFilter(can, &filter);   //< 配置过滤器	
    check=HAL_FDCAN_Start(can);                   //< 使能can
    //该check来测试can控制器是否使能,可以把该赋值去掉	
	HAL_FDCAN_ActivateNotification(can, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);  // 使能fifo0接收到新信息中断

}

初始化滤波器之后就可以正常发送了,这里参考了官方的代码和学长代码凑了一个

/**
  * @brief CAN发送函数
  */
 uint8_t chassis_can_send_data[8];
uint8_t CAN_Send(FDCAN_HandleTypeDef* can,int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4 )
{
	FDCAN_TxHeaderTypeDef txHeader;
	txHeader.Identifier = (uint32_t)0x200;
	txHeader.IdType = FDCAN_STANDARD_ID;
	txHeader.TxFrameType = FDCAN_DATA_FRAME;
	txHeader.DataLength = FDCAN_DLC_BYTES_8;
	txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    txHeader.BitRateSwitch = FDCAN_BRS_OFF;
	txHeader.FDFormat = FDCAN_CLASSIC_CAN;
	txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
	txHeader.MessageMarker = 0x00;
	
	chassis_can_send_data[0] = motor1 >> 8; 
    chassis_can_send_data[1] = motor1; 
    chassis_can_send_data[2] = motor2 >> 8; 
    chassis_can_send_data[3] = motor2; 
    chassis_can_send_data[4] = motor3 >> 8; 
    chassis_can_send_data[5] = motor3; 
    chassis_can_send_data[6] = motor4 >> 8; 
	chassis_can_send_data[7] = motor4; 

if(HAL_FDCAN_AddMessageToTxFifoQ(can, &txHeader,chassis_can_send_data) != HAL_OK)
	{
			return 0;
	}
	else
	{
		return 1;
	}		
}

在这里插入图片描述

HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)
与上述图片里讲解使用差不多,但没参数4,可参考了解一下该函数

在这里插入图片描述
对于txHeader已是固定的了,不过标识符需要注意一下,如果不是3508前4个ID的电机,标识符会不一样,CAN_send函数可修改的是传入参数的can口和4个电机的电流,那看这个函数为什么通过给个8长度的数组就能确定不同电机的电流呢,欸,看这个表就知道数据在哪位对应哪个电机的电流都分配好了。所以这样写是没错的。
那接下来就是引用这个发送函数了,那就放到上一次我们建好了定时器中断里,没有定时器中断写在while循环里也行。在此之前肯定还需把初始化滤波器放到mian里执行一次对吧

CAN_Open(&hfdcan1);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	c=CAN_Send(&hfdcan1,400,400,400,400);
	//c是来测试是否正常发出的,未正常发出c会返回0
}

这里说明一些,这些电流值-16384 ~ 16384对应电流值-20 ~ 20A
这样电机就正常开环跑起来了,由于是给的电流值,那如果没什么阻力电机是会一直加速的,正常

接收中断

接下来任务就是我们需要接收电机反馈回来的速度角度等信息,这可为之后做闭环控制
首先定义一个结构体存放电机的返回状态
再定义一个结构体存放不同id的电机名称

typedef struct 
{ 
 uint16_t ecd; 
 int16_t speed_rpm; 
 int16_t given_current; 
 uint8_t temperate; 
 int16_t last_ecd; 
} motor_measure_t; 

/*CAN接收的ID*/
typedef enum
{
	//add by langgo
	CAN_3508Moto1_ID = 0x201,
	CAN_3508Moto2_ID = 0x202,
	CAN_3508Moto3_ID = 0x203,
	CAN_3508Moto4_ID = 0x204}CAN_Message_ID;

然后我们把接收状态结构体定义成四个电机变量

motor_measure_t motor_chassis[4] = {0};//4 chassis motor

宏定义一个函数来对接收到数据进行处理

#define get_motor_measure(ptr, data)\
 { \
 (ptr)->last_ecd = (ptr)->ecd; \
 (ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
 (ptr)->speed_rpm = (uint16_t)((data)[2] << 8 | (data)[3]); \
 (ptr)->given_current = (uint16_t)((data)[4] << 8 | (data)[5]); \
 (ptr)->temperate = (data)[6]; \
 } 

最后把这些东西引入到can接收回调函数里

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hcan,uint32_t RxFifo0ITs) 
{ 
	if(hcan==&hfdcan1)
	{
 FDCAN_RxHeaderTypeDef rx_header; 
 uint8_t rx_data[8]; 
 
 HAL_FDCAN_GetRxMessage(hcan, FDCAN_RX_FIFO0, &rx_header, rx_data); 
 
 switch (rx_header.Identifier) 
 { 
 case CAN_3508Moto1_ID: 
 case CAN_3508Moto2_ID: 
 case CAN_3508Moto3_ID: 
 case CAN_3508Moto4_ID: 

 { 
 static uint8_t i = 0; 
 //get motor id 
 i = rx_header.Identifier - CAN_3508Moto1_ID; 
 get_motor_measure(&motor_chassis[i], rx_data); 
	 
 break; 
 } 
 default: 
 { 
 break; 
 } 
 } 
	}
} 

至此,电机就能正常收发了
本教程参考了官方c板例程和实验室库,因为实验室库的这套代码的can太复杂而官方例程不是H750板子,于是个人擅自主张凑出来这套简单的转电机代码,旨在培训新人。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值