打印
[STM32H7]

【STM32H745I-DISCO试用】3.2 DAC输出任意波形

[复制链接]
88|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
pzw1758|  楼主 | 2025-2-22 12:38 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
2.3任意波形CubeMX配置如下:(TIM6配置与之前一致)

添加DMA,减小CPU负担

2.3.1生成任意波的原理
        首先,需要对STM32的DAC模块进行基础配置,这包括选择DAC的分辨率(8位或12位)、配置DAC的输出通道、使能DAC的时钟等。在STM32中,DAC模块通常具有两个输出通道,每个通道都可以独立配置和使用。
        为了生成任意波形,需要事先准备好波形的数据。这些数据通常是一个数组,数组中的每个元素代表波形在一个时间点上的幅度值。例如,对于正弦波,可以使用数学公式计算出每个时间点的正弦值,并将这些值存储在数组中。对于其他类型的波形,如方波、三角波等,也可以使用类似的方法生成数据。
        STM32的DAC模块支持多种触发方式,包括定时器触发、软件触发等。为了生成连续的波形,通常会选择一个定时器作为DAC的触发源。定时器的溢出或更新事件可以触发DAC转换,并将新的数据写入DAC的数据寄存器。这样,随着定时器的不断计数,DAC就会连续输出波形数据,从而形成连续的波形。
        为了减轻CPU的负担并提高数据传输的效率,可以使用STM32的DMA控制器来传输波形数据到DAC的数据寄存器。DMA可以在不占用CPU的情况下,从内存读取数据并写入外设的数据寄存器。在配置DMA时,需要设置DMA的源地址(波形数据数组的起始地址)、目标地址(DAC的数据寄存器地址)、传输的数据量以及传输的方向等参数。
        一旦DAC和基础的外设(如定时器、DMA等)配置完成,并且波形数据已经准备好,就可以开始生成和输出波形了。当定时器触发DAC转换时,DMA(如果已配置)会自动将波形数据从内存传输到DAC的数据寄存器。然后,DAC将这些数字信号转换为模拟信号,并通过输出通道输出。最终,就可以在示波器或其他测量设备上观察到生成的波形了。
2.3.2代码实现#ifndef _WAVE_H_
#define _WAVE_H_

#include "main.h"
#include "dac.h"
#include "tim.h"

#define DAC_Length 256  //采样点
#define PI 3.1415926

void sin_wave(float Amp);
float cal_frq(void);
void sin_half(float Amp);
void sin_all(float Amp);
void swt_wave(float Amp);
void swt_wave_re(float Amp);
void triangle_wave(float Amp);
void sin_wave_rectangle(float Amp);
void sin_wave1(float Amp);
void sin_cos(float Amp);
void trapezoidal_wave(float Amp);
void wave_set(struct wave_para wave);

#endif
​#include "wave.h"
#include "arm_math.h"
#include "stdio.h"

extern uint16_t DAC_Value[DAC_Length];

void sin_wave(float Amp){
    double x;
    double sin_wave;
    double sin_class = (Amp/3.3*4095.0 - 100.0)/2.0;
    for(int i=0;i<DAC_Length;i++){
        x = 2*((double)i/(double)(DAC_Length-1))*(double)PI;
        sin_wave = arm_sin_f32(x) + 1;
        DAC_Value = (uint16_t)(sin_wave*sin_class)+100;
    }
}

float cal_frq(void){
    float frq;
    float tim6_frq;
   
    tim6_frq = (float)170000000 / (TIM6->PSC + 1)/ (TIM6->ARR + 1);
   
    frq = tim6_frq / DAC_Length;
   
    return frq;
}

void sin_half(float Amp){
    double x;
    double sin_wave;
    double sin_class = Amp/3.3*4095.0 - 100.0;
    for(int i=0;i<DAC_Length;i++){
        x = 2*((double)i/(double)(DAC_Length-1))*(double)PI;
        sin_wave = arm_sin_f32(x);
        if(sin_wave>0){
            DAC_Value = (uint16_t)(sin_wave*sin_class)+100;
        }else{
            DAC_Value = 0;
        }
    }
}

void sin_all(float Amp){
    double x;
    double sin_wave;
    double sin_class = Amp/3.3*4095.0 - 100.0;
    for(int i=0;i<DAC_Length;i++){
        x = 2*((double)i/(double)(DAC_Length-1))*(double)PI;
        sin_wave = fabs(arm_sin_f32(x));
        DAC_Value = (uint16_t)(sin_wave*sin_class)+100;
    }
}

