资料:
pcf8591_jj[1].pdf
仿真:
照片:(相机像素问题,看不太清)
公开代码:
***********************LCD.h*******************************
#ifndef LCD_CHAR_1602_
#define LCD_CHAR_1602_
#include <intrins.h>
//Port Definitions**********************************************************
sbit LcdRs = P2^4;
sbit LcdRw = P2^5;
sbit LcdEn = P2^6;
sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
//内部等待函数**************************************************************************
unsigned char LCD_Wait(void)
{
LcdRs=0;
LcdRw=1; _nop_();
LcdEn=1; _nop_();
//while(DBPort&0x80);//在用Proteus仿真时,注意用屏蔽此语句,在调用GotoXY()时,会进入死循环,
//可能在写该控制字时,该模块没有返回写入完备命令,即DBPort&0x80==0x80
//实际硬件时打开此语句
LcdEn=0;
return DBPort;
}
//向LCD写入命令或数据************************************************************
#define LCD_COMMAND 0 // Command
#define LCD_DATA 1 // Data
#define LCD_CLEAR_SCREEN 0x01 // 清屏
#define LCD_HOMING 0x02 // 光标返回原点
void LCD_Write(bit style, unsigned char input)
{
LcdEn=0;
LcdRs=style;
LcdRw=0; _nop_();
DBPort=input; _nop_();//注意顺序
LcdEn=1; _nop_();//注意顺序
LcdEn=0; _nop_();
LCD_Wait();
}
//设置显示模式************************************************************
#define LCD_SHOW 0x04 //显示开
#define LCD_HIDE 0x00 //显示关
#define LCD_CURSOR 0x02 //显示光标
#define LCD_NO_CURSOR 0x00 //无光标
#define LCD_FLASH 0x01 //光标闪动
#define LCD_NO_FLASH 0x00 //光标不闪动
void LCD_SetDisplay(unsigned char DisplayMode)
{
LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
}
//设置输入模式************************************************************
#define LCD_AC_UP 0x02
#define LCD_AC_DOWN 0x00 // default
#define LCD_MOVE 0x01 // 画面可平移
#define LCD_NO_MOVE 0x00 //default
void LCD_SetInput(unsigned char InputMode)
{
LCD_Write(LCD_COMMAND, 0x04|InputMode);
}
//移动光标或屏幕************************************************************
/*
#define LCD_CURSOR 0x02
#define LCD_SCREEN 0x08
#define LCD_LEFT 0x00
#define LCD_RIGHT 0x04
void LCD_Move(unsigned char object, unsigned char direction)
{
if(object==LCD_CURSOR)
LCD_Write(LCD_COMMAND,0x10|direction);
if(object==LCD_SCREEN)
LCD_Write(LCD_COMMAND,0x18|direction);
}
*/
//初始化LCD************************************************************
void LCD_Initial()
{
LcdEn=0;
LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动
}
//************************************************************************
void GotoXY(unsigned char x, unsigned char y)
{
if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}
void Print(unsigned char x, unsigned char y,unsigned char *str)
{
GotoXY(x,y);
while(*str!='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
/*
void LCD_LoadChar(unsigned char user[8], unsigned char place)
{
unsigned char i;
LCD_Write(LCD_COMMAND,0x40|(place*8));
for(i=0; i<8; i++)
LCD_Write(LCD_DATA,user[i]);
}
*/
//************************************************************************
#endif
--------------------------------------PCF8591.h----------------------------------------
#ifndef _PCF8591_h_
#define _PCF8591_h_
#include<reg52.h>
#include<intrins.h>
#define channal0 0x00
#define channal1 0x01
#define channal2 0x02
#define channal3 0x03
sbit SCL=P1^1;
sbit SDA=P1^2;
#define SCL_0 SCL=0
#define SCL_1 SCL=1
#define SDA_0 SDA=0
#define SDA_1 SDA=1
void delay(void); //大约4.7us的延时
void i_start(void);//iic起始信号
void i_stop(void); //iic终止信号
bit i_clock(void);//主器件没写完一个字节8位以后,在第九个时钟周期,读取SDA数据线的信息,看是否被从器件拉低,来判断数据总线的状态
void ack(); //主器件发给从器件的应答信号,表明仍然需要从器件发送数据
void nack();//主器件发送的非应答信号,表明接收完了,不需要从器件再发了
bit i_send(unsigned char i_data);//写一个字节
unsigned char i_receive(void);//读一个字节
void PCF8591write(unsigned char dat); //PCF8591写函数,参数为需要D/A转换的数据
unsigned char PCF8591read(unsigned char channal);//PCF8591读函数 无参数
#endif
while(1)
{
vol=(float)PCF8591read(channal0)/255*5*10;
voltage[0]=(unsigned char)vol/10+0x30;
voltage[1]='.';
voltage[2]=(unsigned char)vol%10+0x30;
Print(0,0,"RG1:");
Print(4,0,voltage);
vol=(float)PCF8591read(channal1)/255*5*10;
voltage[0]=(unsigned char)vol/10+0x30;
voltage[1]='.';
voltage[2]=(unsigned char)vol%10+0x30;
Print(8,0,"NTC:");
Print(12,0,voltage);
vol=(float)PCF8591read(channal2)/255*5*10;
voltage[0]=(unsigned char)vol/10+0x30;
voltage[1]='.';
voltage[2]=(unsigned char)vol%10+0x30;
Print(0,1,"CH2:");
Print(4,1,voltage);
vol=(float)PCF8591read(channal3)/255*5*10;
voltage[0]=(unsigned char)vol/10+0x30;
voltage[1]='.';
voltage[2]=(unsigned char)vol%10+0x30;
Print(8,1,"CH3:");
Print(12,1,voltage);
//delay1(10000);
//PCF8591write(255);
}
return 0;
}
#include<PCF8591.h>
void delay(void)
{ //延时5个时钟周期
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void i_start(void)
{ //iic起始信号
SDA_1;
delay();
SCL_1; //iic时钟线置高电平
delay(); //需要这么长时间吗
SDA_0; //iic数据线置低电平
delay();
SCL_0; //iic数据线置低电平
delay();
}
void i_stop(void) //iic终止信号
{
SDA_0; //iic数据线置低电平
delay();
SCL_1; //iic时钟线置高电平
delay();
SDA_1; //iic数据线置高电平
delay();
SCL_0; //iic时钟线置低电平
delay();
}
bit i_clock(void)
{ //保持一个时钟周期,保证一位数据的有效传输,并且从数据线获取1bit信息并返回该bit信息
bit sample;
SCL_1; //iic时钟线置高电平,不允许数据线状态变化
delay();
sample=SDA;
_nop_(); //延时一个周期
_nop_(); //延时一个周期
SCL_0; //iic时钟线置低电平
delay();
return(sample); //返回从数据线读到的一bit信息
}
void ack()
{ //发送应答位
SCL_0; //iic时钟线置低电平
SDA_0; //iic数据线置低电平
delay(); //延时
SCL_1; //iic时钟线置高电平
delay();
SCL_0; //iic时钟线置低电平
delay();
SDA_1; //iic时数据置高电平
}
void nack()
{ //发送非应答位
SCL_0; //iic时钟线置低电平
SDA_1; //iic数据线置高电平
delay();
SCL_1; //iic时钟线置高电平
delay();
SCL_0; //iic时钟线置低电平
delay();
SDA_1; //iic数据线置高电平
}
bit i_send(unsigned char i_data)
{ //发送一byte数据,返回bit信息
unsigned char i;
for(i=8;i>0;i--)
{
SDA=(bit)(i_data & 0x80); //获取最高位
i_data=i_data<<1; //左移一位,用于依次获取下一位
i_clock(); //提供一个时钟脉冲
}
SDA_1; //iic数据线置高电平,用于接收应答位
return(~i_clock()); //返回接收的应答位
}
unsigned char i_receive(void)
{ //从iic接收一个字节数据,并返回该字节
unsigned char i_data=0; //i_data保存接收到的数据
unsigned char i;
for(i=8;i>0;i--)
{
i_data*=2; //每次将i_data右移1位,用来保存接收的1位信息
if(i_clock()) i_data++;
}
return(i_data); //返回接收的字节
}
void PCF8591write(unsigned char dat) //PCF8591写函数,参数为需要D/A转换的数据
{
i_start(); //发送开始
if(i_send(0x90)) //发送地址信息,然后判断接收的是应答位,还是非应答位
{
if(i_send(0x40)) //发送控制字
{
i_send(dat); //发送要转换的数据
i_stop(); //发送停止信号
delay();
}
}
}
unsigned char PCF8591read(unsigned char channal) //PCF8591读函数 无参数
{
unsigned char dat; //存放读取的数据
i_start(); //开始信号
if(i_send(0x90)) //发送地址信息,然后判断接收的是应答位,还是非应答位
{
if(i_send(channal)) //发送控制字。
{
i_start(); //从新发送开始信号
if(i_send(0x91)) //发送地址信息,然后判断接收的是应答位,还是非应答位
{
dat=i_receive(); //读取A/D转换后的结果,第一次读取的是寄存器中的初始值,所以还要再读一次
ack(); //发送应答信号
delay();
dat=i_receive(); //再次读取数据,读出的数据为上次转换的结果
nack(); //发送非应答位
i_stop(); //发送停止信号
return dat; //返回读出的数据
}
}
}
}
---------------------------main.c------------------------------------------------------------------
#include "reg52.h"
#include "lcd.h"
#include "pcf8591.h"
unsigned char voltage[5]={1,2,3};
void delay1(unsigned int tim)
{
while(tim--);
}
int main(void)
{ float vol;
LCD_Initial();