DAC产生正弦波

DAC+DMA产生正弦波。适用于stm32f1系列的单片机

DMA的初始化 
 
#include "dma.h" 
 
extern u16 DualSine12bit[500];  
 
void MY_DMA_Init() 
{ 
DMA_InitTypeDef DMA_InitSt; 
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE); 
DMA_DeInit(DMA2_Channel3); 
 
DMA_InitSt.DMA_PeripheralBaseAddr = (u32)&DAC->DHR12R1;// 
DMA_InitSt.DMA_MemoryBaseAddr = (u32)DualSine12bit; 
DMA_InitSt.DMA_DIR = DMA_DIR_PeripheralDST; 
DMA_InitSt.DMA_BufferSize = 500;//每次传输数据量大小 
DMA_InitSt.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
DMA_InitSt.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitSt.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
DMA_InitSt.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;/ 
DMA_InitSt.DMA_Mode = DMA_Mode_Circular; 
DMA_InitSt.DMA_Priority = DMA_Priority_Medium; 
DMA_InitSt.DMA_M2M = DMA_M2M_Disable; 
DMA_Init(DMA2_Channel3,&DMA_InitSt); 
 
DMA_Cmd(DMA2_Channel3,ENABLE); 
 
} 
 
 
DAC的初始化 
#include "dac.h" 
 
void my_dac_Init(void) 
{ 
DAC_InitTypeDef DAC_xx; 
GPIO_InitTypeDef GPIO_xx; 
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE); 
 
GPIO_xx.GPIO_Pin = GPIO_Pin_4; 
GPIO_xx.GPIO_Mode = GPIO_Mode_AIN; 
GPIO_Init(GPIOA,&GPIO_xx); 
 
DAC_DeInit(); 
DAC_xx.DAC_Trigger = DAC_Trigger_T2_TRGO; 
DAC_xx.DAC_LFSRUnmask_TriangleAmplitude =DAC_LFSRUnmask_Bit0; 
DAC_xx.DAC_OutputBuffer =DAC_OutputBuffer_Disable; 
DAC_xx.DAC_WaveGeneration =DAC_WaveGeneration_Triangle; 
DAC_Init(DAC_Channel_1,&DAC_xx); 
 
DAC_Cmd(DAC_Channel_1,ENABLE); 
 
//	DAC_SetChannel1Data(DAC_Align_12b_R,2048); 
 
} 
 
触发定时器的初始化 
void TIM2_Int_Init(u16 arr,u16 psc) 
{ 
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 
NVIC_InitTypeDef NVIC_InitStructure; 
 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  
 
//定时器TIM3初始化 
TIM_TimeBaseStructure.TIM_Period = arr; 
TIM_TimeBaseStructure.TIM_Prescaler =psc;  
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  
  
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );  
 
//中断优先级NVIC设置 
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;   
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
NVIC_Init(&NVIC_InitStructure);   
 
    TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update); 
TIM_Cmd(TIM2, ENABLE);   
} 
 
 
设置了个数组存放正弦波的数据 
const u16 Sine12bit2[500] = {   
                      2048,2073,2099,2125,2150,2176,2202,2227,2253,2279,2304,2330,2355,2380, 
2406,2431,2456,2482,2507,2532,2557,2582,2606,2631,2656,2680,2705,2729,2753, 
2777,2801,2825,2849,2872,2896,2919,2942,2966,2988,3011,3034,3056,3079,3101, 
3123,3145,3166,3188,3209,3230,3251,3272,3292,3313,3333,3353,3372,3392,3411, 
3430,3449,3468,3486,3504,3522,3540,3558,3575,3592,3609,3625,3641,3657,3673, 
3689,3704,3719,3734,3748,3762,3776,3790,3803,3816,3829,3842,3854,3866,3878, 
3889,3900,3911,3921,3932,3942,3951,3961,3970,3978,3987,3995,4003,4010,4017, 
4024,4031,4037,4043,4048,4054,4059,4063,4068,4072,4075,4079,4082,4085,4087, 
4089,4091,4092,4094,4094,4095,4095,4095,4094,4094,4092,4091,4089,4087,4085, 
4082,4079,4075,4072,4068,4063,4059,4054,4048,4043,4037,4031,4024,4017,4010, 
4003,3995,3987,3978,3970,3961,3951,3942,3932,3921,3911,3900,3889,3878,3866, 
3854,3842,3829,3816,3803,3790,3776,3762,3748,3734,3719,3704,3689,3673,3657, 
3641,3625,3609,3592,3575,3558,3540,3522,3504,3486,3468,3449,3430,3411,3392, 
3372,3353,3333,3313,3292,3272,3251,3230,3209,3188,3166,3145,3123,3101,3079, 
3056,3034,3011,2988,2966,2943,2919,2896,2872,2849,2825,2801,2777,2753,2729, 
2705,2680,2656,2631,2606,2582,2557,2532,2507,2482,2456,2431,2406,2381,2355, 
2330,2304,2279,2253,2227,2202,2176,2150,2125,2099,2073,2048,2022,1996,1970, 
1945,1919,1893,1868,1842,1816,1791,1765,1740,1715,1689,1664,1639,1613,1588, 
1563,1538,1513,1489,1464,1439,1415,1390,1366,1342,1318,1294,1270,1246,1223, 
1199,1176,1153,1129,1107,1084,1061,1039,1016,994,972,950,929,907,886,865, 
844,823,803,782,762,742,723,703,684,665,646,627,609,591,573,555,537,520, 
503,486,470,454,438,422,406,391,376,361,347,333,319,305,292,279,266,253, 
241,229,217,206,195,184,174,163,153,144,134,125,117,108,100,92,85,78,71, 
64,58,52,47,41,36,32,27,23,20,16,13,10,8,6,4,3,1,1,0,0,0,1,1,3,4,6,8,10, 
13,16,20,23,27,32,36,41,47,52,58,64,71,78,85,92,100,108,117,125,134,144, 
153,163,174,184,195,206,217,229,241,253,266,279,292,305,319,333,347,361, 
376,391,406,422,438,454,470,486,503,520,537,555,573,591,609,627,646,665, 
684,703,723,742,762,782,803,823,844,865,886,907,929,950,972,994,1016,1039, 
1061,1084,1107,1129,1153,1176,1199,1223,1246,1270,1294,1318,1342,1366,1390, 
1415,1439,1464,1489,1513,1538,1563,1588,1613,1639,1664,1689,1715,1740,1765, 
1791,1816,1842,1868,1893,1919,1945,1970,1996,2022};   
 
