• (29)STM32——PWM DAC实验笔记


    目录

    学习目标

    成果展示 

    介绍

    简介

    硬件

    代码

    总结 


    学习目标

            本节内容讲解的是有关PWM转DAC的知识点,其实这种做法我们已经不陌生了,因为在学习51单片机的时候,DA也是通过PWM来实现的。51单片机——AD/DA转换,好了,接下来就让我们开始吧!

    成果展示 

    PWM DAC

    介绍

    简介

            PWM 本质上其实就是是一种周期一定,而高低电平占空比可调的方波。 

     

            有时候,STM32F4 自带的 2 路 DAC 可能不够用,需要多路 DAC,外扩 DAC 成本又会高不少。此时,我们可以利用 STM32F4 的 PWM+简单的 RC 滤波(低通滤波,在51的时候介绍过)来实现 DAC 输出,从而节省成本。 在精度要求不是很高的时候,PWM+RC 滤波的 DAC 输出方式,是一种非常廉价的解决方案。

            视频中介绍时讲了许多的东西,包括傅里叶级数以及二阶滤波等知识点,这些东西我觉得靠这一个笔记不能完全讲透,就简单的概括一下。、

            首先是傅里叶级数,我们在大学一年级就学过高等数学,在级数那一章节就有提到傅里叶级数,我们可以将PWM的波形用一个傅里叶级数来表示,然后通过滤波,最后得到我们的DAC。

            然后是如何滤波的问题,这边我们使用的是低通滤波器,不了解的同学可以简单理解为,滤掉交流,留下直流。

    硬件

            我们使用 STM32F4 的 TIM9_CH2(PA3)输出 PWM,经过二阶 RC 滤波后,转换 为直流输出,实现 PWM DAC。同上一章一样,我们通过 ADC1 的通道 5(PA5)读取 PWM DAC 的输出,并在 LCD 模块上显示相关数值,通过按键和 USMART 控制 PWM DAC 的输 出值。我们需要用到 ADC 采集 DAC 的输出电压,所以需要在硬件上将 PWM DAC 和 ADC 短接起来

     代码

            这个和之前PWM是一样的,只不过改变了一下通道和使用的定时器。 

    1. #include "pwmdac.h"
    2. #include "led.h"
    3. #include "usart.h"
    4. void TIM9_CH2_PWM_Init(u16 arr,u16 psc)
    5. {
    6. GPIO_InitTypeDef GPIO_InitStructure;
    7. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    8. TIM_OCInitTypeDef TIM_OCInitStructure;
    9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE); //TIM9时钟使能
    10. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟
    11. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //GPIOA3
    12. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    13. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
    14. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    15. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    16. GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA3
    17. GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_TIM9); //GPIOA3复用位定时器9 AF3
    18. TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
    19. TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
    20. TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
    21. TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    22. TIM_TimeBaseInit(TIM9,&TIM_TimeBaseStructure);//初始化定时器9
    23. //初始化TIM14 Channel1 PWM模式
    24. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
    25. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    26. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    27. TIM_OCInitStructure.TIM_Pulse=0;
    28. TIM_OC2Init(TIM9, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM9 OC2
    29. TIM_OC2PreloadConfig(TIM9, TIM_OCPreload_Enable); //使能TIM9在CCR2上的预装载寄存器
    30. TIM_ARRPreloadConfig(TIM9,ENABLE);//ARPE使能
    31. TIM_Cmd(TIM9, ENABLE); //使能TIM9
    32. }

    1. include "sys.h"
    2. #include "delay.h"
    3. #include "usart.h"
    4. #include "led.h"
    5. #include "adc.h"
    6. #include "key.h"
    7. #include "pwmdac.h"
    8. int main(void)
    9. {
    10. u16 adcx;
    11. float temp;
    12. u8 t=0;
    13. u16 pwmval=0;
    14. u8 key;
    15. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    16. delay_init(168); //初始化延时函数
    17. uart_init(115200); //初始化串口波特率为115200
    18. LED_Init(); //初始化LED
    19. Adc_Init(); //adc初始化
    20. KEY_Init(); //按键初始化
    21. TIM9_CH2_PWM_Init(255,0); //TIM4 PWM初始化, Fpwm=168M/256=656.25Khz.
    22. TIM_SetCompare2(TIM9,pwmval); //初始值
    23. while(1)
    24. {
    25. t++;
    26. key=KEY_Scan(0);
    27. if(key==KEY0_PRES)
    28. {
    29. if(pwmval<250)pwmval+=10;
    30. TIM_SetCompare2(TIM9,pwmval); //输出
    31. }else if(key==KEY1_PRES)
    32. {
    33. if(pwmval>10)pwmval-=10;
    34. else pwmval=0;
    35. TIM_SetCompare2(TIM9,pwmval); //输出
    36. }
    37. if(t==100||key==KEY0_PRES||key==KEY1_PRES) //WKUP/KEY1按下了,或者定时时间到了
    38. {
    39. adcx=TIM_GetCapture2(TIM9);;
    40. printf ("DAC VAL:%d",adcx); //显示DAC寄存器值
    41. printf ("\r\n\r\n");
    42. temp=(float)adcx*(3.3/256);; //得到DAC电压值
    43. adcx=temp;
    44. printf("DAC VOL:%fV",temp); //显示电压值
    45. printf ("\r\n\r\n");
    46. adcx=Get_Adc_Average(ADC_Channel_5,20); //得到ADC转换值
    47. temp=(float)adcx*(3.3/4096); //得到ADC电压值
    48. adcx=temp;
    49. printf("ADC VOL:%fV",temp); //显示电压值
    50. printf ("\r\n\r\n");
    51. t=0;
    52. LED0=!LED0;
    53. }
    54. delay_ms(10);
    55. }
    56. }

    总结 

            其实这一章的知识在之前的51就详细的介绍过,再学一遍就当是复习了。

  • 相关阅读:
    ◢Django 自写分页与使用
    连小白都在用的电子期刊制作网站
    会员权益-需求调查:需要什么样的云服务器优惠
    JavaScript权威指南第七版 第二章笔记:词法结构
    LabVIEW生产者消费者架构
    【华为OD机试python】报数游戏【2023 B卷|100分】
    【博客444】Linux Macvlan
    Kafka
    11月了,焦虑烦躁,然后是无悲无喜
    乌云遮住了天空
  • 原文地址:https://blog.csdn.net/weixin_66578482/article/details/126440732