文章目录
1、PWM 绝对值位置读取功能
1.1 DataSheet说明
1.2 硬件支持
1.3 Cubemax配置及使用
1.4 项目代码实现
PWM输入捕获定时器初始化:
void MX_TIM4_Init(void)
{
/* USER CODE BEGIN TIM4_Init 0 */
/* USER CODE END TIM4_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM4_Init 1 */
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 83;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 0xFFFF;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_IC_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;
sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1;
sSlaveConfig.TriggerFilter = 0xA;
if (HAL_TIM_SlaveConfigSynchro(&htim4, &sSlaveConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0xA;
if (HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
if (HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
}
编码器初始化函数:
/**
* @brief
* @param void
* @retval void
*/
void Bsp_Encoder_Init(void)
{
if(sensor_peripheral.AuxEncoder_Sensor.encType==ENCODER_TYPE_MT_PWM_Abs)
{
MX_TIM4_Init();
HAL_TIM_IC_Start_IT (&htim4, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT (&htim4, TIM_CHANNEL_2);
ENC_485_RX_EN;
}
MX_TIM3_Init(); //ENC
HAL_TIM_Encoder_Start_IT(&htim3, TIM_CHANNEL_ALL);
}
输入捕获中断回调:
/**
* @brief Input Capture callback in non-blocking mode
* @param htim TIM IC handle
* @retval None
*/
#define TIM_ENCODER_PWM TIM4
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM_ENCODER_PWM) //
{
Encoder_MT_PWM_Readout();
}
}
输入捕获中断处理函数:
void Encoder_MT_PWM_Readout(void)
{
if (htim4.Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
enc_mt_pwm_input.freqTemp[0]=HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_2)+1; // 1.读取整周期时间
enc_mt_pwm_input.dutyTemp[0]=HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_1)+1; // 2.读取高电平时间
__HAL_TIM_SetCounter(&htim4, 0);
}
}
角度读取函数(包含数据处理):
uint16_t Bsp_get_PWM_angle(void)
{
enc_mt_pwm_input.usPwmAngReadFlag = 1;
enc_mt_pwm_input.freq=enc_mt_pwm_input.freqTemp[0];
enc_mt_pwm_input.duty=enc_mt_pwm_input.dutyTemp[0];
if(enc_mt_pwm_input.dir)
{
if(enc_mt_pwm_input.duty>=enc_mt_pwm_input.freq)
enc_mt_pwm_input.duty=enc_mt_pwm_input.freq;
else
enc_mt_pwm_input.duty=enc_mt_pwm_input.freq-enc_mt_pwm_input.duty; //get negation
}
enc_mt_pwm_input.factor=enc_mt_pwm_input.freq/enc_mt_pwm_input.div; //Acquire resolution
enc_mt_pwm_input.res=enc_mt_pwm_input.freq-(enc_mt_pwm_input.offset_h+enc_mt_pwm_input.offset_l)*enc_mt_pwm_input.factor;
if(enc_mt_pwm_input.duty>=enc_mt_pwm_input.factor * enc_mt_pwm_input.offset_h)
enc_mt_pwm_input.angle_temp=enc_mt_pwm_input.duty - enc_mt_pwm_input.factor * enc_mt_pwm_input.offset_h; //get angle
else
enc_mt_pwm_input.angle_temp=0;
enc_mt_pwm_input.angle=enc_mt_pwm_input.angle_temp*(4095/(enc_mt_pwm_input.res*(84/(ENC_PWM_INPUT_PRE+1)))); /* get value from 0 to 4095 */
return enc_mt_pwm_input.angle;
}
结构体定义及初始化:
#define SAMPLE_NUM 1 /* Number of samples */
typedef struct
{
uint8_t sample_count; /* counts of samples */
uint16_t freqTemp[SAMPLE_NUM]; /* Acquisition frequency */
float freq; /* frequency */
uint16_t dutyTemp[SAMPLE_NUM]; /* Capture high level */
float duty; /* duty */
uint8_t dir;
uint8_t offset_h; //16 high
uint8_t offset_l; //8 low
uint16_t div; //4095+16+8=4119
float factor;
float res; /* Resolution */
float angle_temp;
uint16_t angle;
uint8_t usPwmAngReadFlag;
}enc_mt_pwm_input_t;
extern enc_mt_pwm_input_t enc_mt_pwm_input;
/************************************************************************************/
enc_mt_pwm_input_t enc_mt_pwm_input={
.sample_count=0,
.freqTemp={0},
.freq=0,
.dutyTemp={0},
.duty=0,
.dir=1,
.offset_h=16,
.offset_l=8,
.div=4119,
.factor=0,
.res=0,
.angle=0,
.usPwmAngReadFlag = 0
};
1.5 效果验证
角度(占空比)周期化变化,满足预期。
1.6 注意事项
2、SPI 绝对值位置读取功能
2.2 硬件支持
MT6825编码器电路
驱动板电路
2.3 Cubemax配置及使用
2.4 项目代码实现
SPI外设初始化:
/* SPI1 init function */
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; //8 10.5Mbit/s 64 1.3125Mbits 16 5.25Mbit/s
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
结构体及初始化:
typedef struct{
uint16_t cmd[3];
uint16_t rec_data[3];
uint8_t no_mag_warning_flag;
uint8_t over_speed_flag;
uint8_t pc1_flag;
uint8_t pc2_flag;
uint8_t pc1_count;
uint8_t pc2_count;
uint8_t err;
uint32_t sample_data;
uint32_t angle_data;
uint32_t pre_angle_data;
}mag_enc_t;
extern mag_enc_t mag_enc;
/**********************************************************/
mag_enc_t mag_enc = {
.cmd = {0x8300, 0x8400, 0x8500},
.rec_data = {0, 0, 0},
.no_mag_warning_flag = 0,
.over_speed_flag = 0,
.pc1_flag = 0,
.pc2_flag = 0,
.pc1_count = 0,
.pc2_count = 0,
.err = 0,
.sample_data = 0,
.angle_data =0,
.pre_angle_data =0
};
SPI读取绝对值位置:
uint32_t SPI1_MT6825_fast_ReadData(void)
{
short timeOut=1000;
SPI1_CS_LOW;
// HAL_SPI_Transmit(&hspi1 ,(unsigned char *)&mag_enc.cmd[0] ,1,200);
// HAL_SPI_Receive(&hspi1 ,(unsigned char *)&mag_enc.rec_data[0] ,3,200);
HAL_SPI_TransmitReceive(&hspi1 ,(unsigned char *)&mag_enc.cmd[0] ,(unsigned char *)&mag_enc.rec_data[0] ,3,200 );
while( hspi1.State == HAL_SPI_STATE_BUSY )
{
if (timeOut-- ==0) return 0;
} // wait for transmission complete
SPI1_CS_HIGH;
mag_enc.angle_data=((mag_enc.rec_data[0]&0x00FF)<<10)+((mag_enc.rec_data[1]&0xFC00)>>6)+((mag_enc.rec_data[1]&0x00F0)>>4);
return mag_enc.angle_data;
}