单片机DAC实验
·
单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
一、DAC输出实验
主函数
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(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
adc_init(); /* 初始化ADC */
dac_init(1); /* 初始化DAC1_OUT1通道 */
lcd_show_string(30, 50, 200, 16, 16, "STM32", 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, "KEY1:+ KEY0:-", RED);
lcd_show_string(30, 130, 200, 16, 16, "DAC VAL:", BLUE);
lcd_show_string(30, 150, 200, 16, 16, "DAC VOL:0.000V", BLUE);
lcd_show_string(30, 170, 200, 16, 16, "ADC VOL:0.000V", BLUE);
while (1)
{
t++;
key = key_scan(0); /* 按键扫描 */
if (key == KEY1_PRES)
{
if (dacval < 4000)
{
dacval += 200;
}
HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacval); /* 输出增大200 */
}
else if (key == KEY0_PRES)
{
if (dacval > 200)
{
dacval -= 200;
}
else
{
dacval = 0;
}
HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacval); /* 输出减少200 */
}
if (t == 10 || key == KEY0_PRES || key == KEY1_PRES) /* KEY0/KEY1按下了,或者定时时间到了 */
{
adcx = HAL_DAC_GetValue(&g_dac_handle, DAC_CHANNEL_1); /* 读取前面设置DAC1_OUT1的值 */
lcd_show_xnum(94, 130, adcx, 4, 16, 0, BLUE); /* 显示DAC寄存器值 */
temp = (float)adcx * (3.3 / 4096); /* 得到DAC电压值 */
adcx = temp;
lcd_show_xnum(94, 150, temp, 1, 16, 0, BLUE); /* 显示电压值整数部分 */
temp -= adcx;
temp *= 1000;
lcd_show_xnum(110, 150, temp, 3, 16, 0X80, BLUE); /* 显示电压值的小数部分 */
adcx = adc_get_result_average(ADC_ADCX_CHY, 20); /* 得到ADC1通道3的转换结果 */
temp = (float)adcx * (3.3 / 4096); /* 得到ADC电压值 */
adcx = temp;
lcd_show_xnum(94, 170, temp, 1, 16, 0, BLUE); /* 显示电压值整数部分 */
temp -= adcx;
temp *= 1000;
lcd_show_xnum(110, 170, temp, 3, 16, 0X80, BLUE); /* 显示电压值的小数部分 */
LED0_TOGGLE(); /* LED0闪烁 */
t = 0;
}
delay_ms(10);
}
}
配置
void dac_init(uint8_t outx)
{
GPIO_InitTypeDef gpio_init_struct;
DAC_ChannelConfTypeDef dac_ch_conf;
__HAL_RCC_DAC_CLK_ENABLE(); /* 使能DAC1的时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能DAC OUT1/2的IO口时钟(都在PA口,PA4/PA5) */
gpio_init_struct.Pin = (outx==1)? GPIO_PIN_4 : GPIO_PIN_5; /* STM32单片机, 总是PA4=DAC1_OUT1, PA5=DAC1_OUT2 */
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
g_dac_handle.Instance = DAC;
HAL_DAC_Init(&g_dac_handle); /* 初始化DAC */
dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE; /* 不使用触发功能 */
dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; /* DAC1输出缓冲关闭 */
switch(outx)
{
case 1:
HAL_DAC_ConfigChannel(&g_dac_handle,&dac_ch_conf,DAC_CHANNEL_1); /* DAC通道1配置 */
HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_1); /* 开启DAC通道1 */
break;
case 2:
HAL_DAC_ConfigChannel(&g_dac_handle,&dac_ch_conf,DAC_CHANNEL_2); /* DAC通道2配置 */
HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_2); /* 开启DAC通道2 */
break;
default:break;
}
}
void dac_set_voltage(uint8_t outx, uint16_t vol)
{
double temp = vol;
temp /= 1000;
temp = temp * 4096 / 3.3;
if (temp >= 4096)temp = 4095; /* 如果值大于等于4096, 则取4095 */
if (outx == 1) /* 通道1 */
{
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,temp); /* 12位右对齐数据格式设置DAC值 */
}
else /* 通道2 */
{
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_2,DAC_ALIGN_12B_R,temp); /* 12位右对齐数据格式设置DAC值 */
}
}
测试结果:

