钻石会员
  
主题
帖子
积分11931
阅读权限50
注册时间2009-7-18
最后登录1970-1-1
在线时间 小时
|
本帖最后由 LBQ691477940 于 2011-1-23 12:43 编辑
能否把这个的程序改成串行驱动1602不要并行的,谢谢!
已自行搞掂了四线驱动方法式
#include <reg52.h>
#include <intrins.h>
#define nop _nop_()
#define PtData P0 //定义连接口线
#define uint unsigned int
#define uchar unsigned char
/*
sbit rs=P0^0;
sbit rw=P0^1;
sbit en=P0^2;
*/
sbit rs=P3^5;
sbit rw=P3^6;
sbit en=P3^4;
sbit DQ=P2^2;
sbit spk=P2^3;
sbit a0=ACC^0;
sbit a1=ACC^1;
sbit a2=ACC^2;
sbit a3=ACC^3;
sbit a4=ACC^4;
sbit a5=ACC^5;
sbit a6=ACC^6;
sbit a7=ACC^7;
sbit k1=P1^7; //调整模式
sbit k2=P1^6; //+按钮
sbit k3=P1^5; //-按钮
sbit k4=P1^4;
/*
sbit clock_clk =P2^2;// P3^2;//ds1302_clk(时钟线7)
sbit clock_dat =P2^1;// P2^4;//ds1302_dat(数据线6)
sbit clock_Rst =P2^0;// P3^3;//ds1302_Rst(复位线5)
*/
sbit clock_clk =P3^2;//ds1302_clk(时钟线7)
sbit clock_dat =P2^4;//ds1302_dat(数据线6)
sbit clock_Rst =P3^3;//ds1302_Rst(复位线5)
uint idata tdat; //温度值变量
char idata sett; //模式计数变量
char tflag; //温度正负标志
char idata disp_buf1[16];//1602显示缓冲区1(即上排16个字符)
char idata disp_buf2[16];//1602显示缓冲区2(即下排16个字符)
char idata timedata[7];//存放时间值变量
uchar code table[]="Temperature ok !";
char idata temdata[5]; //存放温度值变量
uchar i;
uchar code self_dat[]={
0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00, //一,代码 0x04
0x00,0x00,0x00,0x0e,0x00,0xff,0x00,0x00, //二,代码 0x05
0x00,0x00,0xff,0x00,0x0e,0x00,0xff,0x00, //三,代码 0x06
0x00,0x00,0xff,0xf5,0xfb,0xf1,0xff,0x00, //四,代码 0x07
0x00,0xfe,0x08,0xfe,0x0a,0x0a,0xff,0x00, //五,代码 0x08
0x00,0x04,0x00,0xff,0x00,0x0a,0x11,0x00, //六,代码 0x09
0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00}; //日,代码 0x0a};//自定义字符
//************LCD相关函数**********************************//
void delay(uint n) //延时时间为n*1ms
{ uchar x=0;
for(;n>0;n--)
{
for(;x<250;x++)
{
nop;
nop;
nop;
nop;
}
}
}
/*=====================================================================
void check_busy() //LCD忙检测函数
{
P0=0xff;
rs=0;
rw=1;
en=1;
while(P0&0x80);
en=0;
}
void lcd_wcom(uchar com) //写命令
{ check_busy();
rw=0;
rs=0;
P0=com;
en=1;
en=0;
}
void lcd_wdat(uchar dat) //写数据
{ check_busy();
rw=0;
rs=1;
P0=dat;
en=1;
en=0;
}
=======================================================================*/
void check_busy() //LCD忙检测函数
{
/*uchar Temp,t;
PtData=0xff;
rw=1;
rs=0;nop;
en=0;nop;
do
{
nop;
en=1;nop;
Temp=PtData;
nop;nop;nop;
en=0;nop;nop;
en=1;nop;
t=PtData;
nop;nop;nop;
en=0;nop;nop;
Temp&=0x80;
}
while(Temp==0x80);*/
P0=0xff;
rs=0;
rw=1;
en=1;
while(P0&0x80);
en=0;
}
//----------------------------------------------------------------------
void lcd_wcom(uchar Temp)//---写指令
{
check_busy();
rs=0;
rw=0;
en=0;nop;
en=1;nop;
PtData=Temp;
nop;
en=0;nop;
en=1;nop;
PtData=(Temp<<4);//左移四位
nop;
en=0;nop;
}
//--------------------------------------------------------------------------
void lcd_wdat(uchar Temp)//---写数据
{
check_busy();
rs=1;
rw=0;
en=0;nop;
en=1;nop;
PtData=Temp;
nop;
en=0;nop;
en=1;nop;
PtData=(Temp<<4);
nop;
en=0;nop;
}
//
void self_data() //写入自定义字符
{
uchar i=0;
lcd_wcom(0x06); //设定地址指针加一
lcd_wcom(0x48); //装入自定义字符的起始地址(CGRAM)
for(;i<64;i++)
lcd_wdat(self_dat);
}
void lcd_init() //初始化
{
lcd_wcom(0x28); //8位,双列,5*7
//lcd_wcom(0x38); //8位,双列,5*7
lcd_wcom(0x0c); //开显示,关光标,光标所在字符不闪烁
lcd_wcom(0x06); //显示地址递增
lcd_wcom(0x01); //清屏,光标移到左上角
self_data();
}
/*------------------------------------------------------------------------
//---初始化
void lcd_init()
{
Delay(600);//延时应大于15ms,不同的晶振使需要修改,本程序再6M下调试通过
rs=0;
rw=0;nop;
en=0;nop;
en=1;nop;
PtData=0x20;//
nop;
en=0;
Delay(200);//延时应大于4.1ms
en=1;nop;
PtData=0x20;//
nop;
en=0;
Delay(5);//延时应大于100us
en=1;nop;
PtData=0x20;//
nop;
en=0;//设置4位操作;
WriteLcdInstr(0x01);//清屏
WriteLcdInstr(0x28);//设置4位操作,1行显示,5x8
WriteLcdInstr(0x02);//光标归位
WriteLcdInstr(0x06);//AC自动加1,画面不动
WriteLcdInstr(0x0f);//0x0f:光标闪烁开;
}
------------------------------------------------------------------------------*/
//***********DS18B20相关函数*******************//
void delay_18b20(uint sum)
{
while(sum--);
}
void rst_18b20() //复位
{ //uchar flag;
DQ=1;
delay_18b20(8);
DQ=0;
delay_18b20(80);
DQ=1;
delay_18b20(13);
//flag=DQ;
//return(flag);
delay_18b20(20);
}
void wr_18b20(uchar dat) //写一个字节的数据
{
uchar i=8;
for(;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay_18b20(5);
DQ=1;
dat>>=1;
}
}
uchar rd_18b20() //读一个字节的数据
{
uchar dat=0,i=8;
for(;i>0;i--)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
delay_18b20(4);
}
return(dat);
}
uint rd_temperature() //读取温度值,返回值为uint型,占两个字节
{
uchar a=0,b=0;
uint t=0;
float tt=0;
rst_18b20(); //复位
wr_18b20(0xcc); //跳过ROM
wr_18b20(0x44); //启动温度转换
rst_18b20(); //再次对18B20操作时,需要重新复位一次
wr_18b20(0xcc); //跳过ROM
wr_18b20(0xbe); //读取内部RAM的内容
a=rd_18b20(); //读温度值低位(内部RAM的第0个字节)
b=rd_18b20(); //读温度值高位(内部RAM的第1个字节)
t=b;
t<<=8; //温度值高位放在t的高8位
t=t|a; //温度值低位放在t的低8位
if(t<0x0fff) //判断温度值为正还是负
tflag=0; //tflag=0温度值为正
else
{
t=~t+1; //温度值为负,负值以补码存放,这里要将其还原为原码
tflag=1; //tflag=1温度值为负
}
tt=t*0.0625;
t= tt*10; //放大10倍精确到一位小数
return(t);
}
//***********************************************//
uchar disp_self(uchar i) //判断自定义字符是第几个
{
switch(i)
{
case 1:i=1;break;
case 2:i=2;break;
case 3:i=3;break;
case 4:i=4;break;
case 5:i=5;break;
case 6:i=6;break;
case 7:i=7;break;
default : break;
}
return(i);
}
void tem_conv()
{
uchar flagdat ;//定义温度值符号
if(tflag==0)
temdata[4]=flagdat=0x20;//正温度不显示符号
else
temdata[4]=flagdat=0x2d;//负温度显示负号:-
temdata[0]=tdat/1000+0x30;//温度百位值
temdata[1]=tdat%1000/100+0x30;//温度十位值
temdata[2]=tdat%100/10+0x30;//温度个位值
temdata[3]=tdat%10+0x30;//温度小数位值
if(temdata[0]==0x30)
{temdata[0]=0x20;//如果百位为0,不显示
if(temdata[1]==0x30)
{
temdata[1]=0x20;//如果百位为0,十位为0也不显示
}
}
}
void beeper(uchar i) //蜂鸣器
{
uchar j;
for(j=i;j>0;j--)
{
spk=0;
delay(200);
spk=~spk;
delay(200);
}
}
void int_display() //初始显示
{
uchar m=0;
lcd_init();
lcd_wcom(0x80); //显示地址
for(m=0;m<16;m++)
{
lcd_wdat(table[m]); //将数组中字符显示出来
delay(1000);
}
delay(10);
beeper(2);
lcd_wcom(0x01);
}
//********************************************//
void updata_disp() //更新缓冲区数据程序
{
disp_buf1[0]='2';
disp_buf1[1]='0';
disp_buf1[2]=timedata[6]/16+0x30;
disp_buf1[3]=timedata[6]%16+0x30;
disp_buf1[4]='/';
disp_buf1[5]=timedata[4]/16+0x30;
disp_buf1[6]=timedata[4]%16+0x30;
disp_buf1[7]='/';
disp_buf1[8]=timedata[3]/16+0x30;
disp_buf1[9]=timedata[3]%16+0x30;
disp_buf1[10]=0x20;
disp_buf1[11]='[';
disp_buf1[12]=disp_self(timedata[5]%16);
disp_buf1[13]=']';
disp_buf1[14]=0x20;
disp_buf1[15]=0x20;
disp_buf2[0]=timedata[2]/16+0x30;
disp_buf2[1]=timedata[2]%16+0x30;
disp_buf2[2]=':';
disp_buf2[3]=timedata[1]/16+0x30;
disp_buf2[4]=timedata[1]%16+0x30;
disp_buf2[5]=':';
disp_buf2[6]=timedata[0]/16+0x30;
disp_buf2[7]=timedata[0]%16+0x30;
disp_buf2[8]=temdata[4];
disp_buf2[9]=temdata[0];
disp_buf2[10]=temdata[1];
disp_buf2[11]=temdata[2];
disp_buf2[12]='.';
disp_buf2[13]=temdata[3];
disp_buf2[14]=0xdf;
disp_buf2[15]='C';
}
void display() //显示缓冲区数据函数
{
uchar i;
lcd_wcom(0x80);
for(i=0;i<16;i++)
lcd_wdat(disp_buf1);
lcd_wcom(0xc0);
for(i=0;i<16;i++)
lcd_wdat(disp_buf2);
}
//**************DS1302相关子函数**************//
//DS1302写入字节(底层协议)
uchar clock_in(){
clock_dat=1;
a0=clock_dat;
clock_clk=1; clock_clk=0; a1=clock_dat;
clock_clk=1; clock_clk=0; a2=clock_dat;
clock_clk=1; clock_clk=0; a3=clock_dat;
clock_clk=1; clock_clk=0; a4=clock_dat;
clock_clk=1; clock_clk=0; a5=clock_dat;
clock_clk=1; clock_clk=0; a6=clock_dat;
clock_clk=1; clock_clk=0; a7=clock_dat;
return(ACC);
}
//1302驱动程序(底层协议)
void clock_out(uchar dd){
ACC=dd;
clock_dat=a0; clock_clk=1; clock_clk=0;
clock_dat=a1; clock_clk=1; clock_clk=0;
clock_dat=a2; clock_clk=1; clock_clk=0;
clock_dat=a3; clock_clk=1; clock_clk=0;
clock_dat=a4; clock_clk=1; clock_clk=0;
clock_dat=a5; clock_clk=1; clock_clk=0;
clock_dat=a6; clock_clk=1; clock_clk=0;
clock_dat=a7; clock_clk=1; clock_clk=0;
}
//DS1302读数据(底层协议)
uchar read_clock(uchar ord){
uchar dd=0;
clock_clk=0;
clock_Rst=0;
clock_Rst=1;
clock_out(ord);
dd=clock_in();
clock_Rst=0;
clock_clk=1;
return(dd);
}
//DS1302写数据(底层协议)
void write_clock(uchar ord, uchar dd){
clock_clk=0;
clock_Rst=0;
clock_Rst=1;
clock_out(ord);
clock_out(dd);
clock_Rst=0;
clock_clk=1;
}
//设置1302的初始时间
void Init_1302(){//(2011年1月23日12时28分00秒星期日)
if(read_clock(0xc1) != 0xf0)
{
write_clock(0x8e,0x00);//允许写操作
write_clock(0x8c,0x11);//年
write_clock(0x8a,0x07);//星期
write_clock(0x88,0x01);//月
write_clock(0x86,0x23);//日
write_clock(0x84,0x12);//小时
write_clock(0x82,0x28);//分钟
write_clock(0x80,0x00);//秒
write_clock(0x90,0xa5);//充电
write_clock(0xc0,0xf0); //判断是否初始化一次标识写入
write_clock(0x8e,0x80);//禁止写操作
}
}
//常用时钟数据读取
void read_clocks()
{
timedata[0] = read_clock(0x81);//读取秒数据
timedata[1] = read_clock(0x83);//读取分钟数据
timedata[2] = read_clock(0x85);//小时
timedata[3] = read_clock(0x87);//日
timedata[4] = read_clock(0x89);//月
timedata[5] = read_clock(0x8b);//星期
timedata[6] = read_clock(0x8d);//年
}
void set_display(uchar com, uchar dat) //调整时间时显示函数
{
lcd_wcom(com);
lcd_wdat(dat/16+0x30);
lcd_wdat(dat%16+0x30);
}
set_selfdisplay(uchar com, uchar dat) //调整星期时自定义字符显示函数
{
lcd_wcom(com);
lcd_wdat(dat);
}
void int_checkbutton() //初始化按键
{
k1=1;
k2=1;
k3=1;
k4=1;
}
void int_t0() interrupt 1 using 1 //定时中断
{
TH0=0x3c;
TL0=0xb0;
i++;
if(i==10)
{
i=0;
display();//更新显示数据
}
}
//**************主程序************************//
void main()
{
TMOD=0x01; //设置定时中断
TH0=0x3c;
TL0=0xb0;
EA=1;
ET0=1;
TR0=1;
int_display(); //初始化显示
int_checkbutton(); //按键初始化
Init_1302(); //1302初始化
while(1)
{
if(k1==0) //调整模式键按下
{
delay(30);
if(k1==0)
{
while(!k1); //确定按下
sett++;
TR0=0;
beeper(1);
if(sett==1) //按下的次数不同,光标移动到不同的调整位置处
{
lcd_wcom(0x0f);
lcd_wcom(0x83);
}
if(sett==2)
{
lcd_wcom(0x86);
}
if(sett==3)
{
lcd_wcom(0x89);
}
if(sett==4)
{
lcd_wcom(0x8c);
}
if(sett==5)
{
lcd_wcom(0xc1);
}
if(sett==6)
{
lcd_wcom(0xc4);
}
if(sett==7)
{
lcd_wcom(0xc7);
}
if(sett==8) //第八次按下模式键,退出调整,恢复走时显示
{
sett=0;
lcd_wcom(0x0c);
TR0=1;
}
}
}if(sett!=0)
{
if(k2==0) //增加键按下
{
delay(30); //延时消抖
if(k2==0)
{
while(!k2);
beeper(1); //按键放开之后蜂鸣器叫一下,表示确定
if(sett==1) //根据按下的次数调整相应的项目
{ uchar item ;
item=timedata[6];
item=(item/16)*10+item%16;
item++; //年份加一
if(item==100)item=0;
item=(item/10)*16+item%10;
set_display(0x82,item); //调整时显示
write_clock(0x8e,0x00);//允许写操作
write_clock(0x8c,item);
lcd_wcom(0x83);
}
if(sett==2)
{ uchar item ;
item=timedata[4];
item=(item/16)*10+item%16;
item++; //月份加一
if(item==13)item=0;
item=(item/10)*16+item%10;
set_display(0x85,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x88,item);
lcd_wcom(0x86);
}
if(sett==3)
{ uchar item ;
item=timedata[3];
item=(item/16)*10+item%16;
item++; //日加一
if(item==32)item=0;
item=(item/10)*16+item%10;
set_display(0x88,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x86,item);
lcd_wcom(0x89);
}
if(sett==4)
{ uchar item ;
item=timedata[5];
item=(item/16)*10+item%16;
item++; //星期加一
if(item==8)item=1;
item=(item/10)*16+item%10;
set_selfdisplay(0x8c,disp_self(item%16));
write_clock(0x8e,0x00);//允许写操作
write_clock(0x8a,item);
lcd_wcom(0x8c);
}
if(sett==5)
{ uchar item ;
item=timedata[2];
item=(item/16)*10+item%16;
item++; //小时加一
if(item==24)item=0;
item=(item/10)*16+item%10;
set_display(0xc0,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x84,item);
lcd_wcom(0xc1);
}
if(sett==6)
{ uchar item ;
item=timedata[1];
item=(item/16)*10+item%16;
item++; //分加一
if(item==60)item=0;
item=(item/10)*16+item%10;
set_display(0xc3,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x82,item);
lcd_wcom(0xc4);
}
if(sett==7)
{ uchar item ;
item=timedata[0];
item=(item/16)*10+item%16;
item++; //秒加一
if(item==60)item=0;
item=(item/10)*16+item%10;
set_display(0xc6,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x80,item);
lcd_wcom(0xc7);
}
}
}
if(k3==0) //下面这段是减按钮的程序,和加按钮程序差不多
{ //唯一不同就是++变成--,还有就是上限变成了下限
delay(30);
if(k3==0)
{
while(!k3);
beeper(1);
if(sett==1)
{ uchar item ;
item=timedata[6];
item=(item/16)*10+item%16;
item--;
if(item==0)item=99;
item=(item/10)*16+item%10;
set_display(0x82,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x8c,item);
lcd_wcom(0x83);
}
if(sett==2)
{ uchar item ;
item=timedata[4];
item=(item/16)*10+item%16;
item--;
if(item==-1)item=12;
item=(item/10)*16+item%10;
set_display(0x85,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x88,item);
lcd_wcom(0x86);
}
if(sett==3)
{ uchar item ;
item=timedata[3];
item=(item/16)*10+item%16;
item--;
if(item==-1)item=31;
item=(item/10)*16+item%10;
set_display(0x88,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x86,item);
lcd_wcom(0x89);
}
if(sett==4)
{ uchar item ;
item=timedata[5];
item=(item/16)*10+item%16;
item--;
if(item==0)item=7;
item=(item/10)*16+item%10;
set_selfdisplay(0x8c,disp_self(item%16));
write_clock(0x8e,0x00);//允许写操作
write_clock(0x8a,item);
lcd_wcom(0x8c);
}
if(sett==5)
{ uchar item ;
item=timedata[2];
item=(item/16)*10+item%16;
item--;
if(item==-1)item=23;
item=(item/10)*16+item%10;
set_display(0xc0,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x84,item);
lcd_wcom(0xc1);
}
if(sett==6)
{ uchar item ;
item=timedata[1];
item=(item/16)*10+item%16;
item--;
if(item==-1)item=59;
item=(item/10)*16+item%10;
set_display(0xc3,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x82,item);
lcd_wcom(0xc4);
}
if(sett==7)
{ uchar item ;
item=timedata[0];
item=(item/16)*10+item%16;
item--;
if(item==-1)item=59;
item=(item/10)*16+item%10;
set_display(0xc6,item);
write_clock(0x8e,0x00);//允许写操作
write_clock(0x80,item);
lcd_wcom(0xc7);
}
}
}
}
tdat=rd_temperature(); //读温度值
tem_conv(); //转化温度
read_clocks(); //读时钟数据
updata_disp(); //数据送入显示缓冲区
}
} |
|