STM32 使用DMA+DAC+TIMER 输出正弦波
时间: 2023-06-29 19:14:15 浏览: 176
好的,以下是一个使用STM32的DMA、DAC和TIMER模块输出正弦波的示例程序。本示例程序使用的是STM32F103C8T6开发板和Keil MDK-ARM开发环境。
```c
#include "stm32f10x.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_tim.h"
#define PI 3.14159265
uint16_t sinWave[256]; //正弦波数据,共256个采样点
void generateSinWave(void)
{
int i;
for(i = 0; i < 256; i++)
{
sinWave[i] = (uint16_t)(2047.5 * sin(2 * PI * i / 256) + 2047.5); //使用2048作为偏置,将正弦波数据转换为12位DAC输出
}
}
int main(void)
{
generateSinWave(); //生成正弦波数据
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
//PA4配置成DAC1输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_InitTypeDef DAC_InitStructure;
//DAC1初始化
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO; //使用TIM2触发DAC转换
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用波形发生器
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; //不使用LFSR和三角波发生器
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //开启DAC输出缓冲区
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
DMA_InitTypeDef DMA_InitStructure;
//DMA1通道3配置
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R1); //DMA传输目的地址为DAC数据寄存器DHR12R1
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)sinWave; //DMA传输源地址为sinWave数组
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //DMA传输方向为从内存到外设
DMA_InitStructure.DMA_BufferSize = 256; //DMA传输数据量为256个采样点
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定,不需要增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度为半字(16位)
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存数据宽度为半字(16位)
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环模式,不断重复传输
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级为高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁用内存到内存模式
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel3, ENABLE); //使能DMA1通道3
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//TIM2初始化
TIM_TimeBaseStructure.TIM_Period = 71; //TIM2计数周期为72(72MHz / 72 = 1MHz)
TIM_TimeBaseStructure.TIM_Prescaler = 0; //TIM2时钟分频器为0
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_Cmd(TIM2, ENABLE); //使能TIM2
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
DAC_DMACmd(DAC_Channel_1, ENABLE); //使能DAC1 DMA传输
while(1);
}
```
该程序使用了DMA1、DAC和TIM2模块,通过DMA1从内存中读取正弦波数据并传输到DAC数据寄存器DHR12R1中,TIM2用作DAC转换触发器,每个周期输出一个采样点。
请注意,在本示例程序中,正弦波数据被存储在名为sinWave的数组中,根据DAC输出的分辨率,数组中的数据需要分别占据12位。在DMA传输过程中,每个采样点需要占据16位,因此在传输过程中,需要使用DMA_MemoryDataSize_HalfWord参数配置DMA传输时每个数据的大小。
另外,如果需要输出其他类型的波形,可以参考上述程序中的generateSinWave函数,自行生成对应的波形数据。
阅读全文