首先我们知道正弦波的解析式为y=Asin(omiga*x+fei)+b,拓展到STM32中则会得到如下的式子:
y=2048*sin((2*pi/samples)*x)+2048.
其中形参的取值范围是(samples/2) 接下来编写我们的函数代码dac_sin.c: 接下来编写函数头文件dac_sin.h: 最后编写主函数main.c: 到这里我们的实验代码就写完了。#include "./BSP/DAC/dac_sin.h"
#include "math.c"
DAC_HandleTypeDef g_dac_handle;
DMA_HandleTypeDef g_dma_handle;
uint16_t g_dac_sin_buf[4096];
void dac_dma_init(void){
g_dma_handle.Instance = DMA2_Channel3;
g_dma_handle.Init.Direction = DMA_MEMORY_TO_PERIPH; //外设到内存
g_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE; //因为选取的是DMA2的数据寄存器,选择不增量
g_dma_handle.Init.MemInc = DMA_MINC_ENABLE; //对于存储器需要存储多个数据,所以选择增量模式
g_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //外设数据位宽,我们选择16位半字(全字可以理解为全角中文字符)
g_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //存储器数据位宽,我们也选择16位半字
g_dma_handle.Init.Mode = DMA_CIRCULAR; //选择循环模式
g_dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM; //只有1个DMA随便选
HAL_DMA_Init(&g_dma_handle);
DAC_ChannelConfTypeDef dac_ch_conf;
g_dac_handle.Instance = DAC1; //寄存器基地址
HAL_DAC_Init(&g_dac_handle);
_HAL_LINKDMA(&g_dac_handle, DMA_Handle1, &g_dma_handle); //DMA_Handle1是因为选用的是DAC通道1
dac_ch_conf.Trigger = DAC_TRIGGER_T7_TRGO; //触发源选择,选择外部定时器7
dac_ch_conf.OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_1);
HAL_DAC_Start(&g_dac_handle, (uint32_t*)g_dac_sin_buf, (uint32_t)&DAC->DHR12R1, 0); //第三个参数,12位右对齐
}
void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac){
if(hdac->Instance == DAC1){
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_DAC_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_4;
gpio_init_strcut.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
}
}
void dac_dma_wave_enable(uint16_t cndtr, uint16_t arr, uint16_t psc){
TIM_HandleTypeDef g_tim7_handle = {0};
TIM_MasterConfigTypeDef tim_master_config = {0};
__HAL_RCC_TIM7_CLK_ENABLE();
g_tim7_handle.Instance = TIM7;
g_tim7_Handle.Init.Prescalar = psc;
g_tim7_handle.init.Period = arr;
HAL_TIM_Base_Init(&g_tim7_handle);
tim_master_config.MasterOutputTrigger = TIM_TRGO_UPDATE; //选择更新,更新事件作为触发源
tim_master_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; //可选同步或无,我们选择无
HAL_TIMEx_MasterConifgSynchronization(&g_tim7_handle, &);
//配置定时器触发DAC变换
HAL_TIM_Base_Start(&g_tim7_handle);
HAL_DAC_Stop_DMA(&g_dac_handle, &DAC_CHANNEL_1);
HAL_DAC_Start_DMA(&g_dac_handle, &DAC_CHANNEL_1, (uint32_t*)g_dac_sin_buf, cndtr); //第三个参数为数据来源,第四个参数为数据长度
}
void dac_creat_sin_buf(uint16_t maxval, uint_16 samples){
uint8_t i;
float outdata = 0;
float inc = (2 * 3.1415926) / samples;
if(maxval <= (samples / 2))return;
for(i=0; i
#ifndef __DAC_SIN_H
#define __DAC_SIN_H
extern g_dac_sin_buf[4096];
void dac_dma_init(void);
void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac);
void dac_creat_sin_buf(uint16_t vol);
#endif
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/DAC/dac_sin.h"
#include "./BSP/ADC/adc.h"
int main(void)
{
uint16_t adcx;
float temp;
uint8_t t = 0;
uint16_t dacval = 0;
uint8_t key;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
usmart_dev.init(72); /* 初始化USMART */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
adc3_init(); /* 初始化ADC3 */
dac_dma_init(1); /* 初始化DAC1_OUT1通道 */
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);
dac_creat_sin_buf(2048, 100);
dac_dma_wave_enable(100, 10 - 1, 72 - 1); //100kHz, 100个点,得到1kHz的正弦波
while (1)
{
t++;
key = key_scan(0); /* 按键扫描 */
if (key == WKUP_PRES)
{
dac_creat_sin_buf(2048, 100);
dac_dma_wave_enable(100, 10 - 1, 24 - 1); //300kHz, 100个点,得到3kHz的正弦波
}
else if (key == KEY1_PRES)
{
dac_creat_sin_buf(2048, 100);
dac_dma_wave_enable(10, 10 - 1, 24 - 1); //300kHz, 10个点,得到30kHz的正弦波
}
if(t == 40){
LED0_TOGGLE();
t = 0;
}
delay_ms(10);
}
}