cortex_m3_stm32嵌入式学习笔记(十八):DAC实验(数模转换)

STM32 的 DAC 模块(数字/模拟转换模块)是 12 位数字输入,电压输出型的 DAC。 DAC可以配置为 8 位或 12 位模式,也可以与 DMA 控制器配合使用。 DAC 工作在 12 位模式时,数据可以设置成左对齐或右对齐。
DAC 模块有 2 个输出通道,每个通道都有单独的转换器。在双 DAC 模式下, 2 个通道可以独立地进行转换,也可以同时进行转换并同步地更新 2 个通道的输出。

本节实验,我们将利用按键(或 USMART) 控制 STM32 内部 DAC1来输出电压,通过
ADC1的通道1 采集 DAC的输出电压,在 LCD 模块上面显示 ADC 获取到的电压值以及 DAC 的设定输出电压值等信息。

STM32 的 DAC 模块主要特点有:

① 2 个 DAC 转换器:每个转换器对应 1 个输出通道

② 8 位或者 12 位单调输出

③ 12 位模式下数据左对齐或者右对齐

④ 同步更新功能

⑤ 噪声波形生成

⑥ 三角波形生成

⑦ 双 DAC 通道同时或者分别转换

⑧ 每个通道都有 DMA 功能

当 DAC 的参考电压为 Vref+的时候(对 STM32F103RC 来说就是 3.3V), DAC 的输出电压是线性的从 0~Vref+, 12 位模式下 DAC 输出电压与 Vref+以及 DORx 的计算公式如下:

DACx 输出电压=Vref*( DORx/4095)

我的ADC和DAC的理解是:

ADC可以采集电压把电压转换为数字,DAC可以把数字转换为电压的形式并输出

配置步骤:

1)开启
PA 口时钟,设置
PA4 为模拟输入。

STM32F103RCT6 的 DAC 通道 1 在 PA4 上,所以,我们先要使能 PORTA 的时钟,然后设置
PA4 为模拟输入。 DAC 本身是输出,但是为什么端口要设置为模拟输入模式呢?因为一但使能 DACx 通道之后,相应的 GPIO 引脚( PA4 或者 PA5)会自动与 DAC 的模拟输出相连,设置为输入,是为了避免额外的干扰。

2)使能
DAC1 时钟。

3) 初始化
DAC,设置
DAC 的工作模式。

4) 使能
DAC 转换通道

5) 设置
DAC 的输出值。

dac.c

#include "dac.h"
void Dac1_Init(void)
{
	GPIO_InitTypeDef GPIO_ist;
	DAC_InitTypeDef DAC_ist;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );//使能 PA 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能 DAC 时钟
	GPIO_ist.GPIO_Pin=GPIO_Pin_4;
	GPIO_ist.GPIO_Mode=GPIO_Mode_AIN;//模拟输入
	GPIO_ist.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_ist);
	GPIO_SetBits(GPIOA,GPIO_Pin_4);//PA.4 输出高

	DAC_ist.DAC_Trigger=DAC_Trigger_None; //不使用触发功能
	DAC_ist.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
	DAC_ist.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;
	DAC_ist.DAC_OutputBuffer=DAC_OutputBuffer_Disable ;//关DAC1输出缓存
	DAC_Init(DAC_Channel_1,&DAC_ist);  //初始化 DAC 通道 1

	DAC_Cmd(DAC_Channel_1,ENABLE);//使能 DAC1
	DAC_SetChannel1Data(DAC_Align_12b_R,0);//12位右对齐,设置DAC初始值
}

//设置通道 1 输出电压
//vol:0~3300,代表 0~3.3V
void Dac1_Set_Vol(u16 vol)
{
	float temp=vol;
	temp/=1000;
	temp=temp*4096/3.3;
	DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐设置DAC值
}
u16 Dac1_Get_Vol(void)
{
	return DAC_GetDataOutputValue(DAC_Channel_1);
}

dac.h

#ifndef _DAC_H
#define _DAC_H
#include "sys.h"
void Dac1_Init(void);
u16 Dac1_Get_Vol(void);
void Dac1_Set_Vol(u16 vol);
#endif