void swt_wave(float Amp){//锯齿波  正向
    double swt_class = Amp/3.3*4095;
    for(int i=0;i<DAC_Length;i++){
        DAC_Value = (float)i/(float)(DAC_Length-1) * swt_class;
    }
}

void swt_wave_re(float Amp){//锯齿波  反向
    double swt_class = Amp/3.3*4095;
    for(int i=0;i<DAC_Length;i++){
        DAC_Value = swt_class - (float)i/(float)(DAC_Length-1) * swt_class;
    }
}

void triangle_wave(float Amp){
    double swt_class = Amp/3.3*4095;
    for(int i=0;i<DAC_Length;i++){
        if(i<DAC_Length/2){
            DAC_Value = 2*(float)i/(float)(DAC_Length-1) * swt_class;
        }else{
            DAC_Value = 2*swt_class - 2*(float)i/(float)(DAC_Length-1) * swt_class;
        }
    }
}

void sin_wave_rectangle(float Amp){
    double x;
    double sin_wave;
    double sin_class = Amp/3.3*4095.0/2.0;
    for(int i=0;i<DAC_Length;i++){
        x = 2*((double)i/(double)(DAC_Length-1))*(double)PI;
        //sin(x) + 1/3sin(3x) + 1/5sin(5x)不可能同时取最小和最大
        sin_wave = arm_sin_f32(x) + (double)1/3.0*arm_sin_f32(3*x) + (double)1/5.0*arm_sin_f32(5*x) + 1;
        DAC_Value = sin_wave*sin_class;
    }
}

void sin_wave1(float Amp){
    double x;
    double sin_wave;
    double sin_class = Amp/3.3*4095.0/2.0;
    for(int i=0;i<DAC_Length;i++){
        x = 2*((double)i/(double)(DAC_Length-1))*(double)PI;
        //sin(x) + 1/10sin(10x) 同时取最小和最大
        sin_wave = arm_sin_f32(x) + (double)1/10.0*arm_sin_f32(10*x) + 1.1;
        DAC_Value = sin_wave*sin_class;
    }
}

void sin_cos(float Amp){
    double x;
    double sin_wave;
    double sin_class = Amp/3.3*4095.0/2.0;
    for(int i=0;i<DAC_Length;i++){
        x = 2*((double)i/(double)(DAC_Length-1))*(double)PI;
        //sin(x) + 1/10sin(10x) 同时取最小和最大
        sin_wave = arm_sin_f32(x)*arm_cos_f32(10*x) + 1;
        DAC_Value = sin_wave*sin_class;
    }
}

void trapezoidal_wave(float Amp){
    double tra_class = Amp/3.3*4095.0/2.0;
    for(int i=0;i<DAC_Length;i++){
        if(i<DAC_Length/2){
            if(i<DAC_Length/8){
                DAC_Value = 8*(float)i/(float)(DAC_Length-1) * tra_class + tra_class;
            }else if(i>=3*DAC_Length/8){
                DAC_Value = 1.7*tra_class - 8*(float)i/(float)(DAC_Length-1) * tra_class;
            }else{
                DAC_Value = Amp/3.3*4095.0;
            }
        }else{
            if(i<=5*DAC_Length/8){
                DAC_Value = 1.72*tra_class - 8*(float)i/(float)(DAC_Length-1) * tra_class;
            }else if(i>=7*DAC_Length/8){
                DAC_Value = 8*(float)i/(float)(DAC_Length-1) * tra_class - 3.7*tra_class;
            }else{
                DAC_Value = 0;
            }
        }
    }
}

void wave_set(struct wave_para wave){
    HAL_TIM_Base_Stop_IT(&htim6);//关闭定时器
    switch(wave.num){
        case 0:
            sin_wave1(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 1:
            sin_wave(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 2:
            sin_half(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 3:
            sin_all(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 4:
            swt_wave(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 5:
            swt_wave_re(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 6:
            triangle_wave(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 7:
            sin_wave_rectangle(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 8:
            sin_cos(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        case 9:
            trapezoidal_wave(wave.amp);
            TIM6->ARR = (int)(100000000.0/(float)wave.frq/(float)DAC_Length)-1;
          printf("编号:%d 频率:%dHZ 幅度:%.3fV\r\n",wave.num,wave.frq,wave.amp);
            break;
        default:
            break;
    }
    HAL_TIM_Base_Start_IT(&htim6);//开启定时器
}
2.3.3生成波形展示
串口控制波形生成:
控制指令如:编号:0 频率:1000HZ 幅度:2.000V


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

8

帖子

0

粉丝