#includereg51.h#includeintrins.h#defineucharunsignedchar#defineuintunsignedint#defineDelay4us(){_nop_();_nop_();_nop_();_nop_();}//引脚定义sbitLCD_RS=P2^0;sbitLCD_RW=P2^1;sbitLCD_EN=P2^2;//延时子程序voidDelayMS(intms){uchart;while(ms--)for(t=0;t120;t++);}//LCD忙状态检测bitLCD_Busy_Check(){bitResult;LCD_RS=0;LCD_RW=1;LCD_EN=1;Delay4us();Result=(bit)(P0&0x80);LCD_EN=0;returnResult;}//写LCD命令voidLCD_Write_Command(ucharcmd){//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数据voidLCD_Write_Data(uchardat){//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初始化voidLCD_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);//指针清零,显示清零}sbitSCL=P1^0;sbitSDA=P1^1;ucharRecv_Buffer[4];//数据接收缓冲(每通道1字节)uintVoltage[]={'0','0','0'};//数据分解为电压x.xxbitbdataIIC_ERROR;//设置I2C错误标志位ucharLCD_Line_1[]={1-.V2-.V};ucharLCD_Line_2[]={3-.V4-.V};voidLCD_Set_Position(ucharpos){//设置LCD显示位置LCD_Write_Command(pos|0x80);}voidLCD_Display_A_Line(ucharLine_Addr,uchars[]){//显示一行uchari;LCD_Set_Position(Line_Addr);for(i=0;i16;i++);LCD_Write_Data(s[i]);}//将模数转换后的值分解存入缓冲voidConvert_To_Voltage(ucharval){uchartmp;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总线voidIIC_Start(){SDA=1;SCL=1;Delay4us();SDA=0;Delay4us();SCL=0;}//停止I2C总线voidIIC_Stop(){SDA=0;SCL=1;Delay4us();SDA=1;Delay4us();SCL=0;}//从机发送应答voidSlave_Ark(){SDA=0;SCL=1;Delay4us();SCL=0;SDA=1;}//从机发送非应答voidSlave_NOArk(){SDA=1;SCL=1;Delay4us();SCL=0;SDA=0;}//发送一个字节voidIIC_SendByte(ucharwd){uchari;for(i=0;i8;i++)//循环移入8位{SDA=(bit)(wd&0x80);_nop_();_nop_();SCL=1;Delay4us();SCL=0;wd1;}Delay4us();SDA=1;SCL=1;Delay4us();//释放总线并准备读取应答IIC_ERROR=SDA;SCL=0;Delay4us();}//接收一个字节ucharIIC_ReceiveByte(){uchari,rd=0x00;for(i=0;i8;i++){//循环移入8位SCL=1;rd1;rd|=SDA;Delay4us();SCL=0;Delay4us();}SCL=0;Delay4us();returnrd;}voidADC_PCF8591(ucharCtrlByte){//连续读入4路通道的转换结果并保存到Recv_Bufferuchari;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;i4;i++){Recv_Buffer[i++]=IIC_ReceiveByte();Slave_Ark();}Slave_NOArk();IIC_Stop();}//向PCF8591发送1字节,进行D/A转换voidDAC_PCF8591(ucharCtrlByte,uchardat){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();}//主程序voidmain(){LCD_Initialise();while(1){ADC_PCF8591(0x04);Convert_To_Voltage(Recv_Buffer[0]);//将4个转换通道的转换结果放入LCD显示缓冲LCD_Line_1,LCD_Line_2LCD_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中看不到,只有在真实硬件中才能看到}}/*includereg52.h#includeintrins.h#defineuintunsignedint#defineucharunsignedcharsbitCS=P1^0;//ADC0832引脚定义sbitCLK=P1^1;sbitDIO=P1^2;sbitlcd_rs=P2^0;//LCD1602引脚定义sbitlcd_rw=P2^1;sbitlcd_en=P2^2;voidDelayMS(uintms){//延时子程序uintt;while(ms--)for(t=0;t120;t++);}bitLCD_Busy_Check(){//LCD忙状态检测bitresult;lcd_rs=0;lcd_rw=1;lcd_en=1;DelayMS(5);lcd_en=0;DelayMS(5);result=P0^7;//result=(bit)(P0&0x80);returnresult;}voidwrite_com(ucharcom){//写命令//while(LCD_Busy_Check());//LCD是否忙?lcd_rs=0;lcd_rw=0;P0=com;lcd_en=1;DelayMS(2);lcd_en=0;}voidwrite_data(uchardate){//写数据//while(LCD_Busy_Check());//LCD是否忙?lcd_rs=1;lcd_rw=0;P0=date;lcd_en=1;DelayMS(2);lcd_en=0;}voidlcd_disp(uchar*s){//显示子函数while(*s0){write_data(*s);s++;}}voidlcd_init(){//lcd初始化函数write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);}ucharDisplay_Buffer[]=0.000V;//1位整数、3位小数的数字电压显示缓冲ucharGet_AD_Result(){uchari,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/CH1CLK=1;DIO=1;_nop_();_nop_();CLK=0;DIO=1;_nop_();_nop_();//第三个下降沿之前,设DI=0for(i=0;i8;i++)//第4-11,共8个下降沿读取数据(MSB-LSB){CLK=1;_nop_();_nop_();CLK=0;_nop_();_nop_();dat1=dat11|DIO;}for(i=0;i8;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}voidmain(){uchari;uintd;lcd_init();DelayMS(3);write_com(0x80|0x00);lcd_disp(CurrentVolt