|
//********************************
//说明:调用VR2时,ADC0832将模拟电压转换为数字电压并显示在LCD1602上
//********************************
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delay4us(){_nop_();_nop_();_nop_();_nop_();}
//********************************
//ADC引脚定义
//********************************
sbit CS=P3^0;
sbit CLK=P3^1;
sbit DIO=P3^2;
//********************************
//LCD端口定义
//********************************
sbit RS=P3^7;
sbit RW=P3^6;
sbit E=P3^5;
//********************************
//一位整数、两位小数的数字电压显示缓冲
//********************************
uchar Display_Buffer[]="00.000V";
//********************************
//LCD第一行显示信息
//********************************
uchar code Line[]="TEST OK DC ";
//********************************
//延时子程序
//********************************
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
//********************************
//LCD忙状态检测
//********************************
bit LCD_BUSY_CHECK()
{
bit result;
RS=0;
RW=1;
E=1;
delay4us();
result=(bit)(P2&0x80);
E=0;
return result;
}
//********************************
//写LCD命令
//********************************
void LCD_Write_Command(uchar cmd)
{
while(LCD_BUSY_CHECK()); //判断LCD是否忙碌
RS=0;
RW=0;
E=0;
_nop_();
P2=cmd;
delay4us();
E=1;
delay4us();
E=0;
}
//********************************
//设置LCD显示位置
//********************************
void Set_Disp_Pos(uchar pos)
{
LCD_Write_Command(pos|0x80);
}
//********************************
//写LCD数据
//********************************
void LCD_Write_Data(uchar dat)
{
while(LCD_BUSY_CHECK()); //判断LCD是否忙碌
RS=1;
RW=0;
E=0;
P2=dat;
delay4us();
E=1;
delay4us();
E=0;
}
//********************************
//LCD初始化
//********************************
void LCD_Initialise()
{
LCD_Write_Command(0x38);DelayMS(1);
LCD_Write_Command(0x0C);DelayMS(1);
LCD_Write_Command(0x06);DelayMS(1);
LCD_Write_Command(0x01);DelayMS(1);
}
//********************************
//获取AD转换结果(0通道)
//********************************
uchar GET_AD_RESULT()
{
uchar i;
uchar dat1=0;
uchar dat2=0;
//起始控制位
CS=0;
CLK=0;
DIO=1;_nop_(); _nop_();
CLK=1;_nop_(); _nop_();
//第一个下降沿之前,设DI=1/0
//选择单端/差分(SGL\DIF)模式中的单端输入模式
CLK=0;
DIO=1;
_nop_();
_nop_();
CLK=1;
_nop_();
_nop_();
//第二个下降沿之前,设DI=0/1,选择CH0\CH1
CLK=0;
DIO=0;
_nop_();
_nop_();
CLK=1;
DIO=1;
_nop_();
_nop_(); //第三个下降沿之前,设DI=1
CLK=0;
DIO=1;
_nop_();
_nop_();
//第四个至第十一个,共八个下降沿读数据(MSB_LSB)
for(i=0;i<8;i++)
{
CLK=1;
_nop_();
_nop_();
CLK=0;
_nop_();
_nop_();
dat1=dat1<<1|DIO;
}
//第十一个至第十八个,共八个下降沿读数据(LSB_MSB)
for(i=0;i<8;i++)
{
dat2=dat2|((uchar)(DIO)<<i);
CLK=1;
_nop_();
_nop_();
CLK=0;
_nop_();
_nop_();
}
CS=1;
//如果MSB_LSB和LSB_MSB读取的结果相同,则返回读取的结果,否则返回0
return(dat1==dat2)?dat2:0;
}
//***************************
//主函数
//***************************
void main()
{
uchar i;
uint d;
LCD_Initialise();
DelayMS(10);
while(1)
{
//获取AD转换值,最大值为255对应于最高电压5.00V //本例中设计为三个显示数位,故用500
d=GET_AD_RESULT()/(255.0/5)*200; //将AD转换后的数据分解为3个数位
Display_Buffer[0]=d/1000+'0';
Display_Buffer[1]=d%1000/100+'0';
Display_Buffer[3]=d%100/10+'0';
Display_Buffer[4]=d%10+'0';
Set_Disp_Pos(0x00);
i=0;
while(Line[i]!='\0')
LCD_Write_Data(Line[i++]);
Set_Disp_Pos(0x46);
i=0;
while(Display_Buffer[i]!='\0')
LCD_Write_Data(Display_Buffer[i++]);
}
}
程序附上
|
|