数字和模拟是电子学的一个组成部分。大多数设备同时具有adc和 dac,当需要将信号从模拟转换为数字或从数字转换为模拟时使用它们。此外,声音和光等现实世界的信号本质上是模拟的,因此无论何时必须使用这些现实世界的信号,都必须将数字信号转换为模拟信号,例如使用扬声器产生声音或控制光源。
另一种类型的 dac 是脉冲宽度调制器 (pwm)。pwm 接收一个数字字并生成一个具有可变脉冲宽度的数字脉冲。当这个信号通过一个滤波器时,结果将是纯模拟的。一个模拟信号在一个信号中可以有多种类型的数据。
在本教程中,我们将dac mcp4921 与 microchip pic16f877a 接口以进行数模转换。
在本教程中,我们将数字信号转换为模拟信号,并在16x2 lcd上显示输入数字值和输出模拟值。它将提供 1v、2v、3v、4v 和 5v 作为最终的模拟输出,这在最后给出的视频中进行了演示。
dac 可用于许多应用 ,例如电机控制、led 灯的控制亮度、 音频放大器、视频编码器、数据采集系统等。在直接跳转到接口部分之前,了解 mcp4921 的概述非常重要。
mcp4921 dac(数模转换器)
mcp4921 是 12 位 dac,因此 mcp4921 将提供 12 位输出分辨率。dac 分辨率是指可以转换为模拟信号的数字位数。我们可以从中获得多少价值是基于公式的。对于 12 位,它 = 4096。这意味着 12 位分辨率 dac 可以产生 4096 个不同的输出。
通过使用该值,可以轻松计算单个模拟阶跃电压。为了计算步数,需要参考电压。由于该器件的逻辑电压为 5v,因此步进电压为 5/4095(4096-1,因为数字的起点不是 1,而是 0),即 0.00122100122 毫伏。因此,更改 1 位将使模拟输出更改为 0.00122100122。
所以,这就是转换部分。mcp4921是一个 8 引脚 ic。引脚图和说明可以在下面找到。
mcp4921 ic通过spi 协议与微控制器通信。对于 spi 通信,设备必须是主设备,它向作为从设备连接的外部设备提交数据或命令。在 spi 通信系统中,单个主设备可以连接多个从设备。
要提交数据和命令,了解命令寄存器很重要。
在下图中,显示了命令寄存器,
命令寄存器是一个16 位寄存器。bit-15 到 bit-12 用于配置命令。上图清楚地显示了数据输入和配置。在本项目中,mcp4921 将用作以下配置 -
所以二进制是 0011 以及由寄存器的 d11 到 d0 位确定的数据。需要提交16位数据0011 xxxx xxxx xxxx,其中msb的前4位为配置,其余为lsb。看写命令时序图会更清楚。
根据时序图和数据表,在向 mcp4921 的整个命令写入周期内,cs 引脚为低电平。
现在是时候将设备与硬件连接并编写代码了。
所需组件
对于这个项目,需要以下组件 -
mcp4921
pic16f877a
20兆赫晶体
显示 16x2 字符 lcd。
2k电阻-1个
33pf 电容器 - 2 个
4.7k 电阻器 - 1 个
万用表测量输出电压
面包板
5v供电,一个手机充电器即可工作。
很多连接线或 berg 线。
带有 programmer 套件和带有编译器的 ide 的 microchip 编程环境
示意图
将dac4921 与 pic 微控制器连接的电路图 如下所示:
该电路是在面包板中构建的-
代码说明
文章末尾给出了使用 pic16f877a 将数字信号转换为模拟信号 的完整代码。与往常一样,我们首先需要 设置 pic 单片机中的配置位。
// pic16f877a 配置位设置// 'c' 源代码行配置语句// config#pragma config fosc = hs // 振荡器选择位(hs 振荡器)#pragma config wdte = off // 看门狗定时器使能位(wdt 禁用)#pragma config pwrte = off // 上电定时器使能位(pwrt 禁用)# pragma config boren = on // 欠压复位使能位(bor 使能)#pragma config lvp = off // 低电压(单电源)在线串行编程使能位(rb3/pgm 引脚具有 pgm 功能;低-电压编程启用)#pragma config cpd = off // 数据 eeprom 存储器代码保护位(数据 eeprom 代码保护关闭)#pragma config wrt = off // 闪存程序存储器写使能位(写保护关闭;所有程序存储器都可以由 eecon 控制写入)#pragma config cp = off // flash 程序存储器代码保护位(代码保护关闭)
以下代码行用于集成 lcd 和 spi 头文件,还声明了 xtal 频率和 dac 的 cs 引脚连接。
pic spi 教程和库可以在给定的链接中找到。
#include #include #include supporing_cfile\lcd.h #include supporing_cfile\pic16f877a_spi.h/*硬件相关定义*/#define _xtal_freq 200000000 //晶体频率,用于延迟#define dac_cs portcbits.rc0 //声明dac cs引脚
spi_initialize_master ()功能针对该项目所需的不同配置稍作修改。在这种情况下,sspstat 寄存器的配置方式是,在数据输出时间结束时采样输入数据以及配置为发送的 spi 时钟发生在从活动时钟状态模式转换到空闲时钟状态模式时。其他也一样。
无效 spi_initialize_master() { trisc5 = 0; // 设置为输出 sspstat = 0b11000000; //pg 74/234 sspcon = 0b00100000; //pg 75/234 trisc3 = 0; //设置为从模式的输出}
此外,对于以下函数,spi_write() 稍作修改。数据传输将在缓冲区清空后进行,以确保通过 spi 进行完美的数据传输。
无效 spi_write(char 传入) { sspbuf = 传入; //将用户给定的数据写入缓冲区 while (!sspstatbits.bf); }
该程序的重要部分是 mcp4921 驱动程序。这是一个有点棘手的部分,因为命令和数字数据被打孔在一起以通过 spi 提供完整的 16 位数据。但是,该逻辑清楚地显示在代码注释中。
/*此函数用于将数字值转换为模拟值。*/ void convert_dac(unsigned int value) { /*步长 = 2^n, 因此 12bit 2^12 = 4096 对于 5v 参考,步长将为 5/4095 = 0.0012210012210012v 或 1mv(大约)*/ unsigned int 容器; 无符号整数 msb; 无符号整数 lsb; /*步骤:1、将12位数据存入容器 假设数据为4095,二进制1111 1111 1111*/ container = value; /*步骤:2 创建虚拟 8 位。因此,通过除以 256,在 lsb 中捕获高 4 位 lsb = 0000 1111*/ lsb = container/256; /*step: 3 发送配置打孔4位数据。 lsb = 0011 0000 或 0000 1111。结果为 0011 1111 */ lsb = (0x30) | 低位; /*step:4 容器仍然有 21bit 的值。提取低 8 位。 1111 1111 和 1111 1111 1111。结果是 1111 1111,即 msb*/ msb = 0xff & 容器; /*step:4 将16bits的数据分成两个字节发送。*/ dac_cs = 0; // 数据传输期间 cs 为低电平。根据数据表,需要 spi_write(lsb); spi_write(msb); dac_cs = 1; }
在主函数中,使用“for 循环”来创建用于创建 1v、2v、3v、4v 和 5v 输出的数字数据。数字值是根据输出电压 / 0.0012210012210012 毫伏计算得出的。
无效 main() { system_init(); 介绍屏幕(); 整数=0; 国际伏特=0; 而 (1) { for (volt=1; volt<=max_volt; volt++){ number = volt / 0.0012210012210012; 清除屏幕(); lcd_com(first_line); lcd_puts(数据发送:-); lcd_print_number(数字); lcd_com(第二行); lcd_puts(输出:-); lcd_print_number(伏特); lcd_puts(v); 转换_dac(数字); __delay_ms(300); } } }
使用 pic 测试数模转换
使用万用表测试构建的电路。在下图中,输出电压和数字数据显示在 lcd 上。万用表显示接近读数。
/*
* 文件:main.c
* 作者:苏拉夫·古普塔 *<|:-]
* 创建于:circuitdigest.com
* 项目:mcp4921 接口
* 创建于 2019 年 3 月 21 日晚上 7:05
*/
// pic16f877a 配置位设置
// 'c' 源代码行配置语句
// 配置
#pragma config fosc = hs // 振荡器选择位(hs 振荡器)
#pragma config wdte = off // 看门狗定时器启用位(wdt 禁用)
#pragma config pwrte = off // 上电定时器使能位(pwrt 禁用)
#pragma config boren = on // 欠压复位使能位(bor 使能)
#pragma config lvp = off // 低压(单电源)在线串行编程使能位(rb3/pgm 引脚具有 pgm 功能;低压编程使能)
#pragma config cpd = off // 数据 eeprom 存储器代码保护位(数据 eeprom 代码保护关闭)
#pragma config wrt = off // flash 程序存储器写使能位(写保护关闭;eecon 控制可以写入所有程序存储器)
#pragma config cp = off // flash 程序存储器代码保护位(代码保护关闭)
#include
#include
#include supporting_cfile\lcd.h
#include supporting_cfile\pic16f877a_spi.h
/*
硬件相关定义
*/
#define _xtal_freq 200000000 //晶体频率,用于延迟
#define dac_cs portcbits.rc0 //声明dac cs引脚
/*
程序流相关定义
*/
#define max_volt 5
#define first_line 0x80
#define second_line 0xc0
/*
其他具体功能定义
*/
无效系统初始化(无效);
无效 sw_delayms(无符号整数 d);
无效转换_dac(无符号整数数字值);
无效清除屏幕(无效);
无效介绍屏幕(无效);
无效的主要(){
系统初始化();
介绍屏幕();
整数=0;
国际伏特=0;
而(1){
对于(伏特=1;伏特<=max_volt;伏特++){
数字 = 伏特 / 0.0012210012210012;
清除屏幕();
lcd_com(first_line);
lcd_puts(数据发送:-);
lcd_print_number(数字);
lcd_com(第二行);
lcd_puts(输出:-);
lcd_print_number(伏特);
lcd_puts(v);
转换_dac(数字);
__delay_ms(300);
}
}
}
/*
此功能用于软件延迟。
*/
无效 sw_delayms(无符号整数 d){
整数 x, y;
for(x=0;x
for(y=0;y<=1275;y++);
}
/*
该函数用于系统初始化。
*/
无效系统初始化(无效){
trisb = 0x00;// lcd 引脚作为输出
triscbits.trisc0=0;// cs 引脚声明为输出
液晶初始化();//这将初始化lcd
spi_initialize_master();
}
/*
此功能用于在没有命令的情况下清除屏幕。
*/
无效清除屏幕(无效){
lcd_com(first_line);
lcd_puts();
lcd_com(第二行);
lcd_puts();
}
/*
此功能用于播放介绍。
*/
无效介绍屏幕(无效){
lcd_com(first_line);
lcd_puts(欢迎来到);
lcd_com(第二行);
lcd_puts(电路文摘);
__delay_ms(500);
清除屏幕();
lcd_com(first_line);
lcd_puts(mcp4921 with);
lcd_com(第二行);
lcd_puts(pic16f877a);
__delay_ms(350);
}
/*
此功能用于将数字值转换为模拟值。
*/
无效转换_dac(无符号整数值)
{
/*步长 = 2^n,因此 12bit 2^12 = 4096
对于 5v 参考,步长为 5/4095 = 0.0012210012210012v 或 1mv(大约)*/
无符号整数容器;
无符号整数 msb;
无符号整数 lsb;
/*step: 1、将12位数据存入容器
假设数据为4095,二进制1111 1111 1111*/
容器=价值;
/*步骤:2 创建虚拟 8 位。因此,通过除以 256,在 lsb 中捕获高 4 位
lsb = 0000 1111*/
lsb = 容器/256;
/*step: 3 发送配置打孔4位数据。
lsb = 0011 0000 或 0000 1111。结果为 0011 1111 */
lsb = (0x30) | 低位;
/*step:4 容器仍然有 21bit 的值。提取低 8 位。
1111 1111 and 1111 1111 1111。结果为 1111 1111,即 msb*/
msb = 0xff & 容器;
/*step:4 将16bits的数据分成两个字节发送。*/
dac_cs = 0;// 数据传输期间 cs 为低电平。根据数据表,它是必需的
spi_write(lsb);
spi_write(msb);
dac_cs = 1;
}
如何在电脑上玩转华为 VR Glass
一种人工智能系统可以很好地治疗严重的心脏病
回顾海峡两岸半导体产业合作发展的介绍和说明
详细解析指针式万用电表使用方法及注意事项
关于IGBT的特性
将MCP4921与PIC16F877A接口进行数模转换的方法
“芯荒”烧到路由器 网通芯片全面缺货
人体对电流的反应
Vishay新款850nm红外发射器VSLY5850
涂鸦智能放野全球成立战略委员会
远鉴科技用生物识别技术开启智慧安防之门
大功率电机控制器硬件在环系统仿真测试
电感测微仪主要的技术指标_电感测微仪硬件特点
2018区块链、大数据、物联网三大板块中国进入下一个“造富时代”,先睹为快!
电池将开拓清洁能源的未来(后篇)
苹果高管诠释新iPad电池问题:寿命不受影响
卷积神经网络是实现深度学习的重要方法之一
带定时器的星三角控制电路图
思必驰携手博纳时代助力亚洲金融协会打造高效国际会议
华为nova 4e即将发布采用了一颗3200万像素的自拍摄像头