📄 按键.c
字号:
#include <reg51.h>
#include <intrins.h>
#define HIGH 1
#define LOW 0
#define uchar unsigned char
#define uint unsigned int
//***************LCD1602********************************
#define DATA_MODE 0x28 //LCD模式设置,0x28位四位数据线模式
#define OPEN_SCREEN 0x0C //打开LCD显示
#define DISPLAY_ADDRESS 0x80 //写地址指令
#define CLEARSCREEN LCD_en_com(0x01) //清屏
#define LCDIO P0 //LCD1602的高四位接在P0口的高四位
sbit LCD1602_RS=P0^1; //RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
sbit LCD1602_EN=P0^0; //E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
void LCD_en_com(uchar command); //写命令指令
void LCD_en_dat(uchar temp); //写数据指令
void LCD_set_xy(uchar x, unsigned char y); //设置显示地址:X为横轴(0-15),Y为纵轴(0-1).
void LCD_write_char(uchar x,uchar y,uchar dat); //写一个字符
void LCD_write_string(uchar x,uchar y,uchar *s);//写一个字符串
void LCD_write_int(uchar x,uchar y,uint intdat); //写无字符型整形数
void LCD_init(void); //lcd初始化
void cover(void);
//************************DS1302*******************************************//
sbit ds1302_RST =P3^4; //ds1302的接线
sbit ds1302_IO =P3^3;
sbit ds1302_SCLK=P3^2;
sbit ACC0=ACC^0; //累加器
sbit ACC7=ACC^7;
uchar times[7]={0x50,0x59,0x23,0x30,0x11,0x07,0x08}; //存放时间
//uchar times[7];
uchar led[13];
void init_ds1302();
void get_ds1302() ;
void set_ds1302(uchar taddr,uchar *P1302);
uchar read_data_ds1302(uchar taddr);
void write_data_ds1302(uchar taddr,uchar tdata);
void write_Byte(uchar tdata);
uchar read_Byte();
void change_time(unsigned char i);
//*************************DS18B20*******************************************//
sbit DQ=P1^0;
uint h; //定义循环变量
uchar data temp_data[2]={0x00,0x00}; // 读出温度暂放
uchar data display[5]={0x00,0x00,0x00,0x00,0x00};//显示单元数据,共4个数据,一个运算暂存用
uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
//************************其他******************************************//
sbit alarm_speaker=P3^7; //蜂鸣器的接线
void delay(uchar i); //延时程序
unsigned char key=16; //存放健值
//***************************************************************************************
void LCD_en_write(void) //EN端产生一个高电平脉冲,写LCD
{
LCD1602_EN=HIGH;
_nop_();
LCD1602_EN=LOW;
}
//****************************************************************************************
void LCD_en_com(uchar command)
{
delay(9);
LCD1602_RS=LOW; //RS=0 写命令
LCDIO&=0x0f; //清高四位
LCDIO|=command&0xf0; //先发送高四位数据
LCD_en_write();
command=command<<4;
LCDIO&=0x0f;
LCDIO|=command&0xf0; //发送低四位数据
LCD_en_write();
}
//*****************************************************************************************
void LCD_en_dat(uchar dat)
{
delay(9);
LCD1602_RS=HIGH; //RS=1 写数据
LCDIO&=0x0f; //清高四位
LCDIO|=dat&0xf0; //写高四位
LCD_en_write();
dat=dat<<4; //低四位移到高四位
LCDIO&=0x0f; // 清高四位
LCDIO|=dat&0xf0; //写低四位
LCD_en_write();
}
//**************设置显示地址:X为横轴(0-15),Y为纵轴(0-1)**************************************
void LCD_set_xy(uchar x,uchar y)
{
uchar address;
x&=0x0f;
if(!y)
address=0x80+x;
else
address=0xc0+x;
LCD_en_com(address);
}
//***************写一个字符:X为横轴(0-15),Y为纵轴(0-1)**********
void LCD_write_char(uchar x,uchar y,uchar dat)
{
LCD_set_xy(x,y);
LCD_en_dat(dat);
}
//***************写一个字符串**********
void LCD_write_string(uchar x,uchar y,const uchar *s)
{
LCD_set_xy(x,y);
while(*s)
{
LCD_en_dat(*s);
s++;
}
}
//****************写一个无字符整数***************************************
void LCD_write_int(uchar x,uchar y,uint intdat)
{
uchar i=0,temp[5];
LCD_set_xy(x,y);
if(intdat==0)
{
LCD_en_dat(0x30);
return;
}
while(intdat/10 || intdat%10)
{
temp[i]=intdat%10;
intdat/=10;
i++;
}
while(i)
{
i--;
LCD_en_dat(temp[i]+0x30);
}
}
//*****//LCD的初始化函数(刚上电的时候一定要调用一次)//*********************
void LCD_init(void)
{
LCD_en_com(DATA_MODE); //设计四位数据线模式
LCD_en_write();
delay(9);
LCD_en_com(DATA_MODE);
LCD_en_com(OPEN_SCREEN); //打开LCD显示
LCD_en_com(DISPLAY_ADDRESS);//设计首地址
CLEARSCREEN; //清屏
delay(9);
}
//***********************18b20************
//*********************11微秒延时函数*********************//
void delay1(uint t)
{
for(;t>0;t--);
}
//*********************18B20复位函数*********************//
reset(void)
{
char presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_();//总线上拉
DQ=0; //下拉
delay1(50); //维持550us,最短维持480us
DQ=1; //总线上拉
delay1(6); //检测总线上升沿,66us
presence=DQ; //DS18B20发存在低电平信号(60-240us);presence=0继续下一步
}
delay1(30); //延时300us,总线恢复高电平,DQ=1;
presence = ~DQ; //取反,跳出循环
}
DQ=1;
}
//*********************18B20写命令函数*********************//
void write_byte1(uchar val)
{
uchar i;
for (i=8; i>0; i--) //定义 8 bit,写 8 bit
{
DQ=1;_nop_();_nop_();
DQ = 0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us
DQ = val&0x01; //最低位移出,并写入总线
delay1(6); //66us
val=val/2; //右移一位,倒数第二位变为最低位
}
DQ = 1;
delay(1); //高电平维持11us,写结束
}
//*********************18B20读1个字节函数*********************//
uchar read_byte1(void)
{
uchar i;
uchar value = 0;
for (i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
value>>=1; //右移一位
DQ = 0;
_nop_();_nop_();_nop_();_nop_(); //4us
DQ = 1;_nop_();_nop_();_nop_();_nop_(); //4us ,读时隙
if(DQ)value|=0x80; //DQ=1,则写入为 10000000
delay1(6); //66us
}
DQ=1;
return(value);
}
//*********************读出温度函数*********************//
read_temp()
{
reset(); //总线复位
write_byte1(0xCC); // 发Skip ROM命令
write_byte1(0xBE); // 发读命令
temp_data[0]=read_byte1(); //温度低8位
temp_data[1]=read_byte1(); //温度高8位
reset();
write_byte1(0xCC); // Skip ROM
write_byte1(0x44); // 发转换命令
}
//*********************温度数据处理函数*********************//
work_temp()
{
uchar n=0; //存储符号
if(temp_data[1]>112)
{temp_data[1]=(0xFF-temp_data[1]);temp_data[0]=(0xFF-temp_data[0]);n=1;} //负温度求补码
display[4]=temp_data[0]&0x0f;display[0]=ditab[display[4]]; //处理小数位
display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//低八位屏蔽小数位后右移四位与高八位屏蔽符号位后左移四位合并//
if(n){display[4]+=1;display[0]-=9;}
display[3]=display[4]/100; //百位
display[1]=display[4]%100;
display[2]=display[1]/10; //十位
display[1]=display[1]%10; //个位
LCD_write_int(11,1,display[1]); //显示温度的个位
LCD_en_dat('.');
LCD_write_int(13,1,display[0]); //显示温度的小数位
LCD_en_dat(0x27); //显示'号
LCD_en_dat('C'); //显示C
if(!display[3])
{
LCD_write_string(9,1," ");
if(!display[2])
{
LCD_write_string(10,1," ");
}
else
LCD_write_int(10,1,display[2]);
}
else
{
LCD_write_int(9,1,display[3]);
LCD_write_int(10,1,display[2]);
}
if(n)
{
if(!display[2])
LCD_write_string(10,1,"-");
else
LCD_write_string(9,1,"-");
} //负温度时最高位显示"-"
}
/*====ds1302初始化====================*/
void init_ds1302()
{
ds1302_RST=0;
ds1302_SCLK=0;
}
/*====从1302读出一字节数据并返回=====================*/
uchar read_Byte()
{
uchar i;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC7=ds1302_IO;
ds1302_SCLK=1;
ds1302_SCLK=0;
}
return(ACC);
}
//*====向1302写入一字节数据tdata====================*/
void write_Byte(uchar tdata)
{
uchar i;
ACC=tdata;
for(i=8;i>0;i--)
{
ds1302_IO=ACC0;
ds1302_SCLK=1;
ds1302_SCLK=0;
ACC=ACC>>1;
}
}
/*====向1302地址taddr处写入数据tdata====================*/
void write_data_ds1302(uchar taddr,uchar tdata)
{
ds1302_RST=0;
ds1302_SCLK=0;
ds1302_RST=1;
write_Byte(taddr);
write_Byte(tdata);
ds1302_RST=0;
ds1302_SCLK=1;
}
/*====从1302地址taddr处读出数据并返回====================*/
uchar read_data_ds1302(uchar taddr)
{
uchar tdata;
ds1302_RST=0;
ds1302_SCLK=0;
ds1302_RST=1;
write_Byte(taddr);
tdata=read_Byte();
ds1302_RST=0;
ds1302_SCLK=1;
return(tdata);
}
/*====设置时间====================*/
void set_ds1302(uchar taddr,uchar *P1302)
{
uchar i;
write_data_ds1302(0x8e,0x00);
for(i=0; i<7; i++)
{
write_data_ds1302(taddr,*P1302);
P1302++;
taddr+=2;
}
write_data_ds1302(0x8e,0x80);
}
/*====读出时间====================*/
void get_ds1302()
{
uchar k;
uchar taddr = 0x81;
for (k=0; k<7; k++)
{
times[k] = read_data_ds1302(taddr);
taddr+=2;
}
}
//**********转换计算***************
void cover()
{
led[0]=times[0]&0x0f;
led[1]=times[0]>>4;
led[2]=times[1]&0x0f;
led[3]=times[1]>>4;
led[4]=times[2]&0x0f;
led[5]=times[2]>>4;
led[6]=times[3]&0x0f;
led[7]=times[3]>>4;
led[8]=times[4]&0x0f;
led[9]=times[4]>>4;
led[10]=times[5];
led[11]=times[6]&0x0f;
led[12]=times[6]>>4;
}
//********显示时间的函数**************//
void display_dat() //显示时间和温度的函数
{
LCD_write_int(12,0,led[10]);//显示星期
LCD_write_int(0,0,2000+times[6]); //显示年份
LCD_en_dat('-');
LCD_write_int(5,0,led[9]); //显示月份
LCD_write_int(6,0,led[8]);
LCD_en_dat('-');
LCD_write_int(8,0,led[7]); //显示日期
LCD_write_int(9,0,led[6]);
LCD_write_int(0,1,led[5]); //显示小时
LCD_write_int(1,1,led[4]);
LCD_en_dat(':');
LCD_write_int(3,1,led[3]); //显示分钟
LCD_write_int(4,1,led[2]);
LCD_en_dat(':');
LCD_write_int(6,1,led[1]); //显示秒
LCD_write_int(7,1,led[0]);
}
//*================================================*/
void delay(unsigned char i) //延时函数
{
unsigned char j;
while(i--)
for(j=101;j>1;j--);
}
//*******************************
void key_scan()
{ unsigned char X,Y,Z,k=key;
P2=0x0f;
P2=0x0f; //先对P3置数行扫描
if(P2!=0x0f) //判断是否有键按下
{ delay(5); //延时,软件去干扰
if(P2!=0x0f) //确认按键按下X = P3;
{
X=P2; //保存行扫描时有键按下时状态
P2=0xf0; //列扫描
delay(5);
Y=P2; //保存列扫描时有键按下时状态
Z=X|Y; //取出键值
switch ( Z ) //判断键值(那一个键按下)
{
case 0xe7: k=1;break; //秒
case 0xd7: k=5;break; //月
case 0xb7: k=9;break;//设温
case 0x77: k=13;break;//确定
case 0xeb: k=2;break;//分
case 0xdb: k=6;break;//星期
case 0xbb: k=10;break;//定时
case 0x7b: k=14;break; //退出
case 0xed: k=3;break;//时
case 0xdd: k=7;break; //年
case 0xbd: k=11;break; //递增
case 0x7d: k=15;break; //取消
case 0xee: k=4;break; //日
case 0xde: k=8;break; //闹钟
case 0xbe: k=12;break; //递减
case 0x7e: k=16;break; //开关
}
key=k-1;
}
}
P2=0xff;
}
//******************温度定时调整*****************************//
void change_time(unsigned char i)
{
unsigned char tem=0,temp_time=0;
if(i<=6)
{
if(i==0) {CLEARSCREEN;LCD_write_string(0,0,"Change second:");} //修改秒
key=16;
delay(250);
while(1)
{
key_scan();
if(key<10)
{
tem=(tem*10)+key;
if((i==0 || i==1) && tem>59) tem=59;//确保修改的数据不超出限制,
if((i==2 ) && tem>23) tem=23; //比如分不能超过60,月不能超过12等。
if(i==3 && tem>31) tem=31; //如超过限制,则定为最大
if(i==4 && tem>12) tem=12;
if(i==5 && tem>7)
{
if(key<=6 && key!=0)tem=key;
else tem=6;
}
delay(200);
key=16;
}
if(key==12 )break; //确定
if(key==13) //取消
{
tem/=10;
key=16;
delay(200);
}
if(key==14)return; //退出
if(temp_time!=tem)
{
LCD_write_char(8,1,' '); //实时显示修改的数据
if(i==6)
{
LCD_write_int(9,1,20);
LCD_en_dat(tem/10+0x30);
LCD_en_dat(tem%10+0x30);
}
else
{
LCD_write_int(10,1,tem/10);
LCD_write_int(11,1,tem%10);
}
temp_time=tem;
}
delay(100);
get_ds1302();
LCD_write_string(0,1,"Now: ");
if(i==0) //显示秒
{
LCD_write_int(4,1,led[1]);
LCD_write_int(5,1,led[0]);
}
}
//for(i=0;i<7;i++)
// {
// times[i]=itime[i];
// }
get_ds1302();
// led[1]=tem/10;
// led[0]=tem%10;
times[0]=tem;
set_ds1302(0x80,×[0]);
}
}
//*************************************************
void main() //主函数
{
uchar i=0;
init_ds1302();
LCD_init();
set_ds1302(0x80,×);
//for(i=0;i<7;i++)
// {
// times[i]=itime[i];
// }
while(1)
{
get_ds1302(); //读ds1302的时间
cover();
key_scan(); //扫描键盘
if(key<7) //如果键盘值小于7则进入修改界面
{
change_time(key);
key=16;
}
delay(30);
alarm_speaker=1;
delay(170);
read_temp(); //读出18B20温度数据
work_temp(); //处理温度数据
display_dat();//显示时间和温度
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -