资源描述
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define Delay4us() {_nop_();_nop_();_nop_();_nop_();}
//引脚定义
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
//延时子程序
void DelayMS(int ms) {
uchar t;
while(ms--) for(t=0;t<120;t++);
}
//LCD忙状态检测
bit LCD_Busy_Check() {
bit Result;
LCD_RS=0;LCD_RW=1;
LCD_EN=1; Delay4us(); Result=(bit)(P0 & 0x80);
LCD_EN=0;
return Result;
}
//写LCD命令
void LCD_Write_Command(uchar cmd) {
// while(LCD_Busy_Check());
DelayMS(5);
LCD_RS=0; LCD_RW=0;LCD_EN=0; _nop_();_nop_();
P0=cmd;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
//写LCD数据
void LCD_Write_Data(uchar dat) {
// while(LCD_Busy_Check()); //LCD是否忙?
DelayMS(5);
LCD_RS=1; LCD_RW=0; LCD_EN=0; P0=dat; Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
//LCD初始化
void LCD_Initialise()
{
LCD_Write_Command(0x38);DelayMS(5); //设置16*2行显示,5*7点阵,8位数据接口
LCD_Write_Command(0x0C);DelayMS(5); //开显示
LCD_Write_Command(0x06);DelayMS(5); //地址指针加1,光标加1,整屏显示不移动
LCD_Write_Command(0x01);DelayMS(5); //指针清零,显示清零
}
sbit SCL=P1^0;
sbit SDA=P1^1;
uchar Recv_Buffer[4]; //数据接收缓冲(每通道1字节)
uint Voltage[]={'0','0','0'}; //数据分解为电压x.xx
bit bdata IIC_ERROR; //设置I2C错误标志位
uchar LCD_Line_1[]={"1- . V 2- . V"};
uchar LCD_Line_2[]={"3- . V 4- . V"};
void LCD_Set_Position(uchar pos) { //设置LCD显示位置
LCD_Write_Command(pos|0x80);
}
void LCD_Display_A_Line(uchar Line_Addr,uchar s[]) { //显示一行
uchar i;
LCD_Set_Position(Line_Addr);
for(i=0;i<16;i++); LCD_Write_Data(s[i]);
}
//将模数转换后的值分解存入缓冲
void Convert_To_Voltage(uchar val) {
uchar tmp;
Voltage[2]=val/51+'0'; //最大值为255,对应5伏电压,分度为255/5=51,一位整数
tmp=val%51*10;
Voltage[1]=tmp/51+'0'; //第一位小数
tmp=tmp%51+'0';
Voltage[0]=tmp/51+'0'; //第二位小数
}
//启动I2C总线
void IIC_Start() {
SDA=1; SCL=1; Delay4us(); SDA=0; Delay4us(); SCL=0;
}
//停止I2C总线
void IIC_Stop() {
SDA=0; SCL=1; Delay4us(); SDA=1; Delay4us(); SCL=0;
}
//从机发送应答
void Slave_Ark() {
SDA=0; SCL=1; Delay4us(); SCL=0; SDA=1;
}
//从机发送非应答
void Slave_NOArk() {
SDA=1; SCL=1; Delay4us(); SCL=0; SDA=0;
}
//发送一个字节
void IIC_SendByte(uchar wd) {
uchar i;
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; SCL=0; Delay4us();
}
//接收一个字节
uchar IIC_ReceiveByte() {
uchar i, rd=0x00;
for(i=0;i<8;i++) { //循环移入8位
SCL=1; rd<<1; rd |= SDA; Delay4us(); SCL=0; Delay4us();
}
SCL=0; Delay4us();
return rd;
}
void ADC_PCF8591(uchar CtrlByte) { //连续读入4路通道的转换结果并保存到Recv_Buffer
uchar i;
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_Ark();
for(i=0;i<4;i++) {
Recv_Buffer[i++] = IIC_ReceiveByte();
Slave_Ark();
}
Slave_NOArk();
IIC_Stop();
}
//向PCF8591发送1字节,进行D/A转换
void DAC_PCF8591(uchar CtrlByte,uchar dat) {
IIC_Start(); Delay4us();
IIC_SendByte(0x90);
if(IIC_ERROR==1) return;
IIC_SendByte(CtrlByte);
if(IIC_ERROR==1) return;
IIC_SendByte(dat);
if(IIC_ERROR==1) return;
IIC_Stop(); Delay4us(); Delay4us();
}
//主程序
void main()
{
LCD_Initialise();
while(1)
{
ADC_PCF8591(0x04);
Convert_To_Voltage(Recv_Buffer[0]); // 将4个转换通道的转换结果放入LCD显示缓冲LCD_Line_1,LCD_Line_2
LCD_Line_1[2]=Voltage[2];
LCD_Line_1[4]=Voltage[1];
LCD_Line_1[5]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[1]);
LCD_Line_1[11]=Voltage[2];
LCD_Line_1[13]=Voltage[1];
LCD_Line_1[14]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[2]);
LCD_Line_2[2]=Voltage[2];
LCD_Line_2[4]=Voltage[1];
LCD_Line_2[5]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[3]);
LCD_Line_2[11]=Voltage[2];
LCD_Line_2[13]=Voltage[1];
LCD_Line_2[14]=Voltage[0];
LCD_Display_A_Line(0x00,LCD_Line_1); //2行显示4通道的转换结果
LCD_Display_A_Line(0x40,LCD_Line_2);
DAC_PCF8591(0x40,Recv_Buffer[0]); //模拟量输出的转换结果,在proteus中看不到,只有在真实硬件中才能看到
}
}
/*
include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit CS=P1^0; //ADC0832引脚定义
sbit CLK=P1^1;
sbit DIO=P1^2;
sbit lcd_rs=P2^0; //LCD1602引脚定义
sbit lcd_rw=P2^1;
sbit lcd_en=P2^2;
void DelayMS(uint ms) { //延时子程序
uint t;
while(ms--) for(t=0;t<120;t++);
}
bit LCD_Busy_Check() { //LCD忙状态检测
bit result;
lcd_rs=0; lcd_rw=1; lcd_en=1;
DelayMS(5);
lcd_en=0;
DelayMS(5);
result=P0^7; //result=(bit)(P0&0x80);
return result;
}
void write_com(uchar com){ //写命令
//while(LCD_Busy_Check()); //LCD是否忙?
lcd_rs=0; lcd_rw=0; P0=com;
lcd_en=1; DelayMS(2);
lcd_en=0;
}
void write_data(uchar date) { //写数据
//while(LCD_Busy_Check()); //LCD是否忙?
lcd_rs=1; lcd_rw=0; P0=date;
lcd_en=1; DelayMS(2);
lcd_en=0;
}
void lcd_disp(uchar *s) { //显示子函数
while(*s>0) {write_data(*s);s++;}
}
void lcd_init() { //lcd初始化函数
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
uchar Display_Buffer[]="0.000V"; //1位整数、3位小数的数字电压显示缓冲
uchar Get_AD_Result() {
uchar i, dat1=0, dat2=0; //起始控制位
CS=0; CLK=0; DIO=1;_nop_();_nop_();
CLK=1;_nop_();_nop_();
CLK=0; //第一个下降沿之前,设DI=1/0,选择单端/差分(SGL/DIF)模式中的单端输入模式
DIO=1;_nop_();_nop_();
CLK=1;_nop_();_nop_();
CLK=0;DIO=0;_nop_();_nop_(); //第二个下降沿之前,设DI=1/0,选择CH0/CH1
CLK=1;DIO=1;_nop_();_nop_();
CLK=0;DIO=1;_nop_();_nop_(); //第三个下降沿之前,设DI=0
for(i=0;i<8;i++) //第4-11,共8个下降沿读取数据(MSB->LSB)
{
CLK=1;_nop_();_nop_();
CLK=0;_nop_();_nop_();
dat1=dat1<<1|DIO;
}
for(i=0;i<8;i++) { //第11-18,共8个下降沿读取数据(LSB->MSB)
dat2=dat2 | ((uchar)(DIO)<<i);
CLK=1;_nop_();_nop_();
CLK=0;_nop_();_nop_();
}
CS=1;
return (dat1==dat2) ? dat1 : 0; //如果两次读取的结果相同,则返回读取的结果,否则返回0
}
void main()
{
uchar i;
uint d;
lcd_init();
DelayMS(3);
write_com(0x80|0x00);
lcd_disp("Current Voltage:");
while(1) {
d=Get_AD_Result()*5000.0/255;
Display_Buffer[0]=d/1000+'0';
Display_Buffer[2]=(d%1000)/100+'0';
Display_Buffer[3]=d%1000%100/10+'0';
Display_Buffer[4]=d%1000%100%10+'0';
write_com(0x80|0x46); //设置第二行显示位置
i=0;
while (Display_Buffer[i] != '\0')write_data(Display_Buffer[i++]);
}
}
*/
展开阅读全文