一、单片机也好,嵌入式也好,甚至手机也一样,硬件设计与软件设计相互相承,从苹果手机使用了比安卓手机低得多硬件水平,但系统的流畅度好很多就可以看出,硬件设计影响了软件的设计。
二、从两次的电机H桥驱动电路,第二次设计只增加一个简单的换向电路,软件从一大段节省到只需2行
三、第一次的H桥电路,2个半桥的驱动是直连到MCU IO口来进行换向及PWM输出,也正因为这个原因,PWM只能软件IO翻转实现,频率高了中断太频繁占用时间太多,频率低了调整效果不理想,而且实现的代码也一大段。
这段是根据设定的占空比输出PWM
void TEC_PWM_Config(uint8_t chn, uint8_t PN_Flag, uint8_t duty)
{
if( chn > TEMP_MAX-1 )
return;
pwm_config_t *pwm_config_ptr = tec_driver_pwm(chn);
duty>=100?duty=100:(duty=duty);
if( chn<=TEMP_TEC7 ){
if( PN_Flag == 0){//关闭
//加入GPIO控制
pwm_config_ptr->u8HeatFlag=0;
pwm_config_ptr->u8CoolFlag=0;
pwm_config_ptr->u8Duty=0;
tec_drv_pwm(chn, 0);
pwm_config_ptr->u8StepH_Cnt=0;
rt_thread_delay(1);
}
else if( PN_Flag == 1){//需要
//加入GPIO控制
pwm_config_ptr->u8HeatFlag=0;//关闭加热标志位
pwm_config_ptr->u8CoolFlag=0;//关闭制冷标志位
tec_drv_pwm(chn, duty);
pwm_config_ptr->u8Duty=Duty; //配置PWM占空比
pwm_config_ptr->u8StepH_Cnt=0;//清零PWM计算步数
pwm_config_ptr->u8HeatFlag=1; //使能加热标志位
}
else if( PN_Flag == 2){//需要
//加入GPIO控制
pwm_config_ptr->u8HeatFlag=0;//关闭加热标志位
pwm_config_ptr->u8CoolFlag=0;//关闭制冷标志位
rt_pin_write(pwm_config_ptr->n_pin, TEC_N_OFF);
rt_pin_write(pwm_config_ptr->p_pin, TEC_P_OFF);
rt_pin_write(pwm_config_ptr->pwm_pin, TEC_PWM_OFF);
rt_thread_delay(1);
rt_pin_write(pwm_config_ptr->en_pin, TEC_EN_ON);
pwm_config_ptr->u8Duty=Duty; //配置PWM占空比
pwm_config_ptr->u8StepH_Cnt=0;//清零PWM计算步数
pwm_config_ptr->u8CoolFlag=1; //使能制冷标志位
}
}
else if( chn==TEMP_COVER ){
if( PN_Flag == 0){//关闭
//加入GPIO控制
pwm_config_ptr->u8HeatFlag=0;
pwm_config_ptr->u8CoolFlag=0;
pwm_config_ptr->u8Duty=0;
rt_pin_write(pwm_config_ptr->pwm_pin, HOT_PLATE_OFF);
pwm_config_ptr->u8StepH_Cnt=0;
}
这段代码是配置PWM的占空比及设置相应的状态变量
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if( htim == &htim9){
//实测168M主频下,函数执行时间为2us
PWM_CONTROL();
}
}
定时器的中断,200HZ,5ms中断一次,虽然说也能实现,但不是最优方案,上层应用被频繁的打断
三、第二次改进,以硬件PWM产生,PWM频率上1K~10K都轻松实现,也不需频繁中断占用CPU资源,同时管理20个PWM,驱动20路电机也不成问题,其中最关键的就这个H桥换向电路
H桥换向电路
开关模拟的H桥的换向,脉冲模拟的是PWM输出,2个LED模拟H桥的输出,直接连接到H桥DRV_N,DRV_P,可以看到LED轮流闪动,如需关闭H桥输出PWM引脚为一直低电平即可,4001是用于高电平驱动H桥电路,4011用于低电平驱动H桥电路
motor_drv_pwm(uint8_t chn, uint8_t ctrl, uint8_t duty)
{
dir = ctrl;
set_chn_pwm(chn, (float)duty/100.0*MAX_PWM_VALUE);
}
提供给上层PID计算后输出调用,省略了PWM初始化部分,但使用比原来的简化很多