虽然STM32F103ZET6具有内部DAC,但是也仅仅只有两条DAC通道,并且STM32还有其他的很多型号是没有DAC的。通常情况下,采用专用的D/A芯片来实现,但是这样就会带来成本的增加。

不过STM32所有的芯片都有PWM输出,并且PWM输出通道很多,资源丰富。因此,我们可以使用PWM+简单的RC滤波来实现DAC的输出从而节省成本。

PWM DAC
PWM DAC的构成原理
PWM本质上其实就是是一种周期一定,而高低电平占空比可调的方波。实际电路的典型PWM波形,如下图所示:

针对PWM的波形进行以下分析:

高电平阶段:计数器当前值从0-CCRx阶段(总时间=CCRx*每两个计数之间的间隔时间);
低电平阶段:计数器当前值从CCRx-ARR-1阶段(总时间=(ARR-1-CCRx)*每两个计数之间的间隔时间)。
如果PWM内容如果不太懂,可以参考链接:【STM32】通用定时器的PWM输出(实例:PWM输出)。

根据PWM的波形,可以用分段函数来进行表示:

其中:T是STM32中计数脉冲的基本周期,也就是STM32定时器的计数频率的倒数;N是PWM波一个周期的计数脉冲个数,也就是STM32的ARR-1的值;n是PWM波一个周期中高电平的计数脉冲个数,也就是STM32的CCRx的值;VH和VL分别是PWM波的高低电平电压值;k为谐波次数;t为时间。

我们将分段函数①式展开成傅里叶级数,得到公式②:

从②式可以看出,式中第1个方括弧为直流分量,第2项为1次谐波分量,第3项为大于1次的高次谐波分量。

式②中的直流分量与n成线性关系,并随着n从0到N,直流分量从VL到VL+VH之间变化。而STM32的DAC功能也就是电压输出,这正是电压输出的DAC所需要的。

因此,如果能把式②中除直流分量外的谐波过滤掉,则可以得到从PWM波到电压输出DAC的转换,即:PWM波可以通过一个低通滤波器进行解调。式②中的第2项的幅度和相角与n有关,频率为1/(NT),其实就是PWM的输出频率。该频率是设计低通滤波器的依据。如果能把1次谐波很好过滤掉,则高次谐波就应该基本不存在了。

PWM DAC的具体实现
通过上面的了解,我们可以得到PWM DAC的分辨率,计算公式如下:

分辨率=log2(N)

这里假设n的最小变化为1,当N=256的时候,分辨率就是8位。而STM32的定时器都是16位的,可以很容易得到更高的分辨率,分辨率越高,速度就越慢。不过我们在本章要设计的DAC分辨率为8位。

在8位分辨条件下,我们一般要求1次谐波对输出电压的影响不要超过1个位的精度,也就是3.3/256=0.01289V。假设VH为3.3V,VL为0V,那么一次谐波的最大值是2*3.3/π=2.1V,这就要求我们的RC滤波电路提供至少-20lg(2.1/0.01289)=-44dB的衰减。

STM32的定时器最快的计数频率是72Mhz,8为分辨率的时候,PWM频率为72M/256=281.25Khz。如果是1阶RC滤波,则要求截止频率为1.77Khz,如果为2阶RC滤波,则要求截止频率为22.34Khz。

二阶RC滤波截止频率计算公式为:

f=1/2πRC

以上公式要求R55=R56=R,C63=C64=C(R55*C63=R56*C64=RC)。根据这个公式,我们计算出图25.1.2的截止频率为:33.8Khz超过了22.34Khz,这个和我们前面提到的要求有点出入,原因是该电路我们还需要用作PWM DAC音频输出,而音频信号带宽是22.05Khz,为了让音频信号能够通过该低通滤波,同时为了标准化参数选取,所以确定了这样的参数。实测精度在0.5LSB以内。