u16 DualSine12bit[500]={0};

如果对您的问题有帮助的话可以帮忙点个赞,谢谢~QQ群:540093471 有问题大家可以一起交流沟通!

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要使用STM32DAC模块产生正弦波,可以使用以下步骤: 1. 初始化DAC模块,包括时钟使能、GPIO配置和DAC配置等; 2. 定义正弦波数组,可以使用sin函数计算出每个采样点的数值; 3. 启动定时器以固定的采样率产生DAC数据; 4. 在定时器中断中,将正弦波数组中下一个采样点数据写入DAC数据寄存器中; 5. 监测DAC中断标志位,确保数据已经输出完毕。 下面是一个基于STM32CubeMX和HAL库的DAC产生正弦波的例子代码: ```c #include "main.h" #include <math.h> #define SAMPLE_RATE 20000 // 20kHz采样率 #define SAMPLE_NUM 100 // 正弦波采样点数 DAC_HandleTypeDef hdac; TIM_HandleTypeDef htim6; static uint16_t sinewave[SAMPLE_NUM]; // 正弦波数据数组 static void MX_GPIO_Init(void); static void MX_DAC_Init(void); static void MX_TIM6_Init(void); void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim); int main(void) { HAL_Init(); MX_GPIO_Init(); MX_DAC_Init(); MX_TIM6_Init(); for (int i = 0; i < SAMPLE_NUM; i++) { sinewave[i] = (uint16_t)(2048 * (1 + sin(2 * M_PI * i / SAMPLE_NUM))); // 生成正弦波数据,最大输出值为4095(12位DAC) } HAL_DAC_Start(&hdac, DAC_CHANNEL_1); HAL_TIM_Base_Start_IT(&htim6); while (1) { // Main loop } } static void MX_DAC_Init(void) { DAC_ChannelConfTypeDef sConfig = {0}; hdac.Instance = DAC; if (HAL_DAC_Init(&hdac) != HAL_OK) { Error_Handler(); } sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO; // DAC使用定时器6触发 sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK) { Error_Handler(); } } static void MX_TIM6_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; htim6.Instance = TIM6; htim6.Init.Prescaler = HAL_RCC_GetHCLKFreq() / (SAMPLE_NUM * SAMPLE_RATE) - 1; // 定时器时钟频率 = 系统时钟 / PSC htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = SAMPLE_NUM - 1; // 计数器从0到99,共100次 if (HAL_TIM_Base_Init(&htim6) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK) { Error_Handler(); } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM6) { static uint8_t index = 0; // 当前采样点索引 uint16_t value = sinewave[index]; HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, value); // 写入DAC数据寄存器 index = (index + 1) % SAMPLE_NUM; } } static void MX_GPIO_Init(void) { // DAC输出GPIO初始化 GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void Error_Handler(void) { // 程序发生错误时停机 while (1) { } } ``` 需要注意的是,当DAC模块输出到外部电路时,需要使用一定的滤波电路来去除采样过程中可能产生的高频噪声。另外,如果要实现多声道输出,可以使用不同的DAC通道,或者使用DMA功能直接传输多通道数据。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_LiuChunJiang刘春江

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值