嵌入式开发学习(STC51-17-DAC数模转换)

news2024/9/20 16:36:29

内容

使DAC(PWM)模块上的指示灯DA1呈呼吸灯效果,由暗变亮再由亮变暗;

DAC介绍

简介

DAC(Digital to analog converter)即数字模拟转换器,它可以将数字信号转换为模拟信号,它的功能与ADC相反;

在常见的数字信号系统中,大部分传感器信号被转化成电压信号,而ADC把电压模拟信号转换成易于计算机存储、处理的数字编码,由计算机处理完成后,再由DAC输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知;如音频信号的采集及还原就是这样一个过程;

主要技术指标

分辨率

DAC的分辨率是输入数字量的最低有效位(LSB)发生变化时,所对应的输出模拟量(电压或电流)的变化量,它反映了输出模拟量的最小变化值;

分辨率与输入数字量的位数有确定的关系,可以表示成FS/(2^n),FS表示满量程输入值,n为二进制位数;

对于5V的满量程,采用8位的DAC时,分辨率为5V/256=19.5mV;当采用12位的DAC时,分辨率则为5V/4096=1.22mV;显然,位数越多分辨率就越高;

线性度

线性度(也称非线性误差)是实际转换特性曲线与理想直线特性之间的最大偏差;

常以相对于满量程的百分数表示,如±1%是指实际输出值与理论值之差在满刻度的±1%以内;

绝对精度和相对精度

绝对精度(简称精度)是指在整个刻度范围内,任一输入数码所对应的模拟量实际输出值与理论值之间的最大误差;

绝对精度是由DAC的增益误差(当输入数码为全1时,实际输出值与理想输出值之差)、零点误差(数码输入为全0时,DAC的非零输出值)、非线性误差和噪声等引起的;

绝对精度(即最大误差)应小于1个LSB;

相对精度与绝对精度表示同一含义,用最大误差相对于满刻度的百分比表示;

建立时间

建立时间是指输入的数字量发生满刻度变化时,输出模拟信号达到满刻度值的±1/2LSB所需的时间;

是描述D/A转换速率的一个动态指标;

根据建立时间的长短,可以将DAC分成超高速(<1μS)、高速(10~1μS)、中速(100~10μS)、低速(≥100μS)几档;

工作原理

其内部结构图如下所示:
在这里插入图片描述
DAC输出电压计算公式:V0=Vref*z/256;

公式中的z表示单片机给的数字量;vref为参考电压,通常我们是接在系统电源上,即5V;数值256表示DAC精度为8位;

DAC主要由数字寄存器、模拟电子开关、位权网络、求和运算放大器和基准电压源(或恒流源)组成;

用存于数字寄存器的数字量的各位数码,分别控制对应位的模拟电子开关,使数码为1的位在位权网络上产生与其位权成正比的电流值,再由运算放大器对各电流值求和,并转换成电压值;

上述的模拟电子开关都分别接着一个分压的器件,比如说电阻;

模拟开关的个数取决于DAC的精度,N个电子开关就把基准电压分为N份(并不是平均分),而这些开关根据输入的二进制每一位数据对应开启或者关闭,把分压的器件上的电压引入输出电路中;

PWM介绍

简介

PWM是Pulse Width Modulation的缩写,中文意思就是脉冲宽度调制,简称脉宽调制;

将数字信号输出转换为模拟信号输出,需要相应的转换器,这种转换器我们称之为DAC数模转换器,但DAC专用芯片价格是比较高的,在实际应用中通常使用PWM技术来模拟DAC输出;

51开发板上集成了一个DAC(PWM)模块电路,因此我们可以通过单片机IO口生成PWM波来模拟DAC输出;

它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成为电力电子技术最广泛应用的控制方式,其应用领域包括测量,通信,功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些音频放大器,因此学习PWM具有十分重要的现实意义;

原理

我们可以理解为,PWM是一种对模拟信号电平进行数字编码的方法;

通过高分辨率计数器的使用,方波的占空比调制,来对一个具体模拟信号的电平进行编码;

PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF);

电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的;通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候;

只要带宽足够,任何模拟值都可以使用PWM进行编码;

PWM对应模拟信号的等效图,如下图所示:
在这里插入图片描述
从图中可以看到,上图a是一个正弦波即模拟信号,b是一个数字脉冲波形即数字信号;