主函数。。通过按键来调节DAC输出电压的强度,WKUP增强,KEY0减弱(也可以通过USMART组件设置)

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "dac.h"
#include "key.h"
void init()
{
	delay_init();	    	 //延时函数初始化
	uart_init(9600);	 	//串口初始化为9600
	LED_Init();		  		//初始化与LED连接的硬件接口
 	LCD_Init();
	KEY_Init();
	Adc_Init();
	Dac1_Init();

	POINT_COLOR=RED;//设置字体为红色
	LCD_ShowString(60,40,200,24,24,"DAC Test ^-^");
	LCD_ShowString(60,70,200,16,16,"Bigggg difficulty");
	LCD_ShowString(60,90,200,16,16,"2015/1/25");
	LCD_ShowString(60,110,200,16,16,"By--Mr yh");
	LCD_ShowString(60,130,200,16,16,"WK_UP:+ KEY0:-");
	//显示提示信息
	POINT_COLOR=BLUE;//设置字体为蓝色
	LCD_ShowString(60,150,200,16,16,"DAC VAL:");
	LCD_ShowString(60,170,200,16,16,"DAC VOL:0.000V");
	LCD_ShowString(60,190,200,16,16,"ADC VOL:0.000V");
	Dac1_Set_Vol(330);
}
int main(void)
{

	u16  adcnum=0;
	u16 dacnum=0;
	float tem;
	u8 key,t=0;
	init();
	while(1)
	{
		t++;
		key=KEY_Scan(0);
		if(key==WK_UP_PRES)
		{
			if(dacnum<4000)dacnum+=200;
			DAC_SetChannel1Data(DAC_Align_12b_R,dacnum);
		}
		else if(key==KEY0_PRES)
		{
			if(dacnum>200)dacnum-=200;
			else dacnum=0;
			DAC_SetChannel1Data(DAC_Align_12b_R,dacnum);
		}

		if(t==10||key==WK_UP_PRES||key==KEY0_PRES)
		{
			adcnum=Dac1_Get_Vol();dacnum=adcnum;
			LCD_ShowxNum(124,150,adcnum,4,16,0);//显示DAC寄存器值
			tem=(float)adcnum*(3.3/4096); //得到DAC电压值
			adcnum=tem;
			LCD_ShowxNum(124,170,tem,1,16,0);//显示电压值整数部分
			tem-=adcnum;tem*=1000;
			LCD_ShowxNum(140,170,tem,3,16,0X80);//显示电压值的小数部分
			adcnum=Get_Adc_Average(ADC_Channel_1,10);
			tem=(float)adcnum*(3.3/4096);
			adcnum=tem;
			LCD_ShowxNum(124,190,tem,1,16,0);
			tem-=adcnum;tem*=1000;
			LCD_ShowxNum(140,190,tem,3,16,0X80);
			t=0;
			LED0=!LED0;
		}
		delay_ms(10);
	}
}

最后在通过杜邦线将PA1和PA4连起来就好了。。至于为什么要连这两个口 看图

ADC1 和DAC1 分别挂在了 PA1和PA4上,所以我们想要通过ADC1采集DAC1输出的电压,就要将这两点连起来

时间: 2024-10-03 21:53:34

cortex_m3_stm32嵌入式学习笔记(十八):DAC实验(数模转换)的相关文章

cortex_m3_stm32嵌入式学习笔记(八):定时器中断实验

STM32 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和TIME7 等基本定时器. 本节学习通用定时器 TIM3 STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等. STM3 的通用 TIMx (TIM2. TIM3. TIM4 和 TIM5)定时器功能包括: 1)16 位向上.向下.向上/向下自动装载计数器( TIMx_CNT). 2)16 位可

cortex_m3_stm32嵌入式学习笔记(十九):DMA实验(高速传输)

DMA,全称为: Direct Memory Access,即直接存储器访问. DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路, 能使 CPU 的效率大为提高. 即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU. 一个完整的DMA传输过程必须经过下面的4个步骤. 1.DMA请求 CPU对DMA控制器初始化,并向I/O接

cortex_m3_stm32嵌入式学习笔记(十六):ADC实验(模数转换)

