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
|