制作数字电压表(2学时)
一、实验目的:
1. 了解I2C串行总线工作原理及通信协议
2. 了解ADC0804、DAC0832、PCF8591与AT89S51的接口设计
3. 掌握ADC0804、DAC0832、PCF8591的编程方法
4. 能够熟练运用数模转换模块
二、实验要求:
1. 数字电压表:在AT89C52系统中采用PCF8591芯片,测量0-5V范围内的直流电压,并在2位数码管上显示电压值。
三、实验设备:(PROTEUS元件表)
四、实验报告:
1.描述实验过程(重要步骤用屏幕截图表示)。
2.给出在PROTEUS中设计的单片机系统电路图
3.画出程序流程图
4.给出在KEIL中编写的源程序。
5.描述在proteus中仿真运行程序的实验现象
五、实验总结
单片机源程序如下:
/**********************BST-M51实验开发板例程************************
* 平台:BST-M51 + Keil U4 + STC89C52
* 名称:AD串口读取实验
* 公司:深圳市亚博软件开发有限公司
* 日期:2015-6
* 晶振:11.0592MHZ
******************************************************************/
#include #include #define AddWr 0x90 //PCF8591 地址 // 变量定义 unsigned char AD_CHANNEL=0; unsigned char D[32]; unsigned char code table[10]={0xC0,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //共阳极数码管0~9显示的数值表 unsigned int data dis[3]={0x00,0x00,0x00}; //用以计算存储输出电压的3元素数组 sbit scl=P2^0; //I2C 时钟 sbit sda=P2^1; //I2C 数据 bit ack; /*应答标志位*/ sbit C1=P2^6;//数码管位选 sbit C2=P2^7;//数码管位选 sbit Dp=P2^5;//小数点 unsigned char date; /******************************************************************* 起动总线函数 函数原型: void Start_I2c(); 功能: 启动I2C总线,即发送I2C起始条件. ********************************************************************/ void Start_I2c() { sda=1; /*发送起始条件的数据信号*/ _nop_(); scl=1; _nop_(); /*起始条件建立时间大于4.7us,延时*/ _nop_(); _nop_(); _nop_(); _nop_(); sda=0; /*发送起始信号*/ _nop_(); /* 起始条件锁定时间大于4μs*/ _nop_(); _nop_(); _nop_(); _nop_(); scl=0; /*钳住I2C总线,准备发送或接收数据 */ _nop_(); _nop_(); } /******************************************************************* 结束总线函数 函数原型: void Stop_I2c(); 功能: 结束I2C总线,即发送I2C结束条件. ********************************************************************/ void Stop_I2c() { sda=0; /*发送结束条件的数据信号*/ _nop_(); /*发送结束条件的时钟信号*/ scl=1; /*结束条件建立时间大于4μs*/ _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); sda=1; /*发送I2C总线结束信号*/ _nop_(); _nop_(); _nop_(); _nop_(); } /******************************************************************* 字节数据发送函数 函数原型: void I2C_SendByte(UCHAR c); 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0) 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 ********************************************************************/ void I2C_SendByte(unsigned char c) { unsigned char i; for(i=0;i<8;i++) /*要传送的数据长度为8位*/ { if((c< else sda=0; _nop_(); scl=1; /*置时钟线为高,通知被控器开始接收数据位*/ _nop_(); _nop_(); /*保证时钟高电平周期大于4μs*/ _nop_(); _nop_(); _nop_(); scl=0; } _nop_(); _nop_(); sda=1; /*8位发送完后释放数据线,准备接收应答位*/ _nop_(); _nop_(); scl=1; _nop_(); _nop_(); _nop_(); if(sda==1)ack=0; else ack=1; /*判断是否接收到应答信号*/ scl=0; _nop_(); _nop_(); } /******************************************************************* 字节数据接收函数 函数原型: UCHAR I2C_RcvByte(); 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 发完后请用应答函数应答从机。 ********************************************************************/ unsigned char I2C_RcvByte() { unsigned char retc=0,i; sda=1; /*置数据线为输入方式*/ for(i=0;i<8;i++) { _nop_(); scl=0; /*置时钟线为低,准备接收数据位*/ _nop_(); _nop_(); /*时钟低电平周期大于4.7μs*/ _nop_(); _nop_(); _nop_(); scl=1; /*置时钟线为高使数据线上数据有效*/ _nop_(); _nop_(); retc=retc<<1; if(sda==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */ _nop_(); _nop_(); } scl=0; _nop_(); _nop_(); return(retc); } /******************************************************************** 应答子函数 函数原型: void Ack_I2c(bit a); 功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定) ********************************************************************/ void Ack_I2c(bit a) { if(a==0)sda=0; /*在此发出应答或非应答信号 */ else sda=1; /*0为发出应答,1为非应答信号 */ _nop_(); _nop_(); _nop_(); scl=1; _nop_(); _nop_(); /*时钟低电平周期大于4μs*/ _nop_(); _nop_(); _nop_(); scl=0; /*清时钟线,住I2C总线以便继续接收*/ _nop_(); _nop_(); } /************************************************************ * 函数名 : Pcf8591_DaConversion * 函数功能 : PCF8591的输出端输出模拟量 * 输入 : addr(器件地址),channel(转换通道),value(转换的数值) * 输出 : 无 ******************* *****************************************/ bit Pcf8591_DaConversion(unsigned char addr,unsigned char channel, unsigned char Val) { Start_I2c(); //启动总线 I2C_SendByte(addr); //发送器件地址 if(ack==0)return(0); I2C_SendByte(0x40|channel); //发送控制字节 if(ack==0)return(0); I2C_SendByte(Val); //发送DAC的数值 if(ack==0)return(0); Stop_I2c(); //结束总线 return(1); } /************************************************************ * 函数名 : Pcf8591_SendByte * 函数功能 : 写入一个控制命令 * 输入 : addr(器件地址),channel(转换通道) * 输出 : 无 ************************************************************/ bit PCF8591_SendByte(unsigned char addr,unsigned char channel) { Start_I2c(); //启动总线 I2C_SendByte(addr); //发送器件地址 if(ack==0)return(0); I2C_SendByte(0x40|channel); //发送控制字节 if(ack==0)return(0); Stop_I2c(); //结束总线 return(1); } /************************************************************ * 函数名 : PCF8591_RcvByte * 函数功能 : 读取一个转换值 * 输入 : * 输出 : dat ************************************************************/ unsigned char PCF8591_RcvByte(unsigned char addr) { unsigned char dat; Start_I2c(); //启动总线 I2C_SendByte(addr+1); //发送器件地址 if(ack==0)return(0); dat=I2C_RcvByte(); //读取数据0 Ack_I2c(1); //发送非应答信号 Stop_I2c(); //结束总线 return(dat); } /*------------------------------------------------
上一篇:51单片机简易电子称程序
下一篇:基于AT89S52单片机的电子密码锁
推荐阅读最新更新时间:2024-11-10 18:13
设计资源 培训 开发板 精华推荐
- TI 汽车应用在线展厅与你零距离接触,答题赢礼
- 有奖直播:使用 NI CompactDAQ 和 LabVIEW构建基于传感器的测试系统
- “玄铁杯”第三届RISC-V应用创新大赛—国产高性能RISC-V Linux开发板LicheePi 4A报名专场,万元奖金,邀您奔赴开源设计盛宴
- EE牵手TI上传有礼、积分双倍
- ublox无线开发板EVK-NINA-B400免费申请
- 有奖直播报名|罗姆EcoGaN™与LSI 技术
- 注册有礼|看安富利人工智能云会展,赢京东卡啦!
- 有奖报名 | 安富利邀您参与2022国际工业博览会!(11月30日-12月4日,上海)
- 阅1SP0350V SCALE-2单通道即插即用型门极驱动器,参与PI答题享好礼!