A/D转换

选用芯片AT89S52
函数功能:如下代码

/*******************************************************************
此函数功能为:PCF8591芯片的使用,A/D转换,四路通道。通道一为可调电阻,
通道二为热敏电阻,通道三为光敏电阻,通道四接地。分别转换出它们的对应
电压,显示在液晶LCD1602上。
作者:Crazy Wind
日期:2020.11.2
version:1.0.0
********************************************************************/
#include"reg52.h"
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit SCL=P3^4;     //模拟时钟口
sbit SDA=P3^5;      //模拟数据口
bit askflag;
#define disdata  P0   //显示数据码输出口
sbit LCD_RS=P2^0;    //寄存器选择位RS为P2.0
sbit LCD_RW=P2^1;    //读写选择位RW为P2.1
sbit LCD_E=P2^2;     //使能信号位E为P2.2
uint data dis[4]={0x00,0x00,0x00,0x00};    //定义3个显示数据单元和1个数据存储单元
uchar code dis4[] = {"1- .  V  2- .  V"};
uchar code dis5[] = {"3- .  V  4- .  V"};
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();_nop_();};  //延时5个机器周期
bit bdata SystemError;      //从机错误标志位/*********************** PCF8591专用变量定义 ***********************/#define PCF8591_WRITE   0x90
#define PCF8591_READ    0x91
#define  NUM  4                 //接收和发送缓存区的深度
uchar idata receivebuf[NUM];    //数据接收缓冲区/*****************************************************
函数功能:ms延时
******************************************************/
void delayms(uint ms)       //毫秒延时
{uint i,j;for(i=0;i<ms;i++){for(j=115;j>0;j--);}
}/*****************************************************
函数功能:判断液晶模块的忙碌状态
返回值:busy。busy=1,忙碌;busy=0,不忙
******************************************************/
bit BusyTest(void)
{bit busy;LCD_RS=0;    //RS为低电平,RW为高电平时,可以读状态LCD_RW=1;LCD_E=1;     //E=1,才允许读写_nop_();    //空操作四个机器周期,给硬件反应时间_nop_();_nop_();_nop_();busy=(bit)(P0&0x80);    //将忙碌标志电平赋给busy(通过按位“与”运算将最高位赋给busy)LCD_E=0;return busy;   //将忙碌标志电平赋给busy
}/*****************************************************
函数功能:将模式设置指令或显示地址写入液晶模块
入口参数:z
******************************************************/
void Write_zl(uchar z)
{while(BusyTest()==1);   //如果忙就等待LCD_RS=0;    //RS和RW同时为低电平时,可以写入指令LCD_RW=0;LCD_E=0;     //使能信号E置低电平(写指令前先赋低电平0)_nop_();_nop_();    //空操作两个机器周期,给硬件反应时间P0=z;   //将数据送入P0口(数据总线line),即写入指令或地址_nop_();_nop_();_nop_();_nop_();    //空操作四个机器周期,给硬件反应时间LCD_E=1;    //使能信号E上升沿(0到1)时读取信息_nop_();_nop_();_nop_();_nop_();    //空操作四个机器周期,给硬件反应时间 LCD_E=0;    //使能信号E下降沿(1到0)时执行指令
}/*****************************************************
函数功能:指定字符显示的实际地址
入口参数:x
******************************************************/
void WriteAddress(uchar x)
{Write_zl(x|0x80);   //显示位置的确定方法规定为"地址码x+80H"
}/*****************************************************
函数功能:将数据(字符的标准ASCII码)写入液晶模块
入口参数:y(为字符常量)
******************************************************/
void WriteData(uchar y)
{while(BusyTest()==1);   //如果忙就等待LCD_RS=1;   //RS为高电平,RW为低电平时,可以写入数据LCD_RW=0;LCD_E=0;    //使能信号E置低电平(写数据前先赋低电平0)_nop_();_nop_();    //空操作两个机器周期,给硬件反应时间P0=y;   //将数据送入P0口(数据总线line),即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_();    //空操作四个机器周期,给硬件反应时间LCD_E=1;    //使能信号E上升沿(0到1)时读取信息_nop_();_nop_();_nop_();_nop_();    //空操作四个机器周期,给硬件反应时间LCD_E=0;    //使能信号E下降沿(1到0)时执行指令
}/*****************************************************
函数功能:对LCD的显示模式进行初始化设置
******************************************************/
void LcdInit(void)
{delayms(15);    //延时15ms,首次写指令时应给LCD一段较长的反应时间Write_zl(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口delayms(5); //延时5ms Write_zl(0x38);delayms(5);Write_zl(0x38); //3次写 设置模式delayms(5);Write_zl(0x0c); //显示模式设置:显示开,无光标,光标不闪烁delayms(5);Write_zl(0x06); //显示模式设置:光标右移,字符不移delayms(5);                                           Write_zl(0x01); //清屏幕指令,将以前的显示内容清除delayms(5);
}/*****************************************************
函数功能:将采集到的数据进行16进制转ASCLL码
******************************************************/
void Transform(uchar dat)
{dis[2]=dat/51;   //AD值转换为3位BCD码(256/5),最大为5.00V。dis[2]=dis[2]+0x30;   //转换为ACSII码dis[3]=dat%51;   //余数暂存dis[3]=dis[3]*10;    //计算小数第一位dis[1]=dis[3]/51;dis[1]=dis[1]+0x30;   //转换为ACSII码dis[3]=dis[3]%51;dis[3]=dis[3]*10;    //计算小数第二位dis[0]=dis[3]/51;                                                                             //dis[0]=dis[0]+0x30;  //转换为ACSII码
} /*****************************************************
函数功能:启动I2C总线
******************************************************/
void iic_start(void)
{SDA=1;     SCL=1;  //时钟保持高,数据线从高到低一次跳变,I2C通信开始delayNOP();      // 延时5us SDA=0;delayNOP();SCL=0;
}/*****************************************************
函数功能:停止I2C总线数据传送
******************************************************/
void iic_stop(void)
{   SDA=0;  //时钟保持高,数据线从低到高一次跳变,I2C通信停止SCL=1;delayNOP();SDA=1;delayNOP();SCL=0;
}/*****************************************************
函数功能:初始化I2C总线
******************************************************/
void iicInit(void)
{SCL=0;iic_stop();
}/*****************************************************
函数功能:从机发送应答位
******************************************************/
void slave_ACK(void)
{SDA=0;  SCL=1;delayNOP();    SCL=0;
}/*****************************************************
函数功能:从机发送非应答位,迫使数据传输过程结束
******************************************************/
void slave_NOACK(void)
{ SDA=1;SCL=1;delayNOP();SDA=0;SCL=0;
}/*****************************************************
函数功能:主机应答位检查,迫使数据传输过程结束
******************************************************/
void check_ACK(void)
{       SDA=1;        //将p1.1设置成输入,必须先向端口写1SCL=1;askflag=0;delayNOP();   if(SDA==1)    //若SDA=1表明非应答,置位非应答标志askflagaskflag=1;SCL=0;
}/*****************************************************
函数功能:发送一个字节
入口参数:ch
******************************************************/
void IICSendByte(uchar ch)
{unsigned char idata n=8;  //向SDA上发送一位数据字节,共八位while(n--){ if((ch&0x80)==0x80)   //若要发送的数据最高位为1则发送位1{SDA=1;       //传送位1SCL=1;delayNOP();//  SDA=0; SCL=0; }else{  SDA=0;    //否则传送位0SCL=1;delayNOP();SCL=0;}ch=ch<<1;    //数据左移一位}
}/*****************************************************
函数功能:接收一个字节
******************************************************/
uchar IICreceiveByte(void)
{uchar idata n=8;     //从SDA线上读取一位数据字节,共八位uchar tdata=0;while(n--){SDA=1;SCL=1;tdata=tdata<<1;          //左移一位if(SDA==1)tdata=tdata|0x01;   //若接收到的位为1,则数据的最后一位置1(按位”或“)else tdata=tdata&0xfe;   //否则数据的最后一位置0(按位“与”)SCL=0;}return(tdata);
}/*****************************************************
函数功能:发送n位数据子程序
入口参数:slave_add从机地址,n要发送的数据个数
******************************************************/
void DAC_PCF8591(uchar controlbyte,uchar w_data)
{iic_start();   //启动I2CdelayNOP();IICSendByte(PCF8591_WRITE);     // 发送地址位check_ACK();if(askflag==1){SystemError=1;return;       //若非应答,置错误标志位}IICSendByte(controlbyte&0x77); //Control byte check_ACK();                    //检查应答位if(askflag==1){ SystemError=1;return;                    // 若非应答,置错误标志位}IICSendByte(w_data);           //data bytecheck_ACK();                   // 检查应答位if(askflag==1){ SystemError=1;return;   // 若非应答表明器件错误或已坏,置错误标志位SystemError}iic_stop();         // 全部发完则停止delayNOP();delayNOP();delayNOP();delayNOP();
}/*****************************************************
函数功能:连续读入4路通道的A/D转换结果到receivebuf
入口参数:controlbyte控制字
******************************************************/
void ADC_PCF8591(uchar controlbyte)
{ uchar idata receive_da,i=0;iic_start();IICSendByte(PCF8591_WRITE);   //控制字check_ACK();if(askflag==1){SystemError=1;return;}IICSendByte(controlbyte);  //控制字check_ACK();if(askflag==1){SystemError=1;return;}iic_start();                //重新发送开始命令IICSendByte(PCF8591_READ);   //控制字check_ACK();if(askflag==1){SystemError=1;return;}IICreceiveByte();   //空读一次,调整读顺序slave_ACK();        //收到一个字节后发送一个应答位while(i<4){  receive_da=IICreceiveByte();receivebuf[i++]=receive_da;slave_ACK();       //收到一个字节后发送一个应答位}slave_NOACK();       //收到最后一个字节后发送一个非应答位iic_stop();
}/*****************************************************
函数功能:主程序
******************************************************/
main()
{uchar i,l;delayms(10);LcdInit();       //初始化LCDWriteAddress(0);    //设置显示位置为第一行的第1个字符i=0;while(dis4[i]!='\0'){WriteData(dis4[i]);i++;    }WriteAddress(0x40);    //设置显示位置为第二行的第1个字符i=0;while(dis5[i]!='\0'){WriteData(dis5[i]);i++;    }while(1){iicInit();        //初始化I2C总线ADC_PCF8591(0x04);if(SystemError==1)      //有错误,重新来{iicInit();                 //I2C总线初始化ADC_PCF8591(0x04);}for(l=0;l<4;l++)   {Transform(receivebuf[0]); //显示通道0       WriteAddress(0x02);             WriteData(dis[2]);        //整数位显示WriteAddress(0x04);             WriteData(dis[1]);        //第一位小数显示 WriteAddress(0x05);             WriteData(dis[0]);        //第二位小数显示Transform(receivebuf[1]); //显示通道1   WriteAddress(0x0b);             WriteData(dis[2]);        //整数位显示WriteAddress(0x0d);             WriteData(dis[1]);        //第一位小数显示 WriteAddress(0x0e);             WriteData(dis[0]);        //第二位小数显示Transform(receivebuf[2]); //显示通道2           WriteAddress(0x42);             WriteData(dis[2]);        //整数位显示WriteAddress(0x44);             WriteData(dis[1]);        //第一位小数显示 WriteAddress(0x45);             WriteData(dis[0]);        //第二位小数显示Transform(receivebuf[3]); //显示通道3   WriteAddress(0x4b);             WriteData(dis[2]);        //整数位显示WriteAddress(0x4d);              WriteData(dis[1]);        //第一位小数显示 WriteAddress(0x4e);             WriteData(dis[0]);        //第二位小数显示iicInit();                  //I2C总线初始化  DAC_PCF8591(0x40,receivebuf[0]); //D/A输出if(SystemError == 1)      //有错误,重新来{iicInit();                 //I2C总线初始化DAC_PCF8591(0x40,receivebuf[0]); //D/A输出}           }}
}

