赞
踩
1)实验平台:正点原子APM32E103最小系统板
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban
本章介绍使用APM32E103的DAC输出指定的电压值。通过本章的学习。读者将学习到DAC的使用。
本章分为如下几个小节:
37.1 硬件设计
37.2 程序设计
37.3 下载验证
37.1 硬件设计
37.1.1 例程功能
typedef enum { DAC_TRIGGER_NONE = 0x00000000, /* 禁用DAC通道触发 */ DAC_TRIGGER_TMR6_TRGO = 0x00000004, /* 定时器6的TRGO事件 */ DAC_TRIGGER_TMR8_TRGO = 0x0000000C, /* 定时器8的TRGO事件 */ DAC_TRIGGER_TMR7_TRGO = 0x00000014, /* 定时器7的TRGO事件 */ DAC_TRIGGER_TMR5_TRGO = 0x0000001C, /* 定时器5的TRGO事件 */ DAC_TRIGGER_TMR2_TRGO = 0x00000024, /* 定时器2的TRGO事件 */ DAC_TRIGGER_TMR4_TRGO = 0x0000002C, /* 定时器4的TRGO事件 */ DAC_TRIGGER_EINT9 = 0x00000034, /* 外部中断线9 */ DAC_TRIGGER_SOFT = 0x0000003C /* 软件触发 */ } DAC_TRIGGER_T; typedef enum { DAC_WAVE_GENERATION_NONE = 0x00000000, /* 不产生波形 */ DAC_WAVE_GENERATION_NOISE = 0x00000040, /* 产生噪声波形 */ DAC_WAVE_GENERATION_TRIANGLE = 0x00000080 /* 产生三角波波形 */ } DAC_WAVE_GENERATION_T; typedef enum { DAC_LFSR_MASK_BIT11_1 = 0x00000000, /* 屏蔽LFSP[11:1] */ DAC_LFSR_MASK_BIT11_2 = 0x00000100, /* 屏蔽LFSP[11:2] */ DAC_LFSR_MASK_BIT11_3 = 0x00000200, /* 屏蔽LFSP[11:3] */ DAC_LFSR_MASK_BIT11_4 = 0x00000300, /* 屏蔽LFSP[11:4] */ DAC_LFSR_MASK_BIT11_5 = 0x00000400, /* 屏蔽LFSP[11:5] */ DAC_LFSR_MASK_BIT11_6 = 0x00000500, /* 屏蔽LFSP[11:6] */ DAC_LFSR_MASK_BIT11_7 = 0x00000600, /* 屏蔽LFSP[11:7] */ DAC_LFSR_MASK_BIT11_8 = 0x00000700, /* 屏蔽LFSP[11:8] */ DAC_LFSR_MASK_BIT11_9 = 0x00000800, /* 屏蔽LFSP[11:9] */ DAC_LFSR_MASK_BIT11_10 = 0x00000900, /* 屏蔽LFSP[11:10] */ DAC_LFSR_MASK_BIT11 = 0x00000A00, /* 屏蔽LFSP[11] */ DAC_LFSR_MASK_NONE = 0x00000B00, /* 不屏蔽LFSP */ DAC_TRIANGLE_AMPLITUDE_1 = 0x00000000, /* 三角波幅值等于1 */ DAC_TRIANGLE_AMPLITUDE_3 = 0x00000100, /* 三角波幅值等于3 */ DAC_TRIANGLE_AMPLITUDE_7 = 0x00000200, /* 三角波幅值等于7 */ DAC_TRIANGLE_AMPLITUDE_15 = 0x00000300, /* 三角波幅值等于15 */ DAC_TRIANGLE_AMPLITUDE_31 = 0x00000400, /* 三角波幅值等于31 */ DAC_TRIANGLE_AMPLITUDE_63 = 0x00000500, /* 三角波幅值等于63 */ DAC_TRIANGLE_AMPLITUDE_127 = 0x00000600, /* 三角波幅值等于127 */ DAC_TRIANGLE_AMPLITUDE_255 = 0x00000700, /* 三角波幅值等于255 */ DAC_TRIANGLE_AMPLITUDE_511 = 0x00000800, /* 三角波幅值等于511 */ DAC_TRIANGLE_AMPLITUDE_1023 = 0x00000900, /* 三角波幅值等于1023 */ DAC_TRIANGLE_AMPLITUDE_2047 = 0x00000A00, /* 三角波幅值等于2047 */ DAC_TRIANGLE_AMPLITUDE_4095 = 0x00000B00 /* 三角波幅值等于4095 */ } DAC_MASK_AMPLITUDE_SEL_T; typedef enum { DAC_OUTPUT_BUFFER_ENBALE = 0x00000000, /* 禁用输出缓存 */ DAC_OUTPUT_BUFFER_DISABLE = 0x00000002 /* 使能输出缓存 */ } DAC_OUTPUT_BUFFER_T; typedef struct { DAC_TRIGGER_T trigger; /* 触发 */ DAC_OUTPUT_BUFFER_T outputBuffer; /* 输出缓存 */ DAC_WAVE_GENERATION_T waveGeneration; /* 产生波形 */ DAC_MASK_AMPLITUDE_SEL_T maskAmplitudeSelect;/* 屏蔽LFSR位/三角波幅 */ } DAC_Config_T; 该函数的使用示例,如下所示: #include "apm32e10x.h" #include "apm32e10x_dac.h" void example_fun(void) { DAC_Config_T dac_init_struct; /* 配置DAC通道1 */ dac_init_struct.trigger = DAC_TRIGGER_NONE; dac_init_struct.outputBuffer = DAC_OUTPUT_BUFFER_DISABLE; dac_init_struct.waveGeneration = DAC_WAVE_GENERATION_NONE; dac_init_struct.maskAmplitudeSelect = DAC_LFSR_MASK_BIT11_1; DAC_Config(DAC_CHANNEL_1, &dac_init_struct); }
②:使能DAC通道
该函数用于使能DAC通道,其函数原型如下所示:
void DAC_Enable(DAC_CHANNEL_T channel);
该函数的形参描述,如下表所示:
形参 描述
channel 指定DAC的通道
例如:DAC_CHANNEL_1、DAC_CHANNEL_2(在apm32e10x_dac.h文件中有定义)
表37.2.1.3 函数DAC_Enable()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表37.2.1.4 函数DAC_Enable()返回值描述
该函数的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_dac.h"
void example_fun(void)
{
/* 使能DAC通道1 */
DAC_Enable(DAC_CHANNEL_1);
}
③:配置DAC通道数据保持寄存器
该函数用于配置DAC通道的数据保持寄存器,其函数原型如下所示:
void DAC_ConfigChannel1Data(DAC_ALIGN_T align, uint16_t data);
void DAC_ConfigChannel2Data(DAC_ALIGN_T align, uint16_t data);
该函数的形参描述,如下表所示:
形参 描述
align 数据对齐方式
例如:DAC_ALIGN_12BIT_L、DAC_ALIGN_8BIT_R等(在apm32e10x_dac.h文件中有定义)
data 写入数据保持寄存器的数据
表37.2.1.5 函数DAC_ConfigChannelnData()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表37.2.1.6 函数DAC_ConfigChannelnData()返回值描述
该函数的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_dac.h"
void example_fun(void)
{
/* 配置DAC通道1的保持寄存器 */
DAC_ConfigChannel1Data(DAC_ALIGN_12BIT_R, 1024);
}
37.2.2 DAC驱动
本章实验的DAC驱动主要负责向应用层提供DAC的初始化和配置其输出指定电压的函数。本章实验中,DAC的驱动代码包括dac.c和dac.h两个文件。
DAC驱动中,DAC的初始化函数,如下所示:
/** * @brief 初始化DAC * @note DAC使用VREF作为参考电压,将VSSA接地,可得到DAC的输出电压范围为:0-VREF。 * DAC输出计算公式为:DAC输出=VREF * (DATAOCHx/4095) * * @param outx: 要初始化的通道. 1,通道1; 2,通道2 * @retval 无 */ void dac_init(uint8_t outx) { DAC_Config_T dac_init_struct; GPIO_Config_T gpio_init_struct; /* 使能时钟 */ RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_DAC); /* 使能DAC时钟 */ /* 使能DAC OUT1/2的IO口时钟(都在PA口,PA4/PA5) */ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); /* APM32单片机, 总是PA4=DAC1_OUT1, PA5=DAC1_OUT2 */ gpio_init_struct.pin = (outx == 1)? GPIO_PIN_4 : GPIO_PIN_5; gpio_init_struct.speed = GPIO_SPEED_50MHz; /* 高速 */ gpio_init_struct.mode = GPIO_MODE_ANALOG; /* 模拟输入 */ GPIO_Config(GPIOA, &gpio_init_struct); /* 初始化DAC引脚 */ /* 配置DAC */ dac_init_struct.trigger = DAC_TRIGGER_NONE; /* 不使用触发功能 */ /* DAC1输出缓冲关闭 */ dac_init_struct.outputBuffer = DAC_OUTPUT_BUFFER_DISABLE; dac_init_struct.waveGeneration = DAC_WAVE_GENERATION_NONE;/* 不使用波形发生 */ /* 屏蔽、幅值设置 */ dac_init_struct.maskAmplitudeSelect = DAC_LFSR_MASK_BIT11_1; /* 初始化DAC通道1 */ DAC_Config(DAC_CHANNEL_1, &dac_init_struct); switch(outx) { case DAC_CHANNEL1: { DAC_ConfigChannel1Data(DAC_ALIGN_12BIT_R, 0); /* 配置DAC通道1 */ DAC_Enable(DAC_CHANNEL_1); /* 使能指定的ADC1 */ break; } case DAC_CHANNEL2: { DAC_ConfigChannel2Data(DAC_ALIGN_12BIT_R, 0); /* 配置DAC通道2 */ DAC_Enable(DAC_CHANNEL_2); /* 使能指定的ADC2 */ break; } default: { break; } } }
从上面的代码中可以看出,DAC的初始化函数会根据传入的参数outx自动配置并使能DAC的通道1或通道2,同时将DAC通道对应的输出引脚配置为模拟模式。
DAC驱动中,配置DAC通道输出指定电压的函数,如下所示:
/** * @brief 设置通道1/2输出电压 * @param outx: 1,通道1; 2,通道2 * @param vol : 0~3300,代表0~3.3V * @retval 无 */ void dac_set_voltage(uint8_t outx, uint16_t vol) { uint32_t dacdata; dacdata = vol * 4095 / 3300; /* 将电压值转换为数字量 */ if (dacdata > 4095) /* 限制最大值 */ { dacdata = 4095; } if (outx == 1) { /* DAC通道1输出的电压 */ DAC_ConfigChannel1Data(DAC_ALIGN_12BIT_R, dacdata); } else { /* DAC通道2输出的电压 */ DAC_ConfigChannel2Data(DAC_ALIGN_12BIT_R, dacdata); } }
该函数将输入的电压模拟量转换为DAC输出的数字量后,将该值写入指定DAC通道的数据保持寄存器。
37.2.3 实验应用代码
本章实验的应用代码,如下所示:
int main(void) { uint8_t key; uint16_t dacdata = 0; uint8_t t = 0; uint16_t dacoutdata; uint16_t dac_voltage; uint16_t adcdata; uint16_t adc_voltage; NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4); /* 设置中断优先级分组为组4 */ sys_apm32_clock_init(15); /* 配置系统时钟 */ delay_init(120); /* 初始化延时功能 */ usart_init(115200); /* 初始化串口 */ usmart_dev.init(120); /* 初始化USMART */ led_init(); /* 初始化LED */ lcd_init(); /* 初始化LCD */ key_init(); /* 初始化按键 */ adc_init(); /* 初始化ADC */ dac_init(1); /* 初始化DAC1_OUT1通道 */ lcd_show_string(30, 50, 200, 16, 16, "APM32", 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, "KEY_UP:+ KEY0:-", RED); lcd_show_string(30, 150, 200, 16, 16, "DAC VAL:", BLUE); lcd_show_string(30, 170, 200, 16, 16, "DAC VOL:0.000V", BLUE); lcd_show_string(30, 190, 200, 16, 16, "ADC VOL:0.000V", BLUE); while (1) { t++; key = key_scan(0); /* 扫描按键 */ /* KEY_UP按键按下,DAC输出增加200 */ if (key == WKUP_PRES) { if (dacdata < 4000) { dacdata += 200; } DAC_ConfigChannel1Data(DAC_ALIGN_12BIT_R, dacdata); } /* KEY0按键按下,DAC输出减少200 */ else if (key == KEY0_PRES) { if (dacdata > 200) { dacdata -= 200; } else { dacdata = 0; } DAC_ConfigChannel1Data(DAC_ALIGN_12BIT_R, dacdata); } if ((t == 10) || (key == WKUP_PRES) || (key == KEY0_PRES)) { /* 获取DAC输出电压的数字量 */ dacoutdata = DAC_ReadDataOutputValue(DAC_CHANNEL_1); /* 显示DAC输出电压的数字量 */ lcd_show_xnum(94, 150, dacoutdata, 5, 16, 0, BLUE); /* 计算实际输出的电压值(扩大1000倍) */ dac_voltage = (dacoutdata * 3300) / 4095; /* 显示DAC输出电压值的整数部分 */ lcd_show_xnum(94, 170, dac_voltage / 1000, 1, 16, 0, BLUE); /* 显示DAC输出电压值的小数部分(保留三位小数) */ lcd_show_xnum(110, 170, dac_voltage % 1000, 3, 16, 0x80, BLUE); /* 获取ADC采集到电压的数字量 */ adcdata = adc_get_result_average(ADC_ADCX_CHY, 10); /* 计算实际电压值(扩大1000倍) */ adc_voltage = (adcdata * 3300) / 4095; /* 显示ADC采集电压值的整数部分 */ lcd_show_xnum(94, 190, adc_voltage / 1000, 1, 16, 0, BLUE); /* 显示ADC采集电压值的小数部分(保留三位小数) */ lcd_show_xnum(110, 190, adc_voltage % 1000, 3, 16, 0x80, BLUE); LED0_TOGGLE(); t = 0; } delay_ms(10); } }
可以看到,应用代码中不仅初始化了DAC的通道1(PA4引脚)同时还使能了ADC的通道1(PA1引脚)用于采集DAC通道1的输出电压。在完成初始化后,便不断地扫描按键并将DAC输出电压的模拟量和数字量以及ADC采集到电压的模拟量在LCD上进行显示,此时若扫描到KEY0按键,则减少DAC输出电压的数字量,若扫描到KEY_UP按键,则增加DAC输出电压的数字量。
37.3 下载验证
在完成编译和烧录操作后,可以看到LCD上实时刷新显示着DAC输出电压的模拟量和数字量以及ADC采集到电压的模拟量,此时可以将PA4引脚(DAC通道1输出引脚)和PA4引脚(ADC通道1采集引脚)通过杜邦线相连,在按下KEY0或KEY_UP按键来调整DAC通道1的输出电压,可以看到LCD上显示的DAC输出电压的模拟量和数字量以及ADC采集到电压的模拟量也随之变化,并且ADC采集到电压的模拟量也十分接近DAC输出电压的模拟量。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。