我们知道在计算机系统中只能识别是1和0,对于51单片机芯片,要么输出高电平(5V),要么输出低电平(0),假如要输出1.5V的电压,那么就必须通过相应的处理,比如PWM输出;

从上图也可以看到,只要保证数字信号脉宽足够就可以使用PWM进行编码,从而输出1.5V的电压;

PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号,信号频率是由T的值决定,占空比由C的值决定;

其示意图如图所示:
在这里插入图片描述
从上图中可以看到,PWM输出频率是不变的,改变的是C的值,此值的改变将导致PWM输出信号占空比的改变;

占空比其实就是一个周期内高电平时间与周期的比值;

而频率的话可以使用51单片机的定时器确定;

原理图

在这里插入图片描述
从上图中可知,PWM控制管脚接在单片机P2.1管脚上,DAC1为PWM信号输出管脚;

DAC1连接了一个LED灯即DA1,这样就可以通过指示灯DA1的状态直观的反映出PWM输出电压值变化;

输出信号由J52端子的DAC1引出,在其端子上还有一个AIN3脚,它就是ADC的外部模拟信号输入通道;

如果使用短接片将DAC1和AIN3短接,这样就可以使用XPT2046芯片采集检测PWM输出信号;

思路

通过调节占空比,即操作PWM控制管脚/p21管脚,使其输出对应的模拟信号,从而使DA1灯亮度呼吸变化;

通过定时器中断来确定电位变化的周期和占空比;

设置一个循环,使占空比不断变化,变化不能太快,也不能太慢,最好能直观看到灯光亮度的呼吸变化;

编码

User

main.c

/*
 * @Description: 使指示灯DA1呈呼吸灯效果,由暗变亮再由亮变暗
 */
#include "public.h"
#include "pwm.h"

void main()
{

	u8 dir = 0; // 默认为0
	u8 duty = 0;

	pwm_init(0XFF, 0XF6, 100, 0); // 定时时间为0.01ms,PWM周期是100*0.01ms=1ms,占空比为0%

	while (1) // 通过循环的方式不断改变占空比
	{

		if (dir == 0) // 当dir为递增方向
		{
			duty++; // 占空比递增
			if (duty == 70)
				dir = 1; // 当到达一定值切换方向,占空比最大能到100,但到达70左右再递减,肉眼也分辨不出亮度变化
		}
		else
		{
			duty--;
			if (duty == 0)
				dir = 0; // 当到达一定值切换方向
		}
		pwm_set_duty_cycle(duty); // 设置占空比
		delay_ms(1);			  // 短暂延时,让呼吸灯有一个流畅的效果
	}
}

Public

public.h

#ifndef _public_H
#define _public_H

#include "reg52.h"

typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;

void delay_10us(u16 ten_us);
void delay_ms(u16 ms);

#endif

public.c

#include "public.h"

/**
 * @description: 延时函数,ten_us=1时,大约延时10us
 * @param {u16} ten_us 延时倍数
 * @return {*}
 */
void delay_10us(u16 ten_us)
{
	while (ten_us--)
		;
}

/**ms延时函数,ms=1时,大约延时1ms***
 * @param {u16} ms 延时倍数
 * @return {*}
 */
void delay_ms(u16 ms)
{
	u16 i, j;
	for (i = ms; i > 0; i--)
		for (j = 110; j > 0; j--)
			;
}

App/pwm

pwm.h

#ifndef _pwm_H
#define _pwm_H

#include "public.h"

// 管脚定义
sbit PWM = P2 ^ 1;

// 变量声明
extern u8 gtim_scale;

// 函数声明
void pwm_init(u8 tim_h, u8 tim_l, u16 tim_scale, u8 duty);
void pwm_set_duty_cycle(u8 duty);

#endif

pwm.c

#include "pwm.h"

// 全局变量定义
u8 gtim_h = 0;	   // 保存定时器初值高8位
u8 gtim_l = 0;	   // 保存定时器初值低8位
u8 gduty = 0;	   // 保存PWM占空比
u8 gtim_scale = 0; // 保存PWM周期=定时器初值*tim_scale

/**
 * @description: PWM初始化函数(通过定时器中断实现)
 * @param {u8} tim_h 定时器高8位
 * @param {u8} tim_l 定时器低8位
 * @param {u16} tim_scale 周期倍数=定时器初值*tim_scale
 * @param {u8} duty 占空比(要小于等于tim_scale)
 * @return {*}
 */