基于51单片机的AD转换相关推荐

  1. 基于51单片机的AD转换设计

    一.设计目的 掌握AD转换芯片的基本工作原理: 掌握一个完整的C语言程序结构: 熟悉AD转换与单片机的使用的编程. 二.设计环境 Keil开发环境 Proteus软件. 三.设计及调试 (1) 设计内 ...

  2. 十四、51单片机之AD转换

    1.AD相关简介 1.1.什么是AD转换? (1)A是指analog.模拟的:D是指digital.数字的. (2)现实世界是模拟的,连续分布的,无法被分成有限份:计算机世界是数字的,离散分布的,是可 ...

  3. 基于51单片机PT100热电偶AD转换protues仿真设计

    基于51单片机PT100热电偶AD转换protues仿真设计 (源码+仿真) 仿真原版本:proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0023 这里写 ...

  4. 基于单片机超声波视力保护系统设计-基于51单片机8音键电子琴仿真设计-基于8086八路模拟信号采集均值显示系统设计-基于8086八路数据电压温度采集系统-基于8086波形发生器仿真设计【毕设课设分享】

    539基于单片机超声波视力保护系统设计-设计资料 硬件构成:单片机+最小系统+LCD1602液晶显示模块+超声波模块+DS18B20温度采集模块+光线检测模块+ADC0832模块+蜂鸣器模块+LED指 ...

  5. 基于51单片机自动数字电压表PCF8591 TLC2543 TL548 proteus仿真汇编程序设计

    硬件设计1 基于51单片机+PCF8591 ADC的仿真电路图: A. 基于51单片机和PCF8591的电压表,具有仿真图/源程序: B. 由数码管作为显示器: C.测试电压范围为0~5V,精度约为0 ...

  6. 基于51单片机的压力监测仪(MPX4115)(Proteus仿真+程序)

    编号:28 基于51单片机的压力监测仪(MPX4115) 功能描述: 本设计由51单片机最小系统+MPX4115压力传感器+ADC0832模块+液晶1602模块 1.主控制器是AT89C82单片机 2 ...

  7. 基于51单片机的酒精浓度检测仪设计

    本设计仅供参考 基于51单片机的酒精浓度检测仪设计(proteus仿真+程序+原理图+报告) 原理图:Altium Designer 仿真:proteus 8.9 程序编译器:keil 4/keil ...

  8. 基于51单片机的废气检测I2Cproteus仿真

    目录 文章目录 前言 二.设计步骤 1.proteus设计 2.keil5代码编程设计 总结 前言 前段时间高中同学让我帮忙给她做一个数电课设,反正也没事做就随便做了做,现在总结一下,话不多说直接上效 ...

  9. 基于51单片机的光照强度检测c语言程序,基于51单片机光照强度检测报告.doc

    基于51单片机光照强度检测报告 课程设计报告 课程名称: 智能仪器课程设计 题 目: 基于51单片机的光照强度 摘要 光敏电阻测光强度系统,该系统可以自动检测光照强度的强弱并显示让人们知道此时光照强度 ...

