FOC调试记录
1月13日,已完成PWM和ADC功能
1月20日,已完成串口与VOFA+的联调,可将3个ADC和角度值传递至VOFA+,VOFA+可控制STM32
Foc调试记录
一、使用DSP库计算正余弦
1.CUBEMX_添加DSP库
2.添加全局
,ARM_MATH_CM4
3.添加头文件
#include "arm_math.h"
arm_sin_f32();
arm_cos_f32();
二、生成PWM
使用TIM1定时器,中心对齐模式
4个通道均设置为PWM输出
PWM频率设置在20Khz,中心对齐模式
三、ADC注入通道采样
1.设置TIM1定时器
参照 二、生成PWM
通道4相关设置
中断设置
2.ADC设置
规则通道必须要有1个输入,这里选的是内部温度,但不测量
注入通道设置
3.程序设计
//开启
HAL_ADCEx_InjectedStart(&hadc1);
__HAL_ADC_ENABLE_IT(&hadc1, ADC_IT_JEOC);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
uint16_t volt[3] = {0};
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
volt[0] = hadc->Instance->JDR1;
volt[1] = hadc->Instance->JDR2;
volt[2] = hadc->Instance->JDR3;
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
4.用逻辑分析仪测PC13的频率
五、串口DMA
1.串口数据上传至VOFA+
总的思路是,将ADC采样得到的3个电流值和AS5600获得的角度值上传至上位机VOFA+。在CUBEMX中,需要开启USART的DMA。
VOFA+的JUSTFLOAT模式,接收并显示浮点数,再加上尾巴0, 0, 0x80, 0x7f即可
将浮点数转为4个字节
以为串口只能以字节为单位进行发送数据
//target: 需要转换的浮点数
//buf: 放入的数组
//beg: 放入数组的位置
void Float2Byte(float *target, unsigned char *buf, unsigned char beg)
{
unsigned char *point;
point = (unsigned char *)target; //得到float的地址
buf[beg] = point[0];
buf[beg + 1] = point[1];
buf[beg + 2] = point[2];
buf[beg + 3] = point[3];
}
建立发送数组
//1-4放ADC1,以此类推
//0, 0, 0x80,0x7f为VOFA+的JustFloat模式指定结尾
uint8_t tx_buffer[20]= {1, 2, 3, 4,5,6,7,8,9,10,11,12, 13,14,15,16,0, 0, 0x80, 0x7f};
//while(1)中放置
Float2Byte(&uaaa, tx_buffer, 0);
Float2Byte(&ubbb, tx_buffer, 4);
Float2Byte(&uccc, tx_buffer, 8);
Float2Byte(&angle_now, tx_buffer, 12);
定时器发送
//while(1)前开启定时器
HAL_TIM_Base_Start_IT(&htim4);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim_baseHandle)
{
if (tim_baseHandle->Instance == htim4.Instance)
{
HAL_UART_Transmit_DMA(&huart1, tx_buffer, 20);
}
}
2.串口指定下达至STM32
VOFA+发送的数据格式可以自己设置,在这里设置成P1=%4.0f!,即发送4位带符号的数字,只有0位小数。总共需要8个字节,但是如果发送-1234,则长度变成9位,为了STM32处理的简便性,我们只发送3位有效数字。
假设我们发送-123,即P1= -12!,注意在负号前,VOFA+会自动补齐一个空格。
VOFA+发送的数据格式可以自己设置,在这里设置成P1=%4.0f!,即发送4位带符号的数字,只有0位小数。总共需要8个字节,但是如果发送-1234,则长度变成9位,为了STM32处理的简便性,我们只发送3位有效数字。
假设我们发送-123,即P1= -12!,注意在负号前,VOFA+会自动补齐一个空格。
VOFA+数据 | P | 1 | = | - | 1 | 2 | ! | |
---|---|---|---|---|---|---|---|---|
给串口的ASC码 | 0x50 | 0x31 | 0x3d | 0x20 | 0x2d | 0x31 | 0x32 | 0x21 |
接收数据
#define Lens_Receive_Buffer 8
uint8_t stm32_receive_vofa_buffer[Lens_Receive_Buffer];
//while(1)前开启串口接收
HAL_UART_Receive_IT(&huart1, stm32_receive_vofa_buffer, Lens_Receive_Buffer);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_DMA(&huart1, stm32_receive_vofa_buffer, Lens_Receive_Buffer);
if (VerifyData(stm32_receive_vofa_buffer) == 1)
{
Analyze_VOFA_Data(stm32_receive_vofa_buffer);
}
}
校验及解析数据
校验数据
char VerifyData(uint8_t *data)
{
if (stm32_receive_vofa_buffer[0] == 'P' && stm32_receive_vofa_buffer[7] == '!')
{
return 1;
}
return 0;
}
解析数据
void Analyze_VOFA_Data(uint8_t *data)
{
switch (data[1])
{
case 0x31:
Foc.Target_Speed = Byte2Int(stm32_receive_vofa_buffer);
break;
case 0x32:
Foc.Target_Iq = Byte2Int(stm32_receive_vofa_buffer);
break;
case 0x33:
Foc.Target_Id = Byte2Int(stm32_receive_vofa_buffer);
break;
default:
break;
}
}