void pwm_init(u8 tim_h, u8 tim_l, u16 tim_scale, u8 duty)
{
	gtim_h = tim_h; // 将传入的初值保存在全局变量中,方便中断函数继续调用
	gtim_l = tim_l;
	gduty = duty;
	gtim_scale = tim_scale;

	TMOD |= 0X01; // 选择为定时器0模式,工作方式1
	TH0 = gtim_h; // 定时初值设置
	TL0 = gtim_l;
	ET0 = 1; // 打开定时器0中断允许
	EA = 1;	 // 打开总中断
	TR0 = 1; // 打开定时器
}

/**
 * @description: PWM设置占空比
 * @param {u8} duty PWM占空比(要小于等于tim_scale)
 * @return {*}
 */
void pwm_set_duty_cycle(u8 duty)
{
	gduty = duty;
}

/**
 * @description: 定时器0中断函数
 * @return {*}
 */
void pwm(void) interrupt 1 // 中断号必须对应上
{
	static u16 time = 0;

	TH0 = gtim_h; // 定时初值设置
	TL0 = gtim_l;

	time++;
	if (time >= gtim_scale) // PWM周期=定时器初值*gtim_scale,重新开始计数
		time = 0;
	
	if (time <= gduty) // 占空比
		PWM = 1; 
	else
		PWM = 0;
}

编译和结果

按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机

结果:指示灯DA1以一定周期明暗变化;
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/840848.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java设计模式】建造者模式 注解@Builder

概念 将一个复杂对象的构造与它的表示分离&#xff0c;使同样的构建过程可以创建不同的表示。它使将一个复杂的对象分解成多个简单的对象&#xff0c;然后一步步构建而成。 每一个具体建造者都相对独立&#xff0c;而与其它的具体建造者无关&#xff0c;因此可以很方便地替换具…

【HDFS】每天一个RPC系列----complete(二):客户端侧

上图给出了最终会调用到complete RPC的客户端侧方法链路(除去Router那条线了)。 org.apache.hadoop.hdfs.DFSOutputStream#completeFile(org.apache.hadoop.hdfs.protocol.ExtendedBlock): 下面这个方法在complete rpc返回true之前,会进行重试,直到超过最大重试次数抛异…

解决Element Plus中Select在El Dialog里层级过低的问题(修改select选项框样式)

Element Plus是Vue.js的一套基于Element UI的组件库&#xff0c;提供了丰富的组件用于构建现代化的Web应用程序。其中&#xff0c;<el-select>是一个常用的下拉选择器组件&#xff0c;但在某些情况下&#xff0c;当<el-select>组件嵌套在<el-dialog>&#xf…

Python web实战之Django的文件上传和处理详解

概要 关键词&#xff1a;Python Web开发、Django、文件上传、文件处理 今天分享一下Django的文件上传和处理。 1. 上传文件的基本原理 在开始深入讲解Django的文件上传和处理之前&#xff0c;先了解一下文件上传的基本原理。当用户选择要上传的文件后&#xff0c;该文件会被发…

Oracle-ORA-00600:[ktspffbmb:objdchk_kcbnew_3]

问题背景: 应用执行存储过程报错ORA-00600: 内部错误代码, 参数: [ktspffbmb:objdchk_kcbnew_3], [0], [3303775], [4], [], [], [], [], [], [], [], []&#xff0c;导致过程无法正常执行 ORA-00600: 内部错误代码, 参数: [ktspffbmb:objdchk_kcbnew_3], [0], [3303775], [4]…

关联字典表查询记录

字典表 也可以case gender when xxx then xxx when xxx then xxx end 别名 注意前面case别忘了 重新编辑了下 字典表 key value更加合理点吧 嘿嘿

【计算机视觉】关于图像处理的一些基本操作

目录 图像平滑滤波处理均值滤波计算过程python实现 高斯滤波计算过程python实现 中值滤波计算过程python实现 图像的边缘检测Robert算子计算过程python实现 图像处理腐蚀算子计算过程python实现 Hog&#xff08;梯度方向直方图&#xff09;特征计算流程&#xff1a;Hog的特征维…

数据库操作系列-Mysql, Postgres常用sql语句总结

文章目录 1.如果我想要写一句sql语句&#xff0c;实现 如果存在则更新&#xff0c;否则就插入新数据&#xff0c;如何解决&#xff1f;MySQL数据库实现方案: ON DUPLICATE KEY UPDATE写法 Postgres数据库实现方案:方案1&#xff1a;方案2&#xff1a;关于更新&#xff1a;如何实…