二、DAC输出三角波实验
主函数
int main(void)
{
uint8_t t = 0;
uint8_t key;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
dac_init(1); /* 初始化DAC1_OUT1通道 */
lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "DAC Triangular WAVE TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 110, 200, 16, 16, "KEY0:Wave1 KEY1:Wave2", RED);
lcd_show_string(30, 130, 200, 16, 16, "DAC None", BLUE); /* 默认提示无输出 */
while (1)
{
t++;
key = key_scan(0); /* 按键扫描 */
if (key == KEY0_PRES) /* 高采样率 , 约88.5Hz波形 */
{
lcd_show_string(30, 130, 200, 16, 16, "DAC Wave1 ", BLUE);
dac_triangular_wave(4095, 5, 2000, 100); /* 幅值4095, 采样点间隔5us, 2000个采样点, 100个波形 */
lcd_show_string(30, 130, 200, 16, 16, "DAC None ", BLUE);
}
else if (key == KEY1_PRES) /* 低采样率 , 约100Hz波形 */
{
lcd_show_string(30, 130, 200, 16, 16, "DAC Wave2 ", BLUE);
dac_triangular_wave(4095, 500, 20, 100); /* 幅值4095, 采样点间隔500us, 20个采样点, 100个波形 */
lcd_show_string(30, 130, 200, 16, 16, "DAC None ", BLUE);
}
if (t == 10) /* 定时时间到了 */
{
LED0_TOGGLE(); /* LED0闪烁 */
t = 0;
}
delay_ms(10);
}
}
void dac_init(uint8_t outx)
{
GPIO_InitTypeDef gpio_init_struct;
DAC_ChannelConfTypeDef dac_ch_conf;
__HAL_RCC_DAC_CLK_ENABLE(); /* 使能DAC的时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能DAC OUT1/2的IO口时钟(都在PA口,PA4/PA5) */
gpio_init_struct.Pin = (outx==1)? GPIO_PIN_4 : GPIO_PIN_5; /* STM32单片机, 总是PA4=DAC1_OUT1, PA5=DAC1_OUT2 */
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
g_dac_handle.Instance = DAC;
HAL_DAC_Init(&g_dac_handle); /* 初始化DAC */
dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE; /* 不使用触发功能 */
dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; /* DAC1输出缓冲关闭 */
switch(outx)
{
case 1:
HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_1); /* DAC通道1配置 */
HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_1); /* 开启DAC通道1 */
break;
case 2:
HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_2); /* DAC通道2配置 */
HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_2); /* 开启DAC通道2 */
break;
default:break;
}
}
void dac_triangular_wave(uint16_t maxval, uint16_t dt, uint16_t samples, uint16_t n)
{
uint16_t i, j;
float incval; /* 递增量 */
float Curval; /* 当前值 */
if(samples > ((maxval + 1) * 2))return ; /* 数据不合法 */
incval = (maxval + 1) / (samples / 2); /* 计算递增量 */
for(j = 0; j < n; j++)
{
Curval = 0;
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,Curval); /* 先输出0 */
for(i = 0; i < (samples / 2); i++) /* 输出上升沿 */
{
Curval += incval; /* 新的输出值 */
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,Curval);
delay_us(dt);
}
for(i = 0; i < (samples / 2); i++) /* 输出下降沿 */
{
Curval -= incval; /* 新的输出值 */
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,Curval);
delay_us(dt);
}
}
}
实验结果:
用示波器观察PA4波形。
三、DAC输出正弦波
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
gtim_timx_int_init(10-1,84-1); /* 初始化定时器,定时触发DAC */
dac_init(1,100); /* 初始化DAC1_OUT1通道,100个点,正弦波频率1k Hz */
lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "DAC DMA Sine WAVE TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
while (1)
{
LED0_TOGGLE(); /* LED0翻转 */
delay_ms(1000);
}
}
配置
void dac_init(uint8_t outx,uint16_t cndtr)
{
GPIO_InitTypeDef gpio_init_struct;
DAC_ChannelConfTypeDef DACCH1_Config;
__HAL_RCC_DAC_CLK_ENABLE(); /* 使能DAC的时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能DAC OUT1/2的IO口时钟(都在PA口,PA4/PA5) */
__HAL_RCC_DMA1_CLK_ENABLE();
gpio_init_struct.Pin = (outx==1)? GPIO_PIN_4 : GPIO_PIN_5; /* STM32单片机, 总是PA4=DAC1_OUT1, PA5=DAC1_OUT2 */
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
g_dma_dac_handle.Instance = DMA1_Stream5; /* DMA1数据流5 */
g_dma_dac_handle.Init.Channel = DMA_CHANNEL_7; /* 通道7 */
g_dma_dac_handle.Init.Direction = DMA_MEMORY_TO_PERIPH; /* 从存储器到外设模式 */
g_dma_dac_handle.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设非增量模式 */
g_dma_dac_handle.Init.MemInc = DMA_MINC_ENABLE; /* 存储器增量模式 */
g_dma_dac_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* 外设数据长度:16位 */
g_dma_dac_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; /* 存储器数据长度:16位 */
g_dma_dac_handle.Init.Mode = DMA_CIRCULAR; /* 循环模式 */
g_dma_dac_handle.Init.Priority = DMA_PRIORITY_LOW; /* 中等优先级 */
g_dma_dac_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; /* 不开启FIFO */
HAL_DMA_Init(&g_dma_dac_handle); /* 初始化DMA */
__HAL_LINKDMA(&g_dac_dma_handle,DMA_Handle1,g_dma_dac_handle); /* 把DAC和DMA关联 */
g_dac_dma_handle.Instance = DAC;
HAL_DAC_Init(&g_dac_dma_handle); /* 初始化DAC */
DACCH1_Config.DAC_Trigger = DAC_TRIGGER_T2_TRGO; /* 使用定时器2的TRGO事件触发DAC转换 */
DACCH1_Config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; /* DAC1输出缓冲关闭 */
dac_creat_sin_buf(2048,cndtr); /* 产生正弦波序列,即画点 */
switch(outx)
{
case 1:
HAL_DAC_ConfigChannel(&g_dac_dma_handle,&DACCH1_Config,DAC_CHANNEL_1); /* DAC通道1配置 */
HAL_DAC_Start_DMA(&g_dac_dma_handle,DAC_CHANNEL_1,(uint32_t *)g_dac_sin_buf,cndtr,DAC_ALIGN_12B_R); /* 开启DAC通道1 */
break;
case 2:
HAL_DAC_ConfigChannel(&g_dac_dma_handle,&DACCH1_Config,DAC_CHANNEL_2); /* DAC通道2配置 */
HAL_DAC_Start_DMA(&g_dac_dma_handle,DAC_CHANNEL_2,(uint32_t *)g_dac_sin_buf,cndtr,DAC_ALIGN_12B_R); /* 开启DAC通道2 */
break;
default:break;
}
}
void dac_creat_sin_buf(uint16_t maxval, uint16_t samples)
{
uint8_t i;
float outdata = 0;
if(maxval <= (samples / 2))return ; /* 数据不合法 */
/*
* 正弦波最小正周期为2π,约等于2 * 3.1415926
* 曲线上相邻的两个点在x轴上的间隔 = 2 * 3.1415926 / 采样点数量
*/
float inc = (2 * 3.1415926) / samples; /* 计算相邻两个点的x轴间隔 */
for (i = 0; i < samples; i++) /* 连续打samples个点 */
{
/*
* 正弦波函数解析式:y = Asin(wx + φ)+ b
* 计算每个点的y值,将峰值放大maxval倍,并将曲线向上偏移maxval到正数区域
* 注意:DAC无法输出负电压,所以需要将曲线向上偏移一个峰值的量,让整个曲线都落在正数区域
*/
outdata = maxval * sin(inc * i) + maxval;
if (outdata > 4095)
{
outdata = 4095; /* 上限限定 */
}
g_dac_sin_buf[i] = outdata;
}
}
#define GTIM_TIMX_INT TIM2
#define GTIM_TIMX_INT_IRQn TIM2_IRQn
#define GTIM_TIMX_INT_IRQHandler TIM2_IRQHandler
#define GTIM_TIMX_INT_CLK_ENABLE() do{ __HAL_RCC_TIM2_CLK_ENABLE(); }while(0) /* TIM2 时钟使能 */
void gtim_timx_int_init(uint16_t arr, uint16_t psc)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
GTIM_TIMX_INT_CLK_ENABLE(); /* 使能TIMx时钟 */
g_timx_handle.Instance = GTIM_TIMX_INT; /* 通用定时器x */
g_timx_handle.Init.Prescaler = psc; /* 预分频系数 */
g_timx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */
g_timx_handle.Init.Period = arr; /* 自动装载值 */
HAL_TIM_Base_Init(&g_timx_handle);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; /* 定时器更新事件用于触发 */
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&g_timx_handle, &sMasterConfig);
HAL_TIM_Base_Start(&g_timx_handle); /* 使能定时器x */
}
测试结果:
示波器观察PA4波形。
更多推荐

所有评论(0)