PWM DAC实例
硬件连接
单片机:STM32F103ZET6
硬件资源:指示灯DS0,WK_UP和KEY1按键,ADC,PWM DAC
具体的硬件连接的图如下所示:

  1. STM32控制程序
  2. //设置输出电压
  3. //vol:0~330,代表0~3.3V
  4. void PWM_DAC_Set(u16 vol)
  5. {
  6. float temp=vol;
  7. temp/=;
  8. temp=temp*/3.3;
  9. TIM_SetCompare1(TIM1,temp);
  10. }
  11. int main(void)
  12. {
  13. u16 adcx;
  14. float temp;
  15. u8 t=;
  16. u16 pwmval=;
  17. u8 key;
  18. delay_init(); //延时函数初始化
  19. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  20. uart_init(); //串口初始化为115200
  21. KEY_Init(); //KEY初始化
  22. LED_Init(); //LED端口初始化
  23. usmart_dev.init(); //初始化USMART
  24. LCD_Init(); //LCD初始化
  25. Adc_Init(); //ADC初始化
  26. TIM1_PWM_Init(,); //TIM1 PWM初始化, Fpwm=72M/256=281.25Khz.
  27. TIM_SetCompare1(TIM1,);//初始值为0
  28.  
  29. POINT_COLOR=RED;//设置字体为红色
  30. LCD_ShowString(,,,,,"WarShip STM32");
  31. LCD_ShowString(,,,,,"PWM DAC TEST");
  32. LCD_ShowString(,,,,,"ATOM@ALIENTEK");
  33. LCD_ShowString(,,,,,"2015/1/15");
  34. LCD_ShowString(,,,,,"WK_UP:+ KEY1:-");
  35. //显示提示信息
  36. POINT_COLOR=BLUE;//设置字体为蓝色
  37. LCD_ShowString(,,,,,"PWM VAL:");
  38. LCD_ShowString(,,,,,"DAC VOL:0.000V");
  39. LCD_ShowString(,,,,,"ADC VOL:0.000V");
  40.  
  41. TIM_SetCompare1(TIM1,pwmval);//初始值
  42. while()
  43. {
  44. t++;
  45. key=KEY_Scan();
  46. if(key==WKUP_PRES)
  47. {
  48. if(pwmval<)pwmval+=;
  49. TIM_SetCompare1(TIM1,pwmval); //输出
  50. }else if(key==KEY1_PRES)
  51. {
  52. if(pwmval>)pwmval-=;
  53. else pwmval=;
  54. TIM_SetCompare1(TIM1,pwmval); //输出
  55. }
  56. if(t==||key==KEY1_PRES||key==WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了
  57. {
  58. adcx=TIM_GetCapture1(TIM1);
  59. LCD_ShowxNum(,,adcx,,,); //显示DAC寄存器值
  60. temp=(float)adcx*(3.3/); //得到DAC电压值
  61. adcx=temp;
  62. LCD_ShowxNum(,,temp,,,); //显示电压值整数部分
  63. temp-=adcx;
  64. temp*=;
  65. LCD_ShowxNum(,,temp,,,0x80); //显示电压值的小数部分
  66. adcx=Get_Adc_Average(ADC_Channel_1,); //得到ADC转换值
  67. temp=(float)adcx*(3.3/); //得到ADC电压值
  68. adcx=temp;
  69. LCD_ShowxNum(,,temp,,,); //显示电压值整数部分
  70. temp-=adcx;
  71. temp*=;
  72. LCD_ShowxNum(,,temp,,,0x80); //显示电压值的小数部分
  73. t=;
  74. LED0=!LED0;
  75. }
  76. delay_ms();
  77.  
  78. }

---------------------
作者:Yngz_Miao
来源:CSDN
原文:https://blog.csdn.net/qq_38410730/article/details/80113841
版权声明:本文为博主原创文章,转载请附上博文链接!

【STM32】PWM DAC基本原理(实验:PWM实现DAC)的更多相关文章

  1. 图解单片机8位PWM、16位PWM中“位”的含义!

    今天 发现很多同学 搞不懂单片机的pwm中的位表示什么意思,如很多同学会问“8位pwm.16位pwm是什么意思啊,它们有什么区别啊,其中的‘位’表示什么意思啊”.对于这些问题,今天就给大家解释下,由于 ...

  2. DAC杂谈二 ——ADC和DAC常用技术术语

    采集时间 采集时间是从释放保持状态(由采样-保持输入电路执行)到采样电容电压稳定至新输入值的1 LSB范围之内所需要的时间.采集时间(Tacq)的公式如下: 混叠 根据采样定理,超过奈奎斯特频率的输入 ...

  3. WRTnode 的 HTTP Web PWM 调光实验(2016-05-16)

    前言 这里是节取自 物联网的任意门——WRTnode2R 评测 中的 http web PWM 调光灯实验,所以有一些前置设置如果没有描述清楚可参考该处. 正文 步骤一:编辑 html 文件放在 /w ...

  4. 关于STM32在程序中间修改PWM值的总结(原创)

    首先在STM32库函数里有这样一个函数 void TIM3_PWM_Init(u16 arr,u16 psc)   若TIM3_PWM_Init(7200,100)//设置频谱7200.分频100   ...

  5. stm32定时器输出移相PWM(非主从模式)

    背景:由于项目需要,需要stm32输出任意相角度的PWM 前提知识: 1.stm32定时器的Tim,一般有多个OC.具体差别根据型号来定. 2.定时器的使能,理论上是多个通道同时使能 3.TIM_OC ...

  6. 单片机pwm控制基本原理详解

    前言 PWM是Pulse Width Modulation的缩写,它的中文名字是脉冲宽度调制,一种说法是它利用微处理器的数字输出来对模拟电路进行控制的一种有效的技术,其实就是使用数字信号达到一个模拟信 ...

  7. 51单片机 | 模拟PWM调制控制实验

    ———————————————————————————————————————————— PWM(脉冲宽度调制) 对模拟信号电平进行数字编码的方法 - - - - - - - - - - - - - ...

  8. STM32的can现场总线实验心得

    最近在搞stm32实验板的can现场总线实验,之前只是搞过STC51的串口通信,相比之下,发觉can总线都挺复杂的.开始时,知道自己是新手,只知道can总线跟串行通信,485通信,I2C通信一样都是用 ...

  9. STM32之呼吸灯实验

    首先,我想引用一下在一片博文里 看到 的一段话,写的很详细, 首先来说,你要使用PWM模式你得先选择用那个定时器来输出PWM吧!除了TIM6.TIM7这两个普通的定时器无法输出PWM外,其余的定时器都 ...

随机推荐

  1. C# foreach内部原理

    我们知道使用foreach的一个要求是对象必须继承自IEnumerable接口 这样才可以进行迭代 那内部是怎么实现的呢 这个时候会将对应的foreach语句转换为一个while循环 并且通过Move ...

  2. Git之项目使用

    现在最为盛行的版本控制器,非git莫属了, 那就看看在项目中我们是如何使用它的吧 一. 在已经存在秘钥对的情况下,我们需要在本地进行相关配置 git config --global user.name ...

  3. 如何入门vue之二

    学习完指令之后我们需要学习的就是组件. 在学习组件前我们要了解一下 methods 用来处理事件的. computed用来计算属性  他就是类似于data一样只不过是动态的处理数据 里面写的方法当成属 ...

  4. python之路--MySQL数据库初识

    一 . MySQL安装 # 下载MySQL地址 https://dev.mysql.com/downloads # 要选稳定的,不要选最新的,稳定的就是半年以上没有出现过bug 现在5.6.43为绝大 ...

  5. django rest framework权限和认证

    Django rest framework之权限 一.Authentication用户认证配置 1.四种验证及官网描述: BasicAuthentication 此身份验证方案使用HTTP基本身份验证 ...

  6. nfs+keepalived高可用

    1台nfs主被服务器都下载nfs.keepalived yum install nfs-utils rpcbind keepalived -y 2台nfs服务器nfs挂载目录及配置必须相同 3.在主n ...

  7. SSH本地端口转发的理解

    ssh -L 3307:127.0.0.1:3306 user@ssh-server -N 其中127.0.0.1:3306是指 ssh-server要访问资源的ip和端口 而3307则是隧道的开口, ...

  8. table2excel使用

    原table2excel代码 /* * 采用jquery模板插件——jQuery Boilerplate * * Made by QuJun * 2017/01/10 */ //table2excel ...

  9. How to mount HFS EFI on macOS

    mount_hfs /dev/disk0s1 /volumes/efi

  10. 5.cgroup资源控制

    控制组( CGroups)是 Linux 内核的一个特性,主要用来对共享资源进行隔离.限制.审计等. 只有将分配到容器的资源进行控制,才能避免多个容器同时运行时对宿主机系统的资源竞争.每个控制组是一组 ...