最新文章

  1. 混合深度卷积,更少参数下的轻量级网络
  2. SQL SERVER数据页checksum校验算法
  3. bzoj1066 蜥蜴 (dinic)
  4. JavaEE基础(十四) /正则
  5. Spring 的 BeanFactory 和 FactoryBean 傻傻分不清?
  6. linux shell获取字符串第1个字符
  7. c# Invoke和BeginInvoke 区别
  8. 坐标或测量值超出范围
  9. PAT乙级(1009 说反话)
  10. 一分钟了解contextlib模块
  11. GridView, DataGrid 中,DataFormatString语法汇总
  12. 【资源分享】一款bootstrap开发的后台管理系统前端模板
  13. 事后诸葛亮(追光的人)
  14. 取消挂载是提示:device is busy
  15. MySQL配置参数大全
  16. 【限时删除】一个惊艳的神器,可全网爬取各种资源..........
  17. how to upload directory to github(怎么把文件目录上传到github)
  18. Java中使用redis的完整实例及常用命令
  19. 判别模型:logistic,GDA,QDA(一)
  20. CUDA安装失败-Nsight compute安装失败-如何测试CUDA是否安装成功?Reason: VS** was not found

热门文章

  1. 关于nohup重定向日志按日期区分文件(未解决)
  2. 股妖APP也妖 -- 与暴风魔镜相关
  3. 22春天津大学《国际经济法学》在线作业二
  4. 性能优化:一个 Flink 参数节省了 50% 的 CPU 消耗
  5. 高效阅读嵌入式源码系列一:静态分析神器understand软件基本操作
  6. 解码者:数学探秘之旅——读书笔记(一)
  7. 个人博客,Springboot + Vue搭建属于自己的博客
  8. 大数据征信与个人隐私保护
  9. postgresql使用入门教程
  10. 亲测有效解决“你已购买过此项目,现在可以免费下载,不再另外收费”提示