【项目多人协作的困扰】git-cli 解决 git merge 合并时 lock 文件变化,忘记重新安装依赖的问题

项目多人协作的困扰 相信大家多多少少都遇到过&#xff0c;当主线分支的代码&#xff0c;合入到自己的分支的时候&#xff0c;如果这时候&#xff0c;主线中有一些依赖的更新或者添加或者删除&#xff0c;如果合入之后&#xff0c;没有及时的install的话&#xff0c;项目启动的…

力扣 -- 467. 环绕字符串中唯一的子字符串

一、题目 二、解题步骤 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 三、参考代码 class Solution { public:int findSubstringInWraproundString(string s) {int ns.size();vector<int> dp(n,1);int re…

diffusion model(六)Dalle2技术小结

Dalle2 技术小结 文章目录 Dalle2 技术小结系列阅读背景Dalle2的总体架构DiffusionPrior模块训练阶段推理阶段 DiffusionDecode 模块 Dalle2的生成质量和目前的局限性Dalle2的生成效果基于MS-COCO caption生成效果Other Dalle2的局限性 参考文献 系列阅读 diffusion model&…

Ubuntu服务器ELK部署与实践

文章目录 1. Docker安装2. 拉镜象2.1 ElastciSearch2.2 Kibana2.3 logstash 3. 数据展示 1. Docker安装 看之前的文章 docker ubuntu完全卸载docker及再次安装 Ubuntu安装 Docker 此外&#xff0c;Docker偶尔会出现这种问题dial tcp: lookup registry-1.docker.io on 192.168.1…

ICMP 理解

icmp 差错报告机制&#xff0c;tcp/ip协议族中重要的子协议&#xff0c;通常被ip层或者更高的&#xff08;tcp/udp&#xff09;使用&#xff0c;&#xff0c;属于网络层协议&#xff0c;主要用于在ip主机和路由器之间传递控制消息&#xff0c;用于报告主机是否可达、路由是否可…

融邦JAVA面试题

1. Java线程池的作用及使用方式 线程池的作用&#xff1a; (1) 降低系统资源消耗&#xff1a;通过重用已存在的线程&#xff0c;降低线程创建和销毁造成的消耗。 (2) 提高系统响应速度&#xff1a;当有任务到达时&#xff0c;无需等待新线程的创建便能立即执行。 (3) 提高线程…

SpringBoot3基础用法

技术和工具「!喜新厌旧」 一、背景 最近在一个轻量级的服务中&#xff0c;尝试了最新的技术和工具选型&#xff1b; 即SpringBoot3&#xff0c;JDK17&#xff0c;IDEA2023&#xff0c;Navicat16&#xff0c;虽然新的技术和工具都更加强大和高效&#xff0c;但是适应采坑的过程…

阿里云瑶池 PolarDB 开源官网焕新升级上线

导读近日&#xff0c;阿里云开源云原生数据库 PolarDB 官方网站全新升级上线。作为 PolarDB 开源项目与开发者、生态伙伴、用户沟通的平台&#xff0c;将以开放、共享、促进交流为宗旨&#xff0c;打造开放多元的环境&#xff0c;以实现共享共赢的目标。 立即体验全新官网&…

【测试】软件测试工具JMeter简单用法

简明扼要&#xff0c;点到为止。 1. JMeter介绍 JMeter的全称是Apache JMeter&#xff0c;是一款用于软件测试的工具软件&#xff0c;其是开源免费的&#xff0c;由Apache基金会运营。 官网&#xff1a;Apache JMeter - Apache JMeter™ 2. 下载安装及运行 2.1 安装 Java8…

RabbitMQ的6种工作模式

RabbitMQ的6种工作模式 官方文档&#xff1a; http://www.rabbitmq.com/ https://www.rabbitmq.com/getstarted.html RabbitMQ 常见的 6 种工作模式&#xff1a; 1、simple简单模式 1)、消息产生后将消息放入队列。 2)、消息的消费者监听消息队列&#xff0c;如果队列中…

深入探究Spring核心模块

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Flowise AI:用于构建LLM流的拖放UI

推荐&#xff1a;使用NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是Flowise AI&#xff1f; Flowise AI是一个开源的UI可视化工具&#xff0c;用于帮助开发LangChain应用程序。在我们详细介绍 Flowise AI 之前&#xff0c;让我们快速定义 LangChain。LangChain是…