之前没学过数模电,对A/D D/A转换一窍不通,也百度了很多资料大都深奥难懂..算了,先自以为是一下吧,等以后学了专业课再说..(寒假回家一定要学..恩 就这么决定了)看了那么多资料,感觉 A/D转换就是将电压(或者是其他模拟量:如 压力,图像等)转换为数字,D/A就是反过来,而ADC就是A/D转换器,他可以采集外部电压转化为数字.本节实验通过ADC采集外部电压转换为数字显示在屏幕上. STM32 拥有 1~3 个 ADC( STM32F101/102 系列只有 1 个 ADC),这些 ADC

cortex_m3_stm32嵌入式学习笔记(十):输入捕捉实验(定时器的输入捕捉)

输入捕获模式可以用来测量脉冲宽度或者测量频率. STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能. STM32 的输入捕获,简单的说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值( TIMx_CNT)存放到对应的通道的捕获/比较寄存器( TIMx_CCRx)里面,完成一次捕获.同时还可以配置捕获时是否触发中断/DMA 等. 本章我们用到 TIM2_CH1 来捕获高电平脉宽,也就是要先设置输入捕获为上升沿

cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断)

很多单片机都有低功耗模式, STM32 也不例外.在系统或电源复位以后,微控制器处于运行状态.运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码.当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时.用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式. STM32 的低功耗模式有 3 种: 1)睡眠模式( CM3 内核停止,外设仍然运行) 2)停止模式(所有时钟都停止) 3)待机模式( 1.8V 内核电源关闭) 在这

cortex_m3_stm32嵌入式学习笔记(二十二):触摸屏实验(触摸屏驱动)

目前最常用的触摸屏有两种:电阻式触摸屏与电容式触摸屏. 电阻式触摸屏 在 Iphone 面世之前,几乎清一色的都是使用电阻式触摸屏, 电阻式触摸屏利用压力感应进行触点检测控制,需要直接应力接触, 通过检测电阻来定位触摸位置. 电阻触摸屏的主要部分是一块与显示器表面非常配合的电阻薄膜屏,这是一种多层的复合薄膜,它以一层玻璃或硬塑料平板作为基层,表面涂有一层透明氧化金属(透明的导电电阻)导电层,上面再盖有一层外表面硬化处理.光滑防擦的塑料层.它的内表面也涂有一层涂层.在他们之间有许多细小的(小于 1

cortex_m3_stm32嵌入式学习笔记(二十):IIC实验(I2C串行总线)

IIC(Inter- Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备.它是由数据线SDA 和时钟SCL构成的串行总线,可发送和接收数据.在 CPU 与被控 IC 之间. IC 与 IC 之间进行双向传送, 高速 IIC 总线一般可达 400kbps 以上. ALIENTEK MiniSTM32 开发板板载的 EEPROM 芯片型号为 24C02.该芯片的总容量是 256个字节,该芯片通过 IIC 总线与外部连接,我们本章

cortex_m3_stm32嵌入式学习笔记(二十四):内存管理实验(动态内存)

有用过C语言编程的童鞋对动态管理内存肯定有点了解..好处就不多说了 今天实现STM32的动态内存管理 内存管理,是指软件运行时对计算机内存资源的分配和使用的技术.其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源. 内存管理的实现方法有很多种,他们其实最终都是要实现两个函数:malloc 和 free(好熟悉): malloc 函数用于内存申请, free 函数用于内存释放. 实现方式:分块式内存管理 从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成.内存池被等

cortex_m3_stm32嵌入式学习笔记(四):外部中断实验

本章学习将STM32的IO口作为外部中断输入(实现和按键扫描一样的功能) STM32 的每个 IO 都可以作为外部中断的中断输入口,这点也是 STM32 的强大之处. STM32F103 的中断控制器支持 19 个外部中断/事件请求.每个中断设有状位,每个中断/事件都有独立的触发和屏蔽设置. STM32F103 的19 个外部中断为: 线 0~15:对应外部 IO 口的输入中断.(本章只学习这一种) 线 16:连接到 PVD 输出. 线 17:连接到 RTC 闹钟事件. 线 18:连接到 USB