引言
PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入、一个输出和一个串行I2C 总线接口。3 个地址引脚A0、A1 和A2 用于编程硬件地址,允许将最多8 个器件连接至I2C总线而不需要额外硬件。PCF8591由于其使用的简单方便和集成度高,在单片机应用系统中得到了广泛的应用,这篇文章是介绍IIC通信在ADDA转换芯片PCF8591中的应用。
关于IIC
IIC总线通信协议的介绍在"基于51单片机IIC通信的AT24C02学习笔记"有详细的介绍。
关于PCF8591
PCF8591是单片、单电源低功耗8位CMOS数据采集器件,具有4个模拟输入、一个输出和一个串行I2C总线接口。3个地址引脚A0、A1 和A2 用于编程硬件地址,允许将最多8个器件连接至I2C总线而不需要额外硬件。器件的地址、控制和数据通过两线双向I2C总线传输。器件功能包括多路复用模拟输入、片上跟踪和保持功能、8位模数转换和8位数模拟转换。最大转换速率取决于I2C总线的最高速率。
PCF8591的操作和AT24C02非常类似,只不过AT24C02是写入或读出数据,而PCF8591是AIN端口输入模拟电压,然后PCF8591将转换后的数字量通过IIC总线发送给单片机,或是单片机通过IIC总线给一个数字量,然后PCF8591通过AOUT端口将模拟电压输出.
控制字格式
最高位默认为0
第6位是选择是否允许模拟电压输出,在DA转换时设置为1,AD转换时设置为0或1均可
第5/4位是选择模拟电压输出方式,一般选择00单端输入方式,其他的几种方式如下图所示
第3位默认为0
第2位是自动增量使能位,如果自动增量(auto-increment)标志置1,每次A/D 转换后通道号将自动增加。
第1/0为是在AD转换时选择哪一个通道输入的电压转换为数字量.
PCF8591的器件地址
每一个IIC器件都有一个器件地址,来区分不同的IIC设备,下面是PCF8591的地址
它的地址是由1001和A2A1A0组成的,在原理图中可以看出,A2A1A0均为0,所以器件地址为0x90/0x91,最后一位是读写方向位,0表示下一个字节往总线上写数据,1表示下一个字节从总线上读取数据.
AD转换函数
AD转换即将AIN端口输入的模拟电压转换为数字量并发送到总线上,可以知道该函数需要指定输入的通道,还要将转换后的数字量返回,所以该函数有返回值,和一个形参
程序实现:
/*读取某一个通道转换后的数字量*/
uchar Read_D(uchar Channel)
{
uchar dat;
start();
write_byte(0x90); //器件地址+0
ack();
write_byte(Channel); //控制字0x01表示通道1
ack();
start();
write_byte(0x91); //器件地址+1,下一个字节要读取
ack();
dat=read_byte();
ack();
stop();
// AD_led=0; //转换成功显示
return dat;
}
DA转换函数
DA转换即将从总线上接收到的数字量通过AOUT输出,该函数无返回值,有一个形参
程序实现:
void Out_A(uchar Digital)
{
start();
write_byte(0x90); //器件地址+0,下一个字节为写入
ack();
write_byte(0x40); //设置控制字 0100 0000 允许模拟输出,不自增单端
ack();
write_byte(Digital); //将要转换的数字量写入
ack();
stop();
// DA_led=0; //转换成功显示
}
转换公式
我们可以用一个转换公式,将AD转换后的数字量转换为对应的电压值,在数码管或液晶上显示,公式如下:
#define fun(x) (int)(5*x/255.0*100+0.5) //数字电压x转换为模拟电压的公式
主函数调用
dat1 = Read_D(0x01); //将通道1(电位器v2)的模拟电压转换的数字量读出
Out_A(dat1); //将数字量转换为模拟量输出到led显示
dis_Voltage1(fun(dat1)); //数码管显示电压值
Delay_Ms(5); //延时缓冲
这样就可以实时显示输入的电压值了.还可以将电压值输出到led亮度显示出来.这样就可以作为一个简易的小量程(5v)的电压表了
总结
从程序可以看出PCF8591的操作和AT24C02基本一致,就是增加了控制字的内容,相比于其他的ADDA转换芯片,它结构简单,不需要外围的电路,可以直接使用,而且容易实现模块化设计,在大多数单片机系统中ADDA几乎是不可缺少的,而PCF8591只需要两个IO口(时钟和数据)和电源就可以实现,大大节省了IO口的使用。
关于AT24C02的使用,请看我另一篇随笔:“基于51单片机IIC通信的AT24C02学习笔记”
参考资料:
PCF8591_百度百科
iic_百度百科
我的其他博文:
- 一键自动格式化你的代码
- C标准库string.h中几个常用函数的使用详解
- Jlink使用技巧系列教程索引
- Jlink使用技巧之烧写SPI Flash存储芯片
- Jlink使用技巧之虚拟串口功能
- Jlink使用技巧之读取STM32内部的程序
- Jlink使用技巧之J-Scope虚拟示波器功能
- 基于uFUN开发板的RGB调色板
- 基于uFUN开发板的心率计(一)DMA方式获取传感器数据
- 基于uFUN开发板的心率计(二)动态阈值算法获取心率值
- 基于uFUN开发板的心率计(三)Qt上位机的实现
- Qt实现软件自动更新的一种简单方法
- 【UFUN开发板评测】小巧而不失精致,简单而不失内涵——uFun开发板开箱爆照
- 如何使用串口来给STM32下载程序
- STM32串口打印输出乱码的解决办法
- Keil报错:cannot open source input file "core_cmInstr.h" 解决办法
欢迎大家关注我的个人博客:www.wangchaochao.top
或微信扫码关注我的公众号
基于51单片机IIC通信的PCF8591学习笔记的更多相关文章
-
基于51单片机IIC通信的AT24C02学习笔记
引言 最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章. 关于IIC总线 IIC 即Inter ...
-
51单片机RAM 数据存储区学习笔记
转自:http://www.eepw.com.cn/article/216237_2.htm 1.RAM keil C语言编程 RAM是程序运行中存放随机变量的数据空间.在keil中编写程序,如果当前 ...
-
ET 与RETI 基于51单片机中断跳出指令“RETI”浅议
最近在基于51单片机编程的过程中出现了个很奇怪的问题“程序执行中在寄存器EA=1,ET0=1,TR0=1条件下,单TF0=1时并没有执行中断”.在有过单片机中断编程经历者都知道当EA=1,ET0=1的 ...
-
基于51单片机个LCD1602的万年历程序
小白 第一次跟新博客 基于51单片机和LCD1602的万年历程序 可实现走时和调时功能 有简单的1602菜单制作 欢迎大家交流 LCD1602和51单片机的连接方法 RS = P3^5; //数据/命 ...
-
基于51单片机的CAN通讯协议C语言程序
//-----------------------函数声明,变量定义-------------------------------------------------------- #includ ...
-
Flex与51单片机socket通信 策略问题
直接把<cross-domain-policy> <allow-access-from domain="*" to-ports="*"/> ...
-
基于jdk1.8的HashMap源码学习笔记
作为一种最为常用的容器,同时也是效率比较高的容器,HashMap当之无愧.所以自己这次jdk源码学习,就从HashMap开始吧,当然水平有限,有不正确的地方,欢迎指正,促进共同学习进步,就是喜欢程序员 ...
-
线程之间的通信socketpair【学习笔记】【原创】
平台信息:内核:linux3.1.0系统:android5.0平台:tiny4412 作者:庄泽彬(欢迎转载,请注明作者) 说明: 韦老师的安卓视频学习笔记 一.在一个进程中多个线程如何进行通信,主要 ...
-
基于【 MySql 】二 || mysql详细学习笔记
mysql重点学习笔记 /* Windows服务 */ -- 启动MySQL net start mysql -- 创建Windows服务 sc create mysql binPath= mysql ...
随机推荐
-
【原创】如何在Android Studio下调试原生安卓Framework层面的源代码
1. Open Existing Android Studio Project. 2. 打开后, Projects -> Android 里面是空的. 这时候,需要选到 Projects-> ...
-
android通过pc脚本执行sqlite3脚本
最近在调研市面上的一些android db框架,需要经常重复的输入一堆比如 adb shell cd /data/data/com.example.testandroiddb/databases sq ...
-
*[topcoder]LittleElephantAndIntervalsDiv1
http://community.topcoder.com/stat?c=problem_statement&pm=12822&rd=15707 第一次用C++提交,艰辛.首先想到可以 ...
-
7、第七节课,js逻辑运算
1.条件语句 function MyClick() { ; ; ; if (iNum1==iNum2) { iNum2=iNum3; } alert(iNum2); } 2. iNum3=iNum1& ...
-
javascript模式——Mixin
Mixin是一种扩展收集功能的方式,能提高代码的复用率. 在javascript中,原型可以继承于其它对象的原型,并且可以为任意数量的实例定义属性.可以利用这一点来促进函数的复用. 下面一段代码就是将 ...
-
CentOS时钟同步服务器
①本地时钟服务器需要安装chrony服务,可以通过yum.rpm.源码包安装,chrony支持C/S模式 ②编辑本地时钟服务,使其指向提供标准时间服务器,例如:中国国家授时中心NTP服务器. 修改配置 ...
-
动画:UIViewAnimationOptions类型
动画 1.常规动画属性设置(可以同时选择多个进行设置) UIViewAnimationOptionLayoutSubviews:动画过程中保证子视图跟随运动.**提交动画的时候布局子控件,表示子控件将 ...
-
Codeforces 1130D1 Toy Train (Simplified) (思维)【贪心】
<题目链接> 题目大意: 有一个的环形火车站,其中有$[1,n] n$个站台,站台上能够放糖果,火车只能朝一个方向移动,如果火车在站台$i$,那么下一秒就会在$i+1$站(如果$i=n$, ...
-
关于linux系统如何实现fork的研究(一)
引言 fork函数是用于在linux系统中创建进程所使用,而最近看了看一个fork()调用是怎么从应用到glibc,最后到内核中实现的,这片文章就聊聊最近对这方面研究的收获吧.我们主要聊聊从g ...
-
Unity查找子物体的方式-怎么查找GameObject
Unity动态查找物体 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享.心创 ...