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

提高stm32f103c8t6的PWM精度

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

  w/ d  k( \; k) ~% G( u! X! mvoid TIM1_PWM_Init(u16 arr,u16 psc)
2 S4 J. y. F$ a+ {{  
$ d+ V4 |: B: d- m+ \6 S        GPIO_InitTypeDef GPIO_InitStructure;                              
, F8 S$ D9 a( J6 Z2 W- i: R        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;- z$ z( @3 C4 [5 W% v1 U5 q9 Y
        TIM_OCInitTypeDef  TIM_OCInitStructure;9 \+ M% x4 f2 m& S; w
( s" U* z# {9 c
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);     // , N; g$ V4 u8 @9 U9 ^; T
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能
' a# M" t: T+ i, c: T5 |+ c
6 T: j* T. |+ h5 Q% W   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形0 c3 j5 W3 ]: p7 j
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1         //PA8是PWM输出
  s# M" l. S& [- c% a* O9 G        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            //复用推挽输出% v9 l% \% C" o2 ]
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 C( K$ @% d1 }' Y8 c
        GPIO_Init(GPIOA, &GPIO_InitStructure);& k4 P+ w/ h- x
   //定时器初始化       
4 y3 g, A9 T- V6 e) }! S. `; t        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
4 o7 ^) x* U3 J, \8 Y        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 & R. K- F8 w* E. x  ?
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
' h; X  {+ L" X# y- O1 m$ ?5 v: A        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式2 Z- L' l3 T7 i. k: D1 E  _
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
+ H5 n! ?6 }, n$ ]- F. ^' C   //初始化输出比较参数$ p: M0 f/ E1 r% y0 Q
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2: c; Q4 @8 b. P2 R6 v1 Q
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
* a  q9 |6 l4 V9 n( {4 e- Z        TIM_OCInitStructure.TIM_Pulse = 1350; //设置待装入捕获比较寄存器的脉冲值 1350--Low  200--High( U# v& X7 j: {) |. s( O  d
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高+ p/ M3 s6 o: M
        TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx, D: o( r: D# H% P' [' C. j& m: H
          //使能预装载寄存器; A: ]" N1 [% m
  TIM_CtrlPWMOutputs(TIM1,ENABLE);            //MOE 主输出使能。该函数操作的是TIM1 刹车和死区寄存器该函数并不是适合所有定时器的,
( q1 e+ h1 l& R                                        //只有部分定时器可以使用,例如,在stm32f0中,可用于TIM1, TIM15, TIM16以及TIM17,( V6 `1 Z( @7 h" \( R. J
                                        //在stm32f1中可用于TIM1, TIM8,TIM15, TIM16以及TIM17,如果在其它定时器中使用,$ _4 \* ]4 t1 K
                                        //可能会使STM32停留在某一处而无法继续执行下面的任务& {# l; ^$ `& |" a7 ^% y
        TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);  //CH1预装载使能         3 _: W) X5 R7 [7 ^5 \( ]
  TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
' c1 _5 k3 A, m" e8 \- S        TIM_Cmd(TIM1,ENABLE);  //使能TIM1
, h: F9 P, Q, e1 d) m7 H- |4 `1 v2 M. }8 t0 @
}& D) t, q  h4 }4 r1 ?9 E* @$ O
! ?. B( T! r- V* l) T3 B
: [2 M- D2 }! J2 D! s  v
+ D+ ~, {9 Q. N! U
然后在MAIN()中:
2 m3 s8 O) j1 ~9 J5 |& @/ t: F9 i( rint main()- k$ V0 d6 A. M. ^7 R
{
# C2 Z( u! Q/ t7 i" y* _5 Y" _TIM_SetCompare1(TIM1,1500);  //占空比=1000 / (2999+1)*100% = 50%# q% P' |. u# {
while(1)
& C7 L+ l9 r5 X0 U% M( t- E{
: w$ v7 Y' m7 O+ q$ a   ;
. T4 Q" {' E  u' X" {}
  S) m0 s2 P: Q3 Y" Q- x}6 m' @# g3 X" N2 v; o& O. i5 A
可以在PA8看到PWM波形。一顿操作:' t  C0 c+ M" x7 x9 |1 b; s
1.jpg # K; L: \" |& b& P
发现DAC输出精度,线性都不好。也不知道是运放的问题还是其他。网上一顿搂,改进PWM输出模拟量。1 q+ o2 m7 e5 r6 k0 o5 f% }
2.jpg ; S2 d+ S& N; U; B) O
效果好了不少。线性还是不好。. R8 |- `/ {/ ~1 B* [$ v5 f
于是将DAC又返回ADC采集加数字闭环。
; m2 k$ X5 G) ]: v+ c. ydac_d是期望输出的值,dac_out是送去PWM转换的值,vi是从DACOUT那里取出的电压ADC值。下面程序是数字反馈
& c" f8 x4 I) e6 q7 M+ R% G0 {6 lvoid dac_auto(void)$ O$ |& i- S6 f- K" ?, c
{5 U. ~' u; H1 d9 K
        u16 tmp;6 O3 a2 J* q7 |# p" u# w$ ^
       if((short int)vi>(dac_d+1))
+ y5 R% _; r( f# Q            {
; w5 ~9 X4 T- A  G* n                tmp=(short int)vi-dac_d;. S; l" ^7 p, z% ~8 ~8 {
                if(tmp>=220)dac_out-=170;
0 X. e9 N  _* F+ i: p( K                else if(tmp>=100)dac_out-=80;
9 b9 p# _1 K2 z6 C6 K' a' T                else if(tmp>=50)dac_out-=45;
: q9 c% R" k8 w" |) _/ |7 A, s- p                else if(tmp>=10)dac_out-=6;
$ x% k( g' \0 t( y/ c6 {4 @                else if(tmp>=5)dac_out-=2;. x  o, z& j2 ^; t" H7 L
                else dac_out-=1;
$ r0 B. a3 K+ [; D; G7 K, E9 s! r3 z             }
5 T; I) c& m- t9 P& {        else if((short int)vi<(dac_d-1))  s4 G8 e  Q; |3 s. R4 T$ u! N5 T
            {2 Q! t: B) P4 p2 D+ r' n
                tmp=dac_d-(short int)vi;; j2 W9 ]0 d0 J) L" g& g: `* S( c: K1 I
                if(tmp>=220)dac_out+=110;
8 K4 |+ X) E3 l                else if(tmp>=100)dac_out+=55;- h% E- d" m/ I0 s- J4 A4 O
                else if(tmp>=50)dac_out+=35;
5 s! Y) [, Q9 W0 d0 p                else if(tmp>=10)dac_out+=7;4 V* A% i4 f9 P
                else if(tmp>=5)dac_out+=3;9 Y9 n" D% O( o0 ]0 U; @
                else dac_out+=1;. R' `" L8 h% F
            }' B& ^- n' k+ m2 K. d- h  R+ P
                if(dac_out>=2999)dac_out=2999;
  _9 @  Q1 O+ r                if(dac_out<=1)dac_out=1;
% x! m) q4 G5 J$ d                TIM_SetCompare1(TIM1,dac_out);
9 T6 a5 i7 E; M( l) ~' s2 e. O        filter();! |# C% r! q7 a. H4 K' W
}6 N: c/ j4 y' ^, H

5 y  w4 |, A. n. O: ]! }# e经过处理,PWM输出的最终电压值波动小于1毫伏。+ t9 j: l: U- A+ m. V
赞 收藏 评论0 发布时间:2020-8-16 19:05

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版