STM32实验-PWM DAC模拟输出

一般一个STM32只有2个DAC输出通道,如果需要多路DAC输出,可以选择外扩DAC,但成本回相当高。于是在一些精度要求不高的场合,我们采用定时器输出PWM和RC滤波器模拟DAC来代替外扩DAC。

PWM占空比可由以下式子计算出:p = n / N (n是on的时间,即带宽,N是周期)

PWM周期是由ARR决定的,PWM占空比是由CCRx决定。ARR是自动重装载寄存器的数值,即定时器的锯齿波的最大值,CCRx是捕获/比较寄存器x的数值,是进行比较器comparator的正极电压。

于是我们知道,DAC输出电压为 = DORx / 4096 * Vref。对于分辨率 = log2 (N),比如N = 256,分辨率为8位。因为定时器的时钟频率往往更高,所以更容易获得更高的分辨率。本实验也以8位为例。

本实验的要求如下:要求一次谐波对输出电压影响不要超过一个位的精度,也就是3.3 / 256 = 0.01289V。假设Vh为3.3V,Vl为0V,这里的一次谐波的最大值为2 * 3.3 / pi = 2.1V。RC滤波电路要求是提供至少 -20lg(2.0 / 0.01289) = -44dB的衰减。截止频率要求为当定时器计数频率为72MHz,PWM DAC频率为8位时,PWM频率为72M / 256 = 281.25kHz,如果是一阶RC滤波,则要求截止频率为1.77kHz,如果是二阶RC滤波,则要求截止频率为22.34kHz。

对二阶RC滤波器来说,频率计算公式为f = (1 / (2 * pi)) *RC

接下来我们编写实验代码:

首先我们编写函数代码dac_pwm.c:

#include "dac_pwm.h"
#include "./BSP/TIMER/gtim.h"

TIM_HandleTypeDef g_timx_pwm_chy_handle;

void dac_pwm_init(uint16_t arr, uint16_t psc){

    TIM_OC_InitTypeDef timx_oc_pwm_chy;
 
    g_timx_pwm_chy_handle.Instance = TIM1;
    g_timx_pwm_chy_handel.Init.Prescaler = psc;
    g_timx_pwm_chy_handle.Init.Period = arr;
    g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;//向上计数模式
    g_timx_pwm_chy_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_PWM_Init(&g_timx_pwm_chy_handle);
 
    timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1;//选择PWM1模式
    timx_oc_pwm_chy.Pulse = 0;//设置占空比的比较值
    timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH;//输出极性:低极性
    HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, &timx_oc_pwm_chy, TIM_CHANNEL_1);
 
    HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, TIM_CHANNEL_1);

}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim){
    if(htim->Instance == TIM1){
        GPIO_InitTypeDef gpio_init_struct;
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_TIM1_CLK_ENABLE();
 
        
        gpio_init_struct.Pin = GPIO_PIN_8;
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;
        gpio_init_struct.Pull = GPIO_PULLUP;
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);
 
        __HAL_RCC_AFIO_CLK_ENABLE();
        __HAL_AFIO_REMAP_TIM3_PARTIAL();
    }
}

void dac_pwm_set_voltage(uint16_t vol){

    float temp = vol;
    temp /= 1000;
    temp = temp * 256 / 3.3;

    __HAL_TIM_SET_COMPARE(& timx_pwm_chy_handle, TIM_CHANNEL_1, temp);
}

接下来再编写函数头文件dac_pwm.h:

#ifndef __DAC_PWM_H
#define __DAC_PWM_H
 
#include "./SYSTEM/sys/sys.h"
 
extern TIM_HandleTypeDef g_timx_pwm_chy_handle;

void dac_pwm_init(uint16_t arr, uint16_t psc);
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim);
void dac_pwm_set_voltage(uint16_t vol);
 
#endif

最后编写主函数代码main.c:

#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/GTIM/gtim.h"
#include "./BSP/DAC/dac_pwm.h"
 
int main(void){
    uint16_t adcx = 0;
    float temp = 0;
    uint16_t t = 0;

    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    delay_init(72);
    led_init();
    lcd_init();
    dac_init();
    adc_init();
    dac_pwm_init(256 - 1, 0);

    dac_pwm_set_voltage(3300);
    lcd_show_string(30,  50, 200, 16, 16, "STM32F103", RED);
    lcd_show_string(30,  70, 200, 16, 16, "DAC TEST", RED);
    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "WK_UP:+  KEY1:-", RED);

    while (1)
    {
        adcx = adc_get_result();
        lcd_show_xnum(134, 110, adcx, 5, 16, 0, BLUE);

        temp = (float)adcx * (3.3 / 4096);
        adcx = temp;
        lcd_show_xnum(134, 130, adcx, 1, 16, 0, BLUE);

        temp -= adcx;
        temp *= 1000;
        lcd_show_xnum(150, 110, temp, 3, 16, 0x80, BLUE);

        LED0_TOGGLE();  /* LED0闪烁 */
        delay_ms(100);
    }
}

到这里我们的实验代码就编写完毕了。

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F103C8T6是一款常见的STM32系列微控制器,具有强大的功能和高性能。它也具备PWM输出功能,可用于模拟DACPWM(脉冲宽度调制)是一种常用的模拟信号产生技术。它通过调整脉冲宽度的占空比来模拟出不同的电平,从而实现模拟信号的输出。如果将PWM的输出通过一个低通滤波器进行滤波,就可以得到一个相对平滑的模拟电压输出。 在STM32F103C8T6上实现PWM模拟DAC的方法如下: 1. 配置GPIO引脚:选择一个合适的GPIO引脚作为PWM输出引脚。可以使用STM32的GPIO模块进行引脚配置。 2. 配置定时器:选择一个定时器作为PWM的计数器,并配置计数器的计数周期和分频系数。可以使用STM32的定时器模块进行配置。 3. 配置PWM输出模式:选择PWM输出模式,并设置PWM的占空比。可以使用STM32的定时器模块进行配置。 4. 启动定时器:启动定时器开始计数,并输出PWM信号。 5. 低通滤波:将PWM输出信号通过一个低通滤波器进行滤波,以获得一个平滑的模拟电压。 在实际应用中,可以根据需求选择不同的PWM输出频率和分辨率,以及合适的低通滤波器参数,以获得所需的模拟电压输出。 总之,使用STM32F103C8T6的PWM输出功能可以实现模拟DAC功能,通过配置GPIO引脚、定时器和PWM输出模式来生成PWM信号,并通过低通滤波器进行滤波,从而得到所需的模拟电压输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值