你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

提高stm32f103c8t6的PWM精度

[复制链接]
xiongjx 发布时间:2020-8-16 19:05
刚从51转过来,不想投入太多的资金,选择某宝的小蓝板(bluePill),这个板可能是最便宜的了(7.6元包邮)。初步测试一下时钟,定时器,中断,DMA什么的。到ADC还比较满意,DAC就晕了(这个芯片没有DAC)。于是采用PWM出模拟值。先初始化;

void TIM1_PWM_Init(u16 arr,u16 psc)
{  
        GPIO_InitTypeDef GPIO_InitStructure;                              
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);     //
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能

   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1         //PA8是PWM输出
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
   //定时器初始化       
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
   //初始化输出比较参数
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_Pulse = 1350; //设置待装入捕获比较寄存器的脉冲值 1350--Low  200--High
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高
        TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
          //使能预装载寄存器
  TIM_CtrlPWMOutputs(TIM1,ENABLE);            //MOE 主输出使能。该函数操作的是TIM1 刹车和死区寄存器该函数并不是适合所有定时器的,
                                        //只有部分定时器可以使用,例如,在stm32f0中,可用于TIM1, TIM15, TIM16以及TIM17,
                                        //在stm32f1中可用于TIM1, TIM8,TIM15, TIM16以及TIM17,如果在其它定时器中使用,
                                        //可能会使STM32停留在某一处而无法继续执行下面的任务
        TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);  //CH1预装载使能         
  TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
        TIM_Cmd(TIM1,ENABLE);  //使能TIM1

}



然后在MAIN()中:
int main()
{
TIM_SetCompare1(TIM1,1500);  //占空比=1000 / (2999+1)*100% = 50%
while(1)
{
   ;
}
}
可以在PA8看到PWM波形。一顿操作:
1.jpg
发现DAC输出精度,线性都不好。也不知道是运放的问题还是其他。网上一顿搂,改进PWM输出模拟量。
2.jpg
效果好了不少。线性还是不好。
于是将DAC又返回ADC采集加数字闭环。
dac_d是期望输出的值,dac_out是送去PWM转换的值,vi是从DACOUT那里取出的电压ADC值。下面程序是数字反馈
void dac_auto(void)
{
        u16 tmp;
       if((short int)vi>(dac_d+1))
            {
                tmp=(short int)vi-dac_d;
                if(tmp>=220)dac_out-=170;
                else if(tmp>=100)dac_out-=80;
                else if(tmp>=50)dac_out-=45;
                else if(tmp>=10)dac_out-=6;
                else if(tmp>=5)dac_out-=2;
                else dac_out-=1;
             }
        else if((short int)vi<(dac_d-1))
            {
                tmp=dac_d-(short int)vi;
                if(tmp>=220)dac_out+=110;
                else if(tmp>=100)dac_out+=55;
                else if(tmp>=50)dac_out+=35;
                else if(tmp>=10)dac_out+=7;
                else if(tmp>=5)dac_out+=3;
                else dac_out+=1;
            }
                if(dac_out>=2999)dac_out=2999;
                if(dac_out<=1)dac_out=1;
                TIM_SetCompare1(TIM1,dac_out);
        filter();
}

经过处理,PWM输出的最终电压值波动小于1毫伏。
收藏 评论0 发布时间:2020-8-16 19:05

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版