/*-------------------------------------------------------------------
LCD1602.c 1602用的函数
作者:liunian
邮箱:liunian_leon@sohu.com
日期:2008.7.13
版本:V1.0 适合初学者使用
-------------------------------------------------------------------*/
#include<reg51.h>
#include<absacc.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit EN=P2^2; //使能信号
sbit RW=P2^1; //读写控制信号
sbit RS=P2^0; //数据命令选择端口
sbit P34=P3^4;
sbit P35=P3^5;
#define D_port P0 //传送数据的端口设为P0,以上端口根据实际硬件电路图可做修改
uint ss,lo,loo;
uchar kl = 0;
unsigned char code love[]="Dual Integral AD";
unsigned char code no[]=" ";
unsigned char code time[]="0123456789ABCDEF:MinHour ";
unsigned char code tin[]= "Vin:";
unsigned char code tvref[]="Vref:";
/****************1MS延时函数******************************/
void delay(unsigned int n)
{
unsigned int i,j;
for(j=n;j>0;j--)
for(i=112;i>0;i--);
}
/*液晶***************查询液晶是否忙*************************/
void Checkbusy()
{
D_port=0xff; //P0全部置1,可以查询判断P0口状态,读取液晶的命令
RS=0;
RW=1;
EN=1;
_nop_(); //读液晶命令时各控制位的状态几时序
while(D_port&0x80) //判断最高位状态,最高位是液晶忙的状态位
{
EN=0;
_nop_();
_nop_();
EN=1;
_nop_();
_nop_();
} //如果液晶忙,则循环查询
EN=0;
}
/*液晶***************写数据到液晶***************************/
D_write(uchar a)
{
Checkbusy(); //检查忙标志位
D_port=a;
RS=1;
RW=0;
EN=1; //写数据各控制位的值既对应的时序
_nop_();
_nop_();
_nop_(); //发送数据,此处是发送到P0口,程序前已经定义
EN=0;
}
/*液晶***************写指令到液晶***************************/
C_write(uchar a)
{
Checkbusy(); //检查忙标志位
D_port=a;
RS=0;
RW=0;
EN=1; //写指令各控制位的值既对应的时序
_nop_();
_nop_();
_nop_(); //发送指令,此处是发送到P0口,程序前已经定义
EN=0;
}
/*液晶**************液晶初始化******************************/
Initial()
{
D_port=0;
delay(20);
C_write(0x38);
delay(10);
C_write(0x38);
delay(10);
C_write(0x38);
delay(10);
Checkbusy();
C_write(0x38);
Checkbusy();
C_write(0x08); //关闭显示
Checkbusy();
C_write(0x01); //清屏
Checkbusy();
C_write(0x06); //显示光标右移设置
Checkbusy();
C_write(0x0c); //显示开,光标不显示,不闪烁
delay(5);
} //根据1602初始化的指令顺序来初始化LCD,相关初始化步骤可查阅相关资料
/*液晶**************设定显示位置函数************************/
setpos(uchar posx,uchar posy)
{
posx=posx&0xf; //将显示在第几位置转为二十六进制,每行总共16个位置
posy=posy&0x1; //设置显示在第几行
C_write(posx|posy*0x40+0x80); //设置位置命令最高位必须为一,所以要加0x80
}
/*液晶**************显示一个字符子程序**********************/
displaychar(uchar x,uchar y,uchar a)
{
Checkbusy(); //检查忙标志位
setpos(x,y); //设置显示位置
D_write(a); //将要显示的数据写到液晶
}
/*液晶**************显示一串字符串**************************/
displaystring(uchar x,uchar y,unsigned char code *string)
{
uchar length=0; //定义一个字符串长度
Checkbusy();
while(string[length]!='\0') //字符串是以'\0'结束的,因此只要每结束就显示下一字符
{
displaychar(x,y,string[length++]); //显示一个字符子程序
x++; //液晶显示的位置+1
}
}
/*液晶**************显示个数**************************/
void lcd_byte(unsigned char x, unsigned char y ,unsigned int byte_data) //以十进制的方式显示一个字符变量
{
unsigned int temp_data;
temp_data=byte_data/10000; //求万位数
displaychar(x+0,y,temp_data+48); //转化为ASCII值再显示
temp_data=byte_data % 10000 /1000; //求千位数
displaychar(x+1,y,temp_data+48); //转化为ASCII值再显示
temp_data=byte_data%1000/100; //求百位数
displaychar(x+2,y,temp_data+48); //转化为ASCII值再显示
temp_data=byte_data%100/10; //求十位数
displaychar(x+3,y,temp_data+48); //转化为ASCII值再显示
temp_data=byte_data%10; //求个位数
displaychar(x+4,y,temp_data+48); //转化为ASCII再再显示
}
void my_t0(void) interrupt 1 //定时器0中断用于固定时间对输入待测电压进行积分
{
TR0 = 0; //T0中断关
P34=1; //选择-2.5V基准
TH0 = 0;
TL0 = 0;
//lo=lo+1;
//TMOD=TMOD | 0x8;
//TF0 = 0; //清除T0中断标志
TR0 = 1; //T0中断开
EX0 = 1; //INT0中断开
}
void my_int0(void) interrupt 0 //外部中断 用于反积分过程结束检测
{
TR0 = 0; //T0中断关
TF0 = 0; //清除T0中断标志
EX0 = 0; //INT0中断关
ss = TH0 * 256 + TL0;
P34=1; //选择-2.5V基准
// P35=1; //选择放电
TH0 = 0;
TL0 = 0;
kl = 0;
}
main()
{
Initial();
P34=1; //选择-2.5V基准
//P35=1; //选择放电
displaystring( 0, 0, love);
delay(500);
displaystring( 0, 0, no);
displaystring( 0, 1, tvref);
EA = 1; //中断开
ET0 = 1; //定时计数0中断开
IP = 1; //定时0中断最高优先级 =2
TMOD = 1; //定时0模式1 2个16位定时/计数器
TCON=0x00; //INT0负边缘触发或低电平触发在此好象作用相同
displaystring( 0, 0, tin);
while(1)
{
if(kl==0)
{
P34=1; //选择-2.5V基准
//P35=1; //选择放电
delay(26);
TMOD = 1;
TH0 = 0x63;
TL0 = 0xC0;
//loo=loo+1;
P34=0; //选择输入电压基准
//P35=0; //选择测量
kl = 1;
TR0 = 1; //定时计数0起动
TF0 = 0; //清除T0中断标志
}
delay(500);
//lo=ss*0.0773;
loo=ss-lo;
if(loo>32767)
{loo=65535-loo;}
lo=ss;
lcd_byte(5,0,ss);
lcd_byte(5,1,loo);
//lcd_byte(11,1,loo);
}
}