初级会员
- 积分
- 141
- 金钱
- 141
- 注册时间
- 2019-4-11
- 在线时间
- 36 小时
|
5金钱
问题描述:主控芯片为AT32F407,主频200Mhz,移植原子的电机控制程序。定时器计数频率为40Mhz。当电机处于均速,即最大速度时,比较向前的步进加载 motor->min_delay = 99。那么 脉冲频率为: 40Mhz/100*2) = 200khz。但是用示波器测得的实际频率为178khz。怀疑是中断函数处理时间过程,汇编调试为55步,时间为 55* 0.005us = 0.275us。 中断函数加变量err,记录最大时间为 12个定时器计数。时间 = 20*0.025us = 0.5us。
问题诉求:请大师指导是什么原因导致,实际频率为178khz。
int err = 0;
/**
* @brief 定时器比较中断
* @param htim:定时器句柄指针
* @note 无
* @retval 无
*/
void HAL_TIM_OC_DelayElapsedCallback(MotorData *motor ) // 200M 20M min0.5uS max 0.7uS
{
__IO uint32_t tim_count = 0;
__IO uint32_t tmp = 0;
//tim_count = tmr_counter_value_get(motor->tmr_x);
//tmp = tim_count + motor->step_delay/2; /* 整个C值里边是需要翻转两次的所以需要除以2 */
//tmr_channel_value_set(motor->tmr_x,motor->pwm_ch,tmp);
tmp = motor->tmr_x->cval;
motor->tmr_x->c4dt = motor->tmr_x->cval+motor->step_delay/2;
motor->i++; /* 定时器中断次数计数值 */
if(motor->i == 2) /* 2次,说明已经输出一个完整脉冲 */
{
motor->i = 0; /* 清零定时器中断次数计数值 */
switch(motor->run_state) /* 加减速曲线阶段 */
{
case STOP:
motor->step_count = 0; /* 清零步数计数器 */
motor->rest = 0; /* 清零余值 */
/* 关闭通道*/
tmr_channel_enable(motor->tmr_x,motor->pwm_ch,FALSE);
tmr_counter_enable(motor->tmr_x, FALSE);
//ST1_EN(EN_OFF);
motor->g_motion_sta = FALSE; /* 电机为停止状态 */
break;
case ACCEL:
motor->g_add_pulse_count++; /* 只用于记录相对位置转动了多少度 */
motor->step_count++; /* 步数加1*/
if(motor->dir == CW)
{
motor->g_step_position++; /* 绝对位置加1 记录绝对位置转动多少度*/
}
else
{
motor->g_step_position--; /* 绝对位置减1*/
}
motor->accel_count++; /* 加速计数值加1*/
motor->new_step_delay = motor->step_delay - (((2 *motor->step_delay) + motor->rest)/(4 * motor->accel_count + 1));/* 计算新(下)一步脉冲周期(时间间隔) */
motor->rest = ((2 * motor->step_delay)+motor->rest)%(4 * motor->accel_count + 1); /* 计算余数,下次计算补上余数,减少误差 */
if(motor->step_count >= motor->decel_start) /* 检查是否到了需要减速的步数 */
{
motor->accel_count = motor->decel_val; /* 加速计数值为减速阶段计数值的初始值 */
motor->run_state = DECEL; /* 下个脉冲进入减速阶段 */
}
else if(motor->new_step_delay <= motor->min_delay) /* 检查是否到达期望的最大速度 计数值越小速度越快,当你的速度和最大速度相等或更快就进入匀速*/
{
motor->last_accel_delay = motor->new_step_delay; /* 保存加速过程中最后一次延时(脉冲周期)*/
motor->new_step_delay = motor->min_delay; /* 使用min_delay(对应最大速度speed)*/
motor->rest = 0; /* 清零余值 */
motor->run_state = RUN; /* 设置为匀速运行状态 */
}
break;
case RUN:
motor->g_add_pulse_count++;
motor->step_count++; /* 步数加1 */
if(motor->dir == CW)
{
motor->g_step_position++; /* 绝对位置加1 */
}
else
{
motor->g_step_position--; /* 绝对位置减1*/
}
motor->new_step_delay = motor->min_delay; /* 使用min_delay(对应最大速度speed)*/
if(motor->step_count >= motor->decel_start && !motor-> isContinuous) /* 需要开始减速 */
{
motor->accel_count = motor->decel_val; /* 减速步数做为加速计数值 */
motor->new_step_delay = motor->last_accel_delay; /* 加阶段最后的延时做为减速阶段的起始延时(脉冲周期) */
motor->run_state = DECEL; /* 状态改变为减速 */
}
break;
case DECEL:
motor->step_count++; /* 步数加1 */
motor->g_add_pulse_count++;
if(motor->dir == CW)
{
motor->g_step_position++; /* 绝对位置加1 */
}
else
{
motor->g_step_position--; /* 绝对位置减1 */
}
motor->accel_count++;
motor->new_step_delay = motor->step_delay - (((2 * motor->step_delay) + motor->rest)/(4 * motor->accel_count + 1)); /* 计算新(下)一步脉冲周期(时间间隔) */
motor->rest = ((2 * motor->step_delay)+motor->rest)%(4 * motor->accel_count + 1); /* 计算余数,下次计算补上余数,减少误差 */
/* 检查是否为最后一步 */
if(motor->accel_count >= 0) /* 判断减速步数是否从负值加到0是的话 减速完成 */
{
motor->run_state = STOP;
motor->step_count = 0; /* 清零步数计数器 */
motor->rest = 0; /* 清零余值 */
/* 关闭通道*/
tmr_channel_enable(motor->tmr_x,motor->pwm_ch,FALSE);
tmr_counter_enable(motor->tmr_x, FALSE);
//ST1_EN(EN_OFF);
motor->g_motion_sta = FALSE; /* 电机为停止状态 */
}
break;
}
motor->step_delay = motor->new_step_delay; /* 为下个(新的)延时(脉冲周期)赋值 */
if(motor->homeParas.homeFlag)
{
Homing(motor);
}
}
err = (motor->tmr_x->cval - tmp)> err ? motor->tmr_x->cval - tmp:err;
}
|
-
最佳答案
查看完整内容[请看2#楼]
原因是当响应中断后再读取定时器的计数值,此时定时器的值已经已经向前计数了一小段时间。将程序改为读取比较值,或者直接把比较值向上加,就是标准的频率。但要注意,频率不能高到小于中断程序执行时间。
结帖。
|