基于51单片机用PCF8591进行ADDA转换用1602LCD显示的电流采样.docx
《基于51单片机用PCF8591进行ADDA转换用1602LCD显示的电流采样.docx》由会员分享,可在线阅读,更多相关《基于51单片机用PCF8591进行ADDA转换用1602LCD显示的电流采样.docx(14页珍藏版)》请在冰豆网上搜索。
基于51单片机用PCF8591进行ADDA转换用1602LCD显示的电流采样
基于51单片机用PCF8591进行AD,DA转换用1602LCD显示
的电流采样
福州大学至诚学院本科生课程设计
题目:
可编程序控制器实训姓名:
学号:
系别:
专业:
年级:
指导教师:
1、PCF8591概
述.....................................................32、芯片介
绍.........................................................33、PCF8591
的A/D转换...............................................44、A/D转换程
序设计流程.............................................55、1602LCD主
要技术参数.............................................76、Proteus仿
真原理图10
7、程序代
码........................................................108、结
语............................................................179、参考
文献17
2
1、PCF8591概述
PCF8591是一种具有I2C总线接口的8位A/DD/A转换芯片,在与CPU的信息传输过程中仅靠时钟线SCL和数据线SDA就可以实现。
I2C总线是Philips(飞利浦)公司推出的串行总线,它与传统的通信方式相比具有读写方便,结构简单,可维护性好,易实现系统扩展,易实现模块化标准化设计,可靠性高等优点。
2、芯片介绍
2.1内部结构及引脚功能描述
PCF8591为单一电源供电(2.56V)典型值为5V,CMOS工艺PCF8591有4路8位A/D输入,属逐次比较型,内含采样保持电路;1路8位D/A输出,内含有DAC的数据寄存器A/DD/A的最大转换速率约为11kHz,但是转换的基准电源需由外部提供PCF8591的引脚功能如图1所示
图1PCF8591引脚功能
2.2片内可编程功能设置
在PCF8591内部的可编程功能控制字有两个,一个为地址选择字,另一个为转换控制字PCF8591采用典型的I2C总线接口的器件寻址方法,即总线地址由器
件地址引脚地址和方向位组成Philips(飞利浦)公司规定A/D器件高四位地址为1001,低三位地址为引脚地址A0A1A2,由硬件电路决定,地址选择字格式具体描述如表2所示因此I2C系统中最多可接23=8个具有总线接口的A/D器件地
作时为0总线。
操作时,由器件地址引脚地址和方向位组成的从
3
地址为主控器发送的第一字节。
图2地址选择字格式描述
D0:
读写控制位,对转换器件进行读操作时为1,进行写操作时为0。
D1,D2,D3:
引脚硬件地址设置位,由硬件电路设定该PCF8591的物理地址。
D7,D6,D5,D4:
器件地址位固定为1001.PCF8591的转换控制字存放在控制寄存器
中,用于实现器件的各种功能总线操作时为主控器发送的第二字节转换控制字的格式功能具体描述如图3所示
图3转换控制字格式描述
D0,D1:
通道选择位。
00:
通道0;01:
通道1;10:
通道2;11:
通道3。
D2:
自
动增量允许位,为1时,每对一个通道转换后自动切换到下一通道进行转换,为0
时不自动进行通道转换,可通过软件修改进行通道转换D3:
特征位,固定位0。
D4,D5:
模拟量输入方式选择位。
00:
输入方式0,四路单端输入;01:
输入方式1,三路差分输入;10:
输入方式2,二路单端输入,一路差分输入;11:
输入方式
3,两路差分输入。
D6:
模拟输出允许位,A/D转换时设置为(地址选择字D0位此时设置为1),D/A转换时设置为1(地址选择字位此时设置为)。
D7:
特征位,固定为0。
3、PCF8591的A/D转换
较器对PCF8591进行写读操作后便立即启动A/D转换,并读出A/D转换结果在每个应答信号的后沿触发转换周期,采样模拟电压并读出前一次转换后的结果。
A/D转换中,一旦A/D采样周期被触发,所选择通道的采样电压便保存在采
样,保持电路中,并转换成8位二进制码(单端输入)或二进制补码(差分输入)存放在ADC数据寄存器中等待器件读出。
如果控制字节中自动增量选择位置1,则一次A/D转换完毕后自动选择下一通道。
读周期中读出的第一个字节为前一个周期的转换结果。
上电复位后读出的第一字节为80H。
PCF8591的A/D转换亦使用的是I2C总线的读方式操作完成的。
其数据操作
格式如图4所示。
4
图4A/D转换数据操作格式
其中data0~datan为A/D的转换结果,分别对应于前一个数据读取期间所采样的模拟电压。
A/D转换结束后,先发送一个非应答信号位A再发送结束信号位P。
灰底位由主机发出,白底位是由PCF8591产生。
上电复位后控制字节状态为00H,在A/D转换时须设置控制字,即须在读操作之前进行控制字节的写入操
作。
逻辑操作波形时序图如图5所示。
图5A/D转换逻辑操作波形时序图
4、A/D转换程序设计流程如下图6所示
5
图6
6
5、1602LCD主要技术参数:
显示容量:
16×2个字符,芯片工作电压:
4.5—5.5V,工作电流:
2.0mA(5.0V),模块最佳工作电压:
5.0V,字符尺寸:
2.95×4.35(W×H)mm。
5.1引脚功能说明
图7
编号符号引脚说明编号符号引脚说明1VSS电源地9D2数据
2VDD电源正极10D3数据
3VL液晶显示偏压11D4数据
4RS数据/命令选择12D5数据
5R/W读/写选择13D6数据
6E使能信号14D7数据
7D0数据15BLA背光源正极8D1数据16BLK背光源负极
图7
引脚接口说明表
第1脚:
VSS为地电源。
第2脚:
VDD接5V正电源。
第3脚:
VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:
RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:
R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。
当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:
E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7,14脚:
D0,D7为8位双向数据线。
第15脚:
背光源正极。
第16脚:
背光源负极。
5.21602LCD的指令说明及时序
1602液晶模块内部的控制器共有11条控制指令,如图8
序号指令RSR/WD7D6D5D4D3D2D1D01清显示0000000001
2光标返回000000001*
7
4显示开/关控制0000001DCB
5光标或字符移位000001S/CR/L**6置功能00001DLNF**
置字符发生存贮器地字符发生存贮器地址
70001址
8置数据存贮器地址001显示数据存贮器地址
9读忙标志或地址01BF计数器地址写数到CGRAM或要写的数据内容
1010DDRAM)
11从CGRAM或DDRAM读数11读出的数据内容
图8
1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。
(说明:
1为高电平、0为低电平)指令1:
清显示,指令码01H,光标复位到地址00H位置。
指令2:
光标复位,光标返回到地址00H。
指令3:
光标和显示模式设置I/D:
光标移动方向,高电平右移,低电平左移S:
屏幕上所有文字是否左移或者右移。
高电平表示有效,低电平则无效。
指令4:
显示开关控制。
D:
控制整体显示的
C:
控制光标的开与关,高电平开与关,高电平表示开显示,低电平表示关显示表示有光标,低电平表示无光标B:
控制光标是否闪烁,高电平闪烁,低电平
不闪烁。
指令5:
光标或显示移位S/C:
高电平时移动显示的文字,低电平时移动
:
功能设置命令DL:
高电平时为4位总线,低电平时为8位总线N:
光标。
指令
6
高电平时显示5x10的点阵字符。
指令7:
字符发生器RAM地址设置。
指令8:
DDRAM
地址设置。
指令9:
读忙信号和光标地址BF:
为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
指令10:
写数据。
指令11:
读数据。
读操作时序
8
5.31602LCD的一般初始化(复位)过程延时15mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
写指令08H:
显示关闭写指令01H:
显示清屏9
写指令06H:
显示光标移动设置写指令0CH:
显示开及光标设置6、仿真原理图如下所示
7、C语言程序#include#include
#defineucharunsignedchar#defineuintunsignedint#defineDelay4us(){_nop_();_nop_();_nop_();_nop_();}sbitLCD_RS=P2^6;
sbitLCD_RW=P2^5;sbitLCD_EN=P2^7;
ucharRecv_Buffer[4];//数据接收缓冲uintVoltage[]={'0','0','0','0'};
//数据分解为电压x.xxbitbdataIIC_ERROR;//I2C错误标志位ucharLCD_Line_1[]={".V"};
10
//延时
voiddelay(intms)
{
uchari;
while(ms--)for(i=0;i<250;i++)Delay4us();
}
//LCD忙检测
bitLCD_Busy_Check()
{
bitResult;LCD_RS=0;LCD_RW=1;
LCD_EN=1;Delay4us();Result=(bit)(P0&0x80);LCD_EN=0;
returnResult;
}
//写指令
voidLCD_Write_Command(ucharcmd){while(LCD_Busy_Check());LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();
LCD_EN=1;Delay4us();LCD_EN=0;}
//写数据
voidLCD_Write_Data(uchardat){while(LCD_Busy_Check());LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;Delay4us();LCD_EN=1;Delay4us();LCD_EN=0;}
//初始化
voidLCD_Initialise()
{
LCD_Write_Command(0x38);delay(5);11
LCD_Write_Command(0x0c);delay(5);LCD_Write_Command(0x06);delay(5);LCD_Write_Command(0x01);delay(5);}
//设置显示位置
voidLCD_Set_Position(ucharpos){LCD_Write_Command(pos|0x80);}
//显示一行
voidLCD_Display_A_Line(ucharLine_Addr,uchars[])
{
uchari;
LCD_Set_Position(Line_Addr);for(i=0;i<16;i++)LCD_Write_Data(s[i]);}
//将模数转换后得到的值分解存入缓存voidConvert_To_Voltage(ucharval){
整数部分
Tmp=val%51*10;//第一位小数
Voltage[1]=Tmp/51+'0';Tmp=Tmp%51*10;Voltage[0]=Tmp/51+'0';
}
//启动I2C总线
voidIIC_Start()
{SDA=1;SCL=1;Delay4us();SDA=0;Delay4us();SCL=0;
}
//停止I2C总线
voidIIC_Stop()
{12
SDA=0;SCL=1;Delay4us();SDA=1;Delay4us();SCL=0;
}
//从机发送应答位
voidSlave_ACK()
{
SDA=0;SCL=1;Delay4us();SCL=0;SDA=1;}
//从机发送非应答位
voidSlave_NOACK()
SDA=1;SCL=1;Delay4us();SCL=0;SDA=0;}
//发送一字节
voidIIC_SendByte(ucharwd){uchari;
for(i=0;i<8;i++)//循环移入8位
{
SDA=(bit)(wd&0x80);_nop_();_nop_();SCL=1;Delay4us();SCL=0;wd<<=1;}Delay4us();
SDA=1;//释放总线并准备读取应答SCL=1;Delay4us();
IIC_ERROR=SDA;//IIC_ERROR=1表示无应答SCL=0;
Delay4us();
}
//接收一字节
ucharIIC_ReceiveByte()
{
uchari,rd=0x00;for(i=0;i<8;i++)13
{
SCL=1;rd<<=1;rd|=SDA;Delay4us();SCL=0;Delay4us();
}
SCL=0;Delay4us();
}
//连续读入4路通道的A/D转换结果并保存到Recv_BuffervoidADC_PCF8591(ucharCtrlByte){
uchari;
IIC_Start();
IIC_SendByte(0x90);//发送写地址if(IIC_ERROR==1)return;
//IIC_SendByte(CtrlByte);//发送控制字节//if(IIC_ERROR==1)return;
IIC_Start();//重新发送开始命令IIC_SendByte(0x91);//发送读地址
if(IIC_ERROR==1)return;
IIC_ReceiveByte();//空读一次,调整读顺序Slave_ACK();//收到一字节后发送一个应答位for(i=0;i<4;i++)
{
Recv_Buffer[i++]=IIC_ReceiveByte();Slave_ACK();//收到一个字节后发送一个应答位}
Slave_NOACK();
IIC_Stop();//收到一个字节后发送一个非应答位}
//向PCF8591发送1字节进行AD转换
//主程序
voidmain()
{
LCD_Initialise();while
(1)
14
ADC_PCF8591(0x04);
Convert_To_Voltage(Recv_Buffer[0]);LCD_Line_1[2]=Voltage[2];LCD_Line_1[4]=Voltage[1];
LCD_Line_1[5]=Voltage[0];LCD_Display_A_Line(0x00,LCD_Line_1);}
}
8、结语
在这次单片机课设中,通过自己动手查阅资料,不仅知道了芯片PCF8591和LCD1602工作原理、各引脚的功能等,还巩固了C语言程序的编写,对51单片机也有了更深的理解,丰富了很多课外知识,能熟练的运用Keil等软件。
H6800实验箱的调试,让我们在硬件上更好的了解单片机,增强了我们的动手实践能力。
9、参考文献
单片机原理及应用(c语言版)周国运
#includemain()
{
inta,b,i,j,max;
intc[3][3]={1,2,3,6,9,10,20,22,0};
max=c[0][0];a=b=0;for(i=0;i<3;i++)for(j=0;j<3;j++)if(c[i][j]>max)
{
a=i;b=j;
15
}
printf("最大值max=%d,行a=%d,列b=%d",max,a,b);printf("\n");
}
ViodConvert_To_Voltage2(ucharvalmax)
{
Ucharval[],temp;
Inti=0;
If(val[i]Valmax=val[i+1];ElseValmax=val[i];
Voltage[2]=valmax/51+'0';//整数部分Tmp=valmax%51*10;//第一位小数Voltage[1]=Tmp/51+'0';
Tmp=Tmp%51*10;Voltage[0]=Tmp/51+'0';
}16