实现的功能:密码锁,红外控制,温度计功能等
连线:键盘接P0,P2接数码管,接上LCD,P1.0接蜂鸣器,P1.2-P1.7接步进电机
C程序:
#include
#include
typedef unsigned int uint;
typedef unsigned char uchar;
bit FlagC=1; //接受和发送的标志位
sbit P10=P1^0; //控制蜂鸣器响
sbit IRIN = P3^2; //红外接收器数据线
uchar IRCOM[7];
uint nn=11;//用来判断红外发送的信号是数字几
//////温度液晶////////////////
typedef bit BOOL;
sbit DQ = P3 ^ 7;
uchar Temp_Value[] = { 0x00, 0x00 };
uchar Display_Digit[] = { 0, 0, 0, 0 };
sbit LCD_RW = P2 ^ 5; //写数据?
sbit LCD_RS = P2 ^ 6;
sbit LCD_EP = P2 ^ 7; //使能?
uchar num;
int temper = 0;
int CurrentT = 0;
bit flag;
void delayT(uchar t) {
while (t--)
;
}
void init_ds18b20() {
// uchar n;
DQ = 1;
_nop_();
DQ = 0;
delayT(80);
_nop_();
DQ = 1;
delayT(14);
_nop_();
_nop_();
_nop_();
if (DQ == 0)
flag = 1; //detect 1820 success!
else
flag = 0; //detect 1820 fail!
delayT(20); //20
_nop_();
_nop_();
DQ = 1;
}
void write_byte(uchar dat) {
uchar i;
for (i = 0; i < 8; i++) {
DQ = 0;
_nop_();
DQ = dat & 0x01; //从最低位开始写
delayT(3);
_nop_();
_nop_();
DQ = 1;
dat >>= 1;
}
// delay(4);
}
uchar read_byte() {
uchar i, value = 0;
for (i = 0; i < 8; i++) {
DQ = 0;
value >>= 1;
DQ = 1;
if (DQ)
value |= 0x80;
delayT(2);
_nop_();
}
return value;
}
int readtemperature() {
uchar templ, temph;
// int temp;
init_ds18b20();
write_byte(0xcc); //跳过ROM
write_byte(0x44); //启动温度测量
delayT(300);
init_ds18b20();
write_byte(0xcc);
write_byte(0xbe);
// Temp_Value[0] = ReadOneByte();
// Temp_Value[1] = ReadOneByte();
templ = read_byte();
temph = read_byte();
//CurrentT = ((templ&0xf0)>>4) | ((temph&0x07)<<4);
CurrentT = temph*256 +templ;
CurrentT = CurrentT * 62.5;
return CurrentT;
}
/****************侧忙函数************************/
BOOL lcd_bz() {
BOOL result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (BOOL) (P0 & 0x80); //检测P0最高位是否为1
LCD_EP = 0;
return result;
}
/****************写命令函数************************/
void write_com(uchar cmd) {
while (lcd_bz())
;
LCD_RS = 0;
LCD_RW = 0;
// LCD_EP = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
}
void lcd_pos(uchar pos) {
write_com(pos | 0x80);
}
/****************写数据函数************************/
void write_data(uchar dat) { //写入字符显示数据到LCD
while (lcd_bz())
;
LCD_RS = 1;
LCD_RW = 0;
// LCD_EP = 0;
_nop_();
_nop_();
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
}
void initT() {
// dula=0;
// wela=0;
LCD_EP = 0;
write_com(0x38); //16*2显示
write_com(0x0e); //开显示;显示光标,光标不闪烁
write_com(0x06); //光标自动增加111
write_com(0x01); //显示清屏
// write_com(0x80+0x10);
}
//////////////////////////////
unsigned int ReData;
uchar num=0;
const char Message[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; //要发送的数据
char Get_Mes[8]={0x03}; //获取到的数据
uchar i=0;
uchar Chose;//判断选择哪一个功能选项
//此表为 LED 的字模, 共阴数码管 0-F
uchar code LEDMAP[] = {~0x3f, ~0x06, ~0x5b, ~0x4f, ~0x66, ~0x6d, ~0x7d, ~0x07,~0x7f, ~0x6f, ~0x77, ~0x7c, ~0x39, ~0x5e, ~0x79, ~0x71}; //段码控制
uint LEDN[16];
int n=0;
void delay(uint);
void Send_data(char p[]) //发送数据
{
uchar i;
for(i=0;i<1;i++)
{
SBUF = p[i]; //SUBF接受/发送缓冲器(又叫串行通信特殊功能寄存器)
while(!TI); // 等特数据传送 (TI发送中断标志)
TI = 0; // 清除数据传送标志
}
}
void zhuanhuan(char c) //将PC传过来的16进制数转化成对应的十进制数
{
switch(c)
{
case 0x00:
{
LEDN[0]=0;
break;
}
}
}
void Get_data(char p[]) //接受数据到数组中
{
i=i%8;
i++;
P2=LEDMAP[SBUF];
p[i]=P2;
FlagC=1;
while(!RI); // 等特数据传送 (TI发送中断标志)
RI = 0; // 清除数据传送标志
}
//返回一个选择项
char Get_Chose()
{
return SBUF;
}
void delay(uint z)
{
uchar j;
for(z;z>0;z--)
for(j=0;j<200;j++)
;
}
void init()
{
SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1
PCON|= 0x80;
TMOD|= 0x20; //定时器工作方式2
TH1 = 0xF3; // //baud*2 /* 波特率4800、数据位8、停止位1。效验位无 (12M)
TL1 = 0xF3;
TR1 = 1;
ES = 1; //开串口中断
EA = 1; // 开总中断
}
//蜂鸣器响
void beep(uint t)
{
uint time=0;
for(time;time { P10=1; delay(100); P10=0; delay(100); } } /////////红外////////////////// void beeph() { unsigned char i; for (i=0;i<100;i++) { delay(4); P10=!P10; //BEEP取反 } P10=1; //关闭蜂鸣器 } void delayh(unsigned char x) //x*0.14MS { unsigned char i; while(x--) { for (i = 0; i<13; i++) {} } } void delay1h(int ms) { unsigned char y; while(ms--) { for(y = 0; y<250; y++) { _nop_(); _nop_(); _nop_(); _nop_(); } } } void IR_IN() interrupt 0 using 0 { unsigned char j,k,N=0; EX0 = 0; delayh(15); if (IRIN==1) { EX0 =1; return; } //确认IR信号出现 while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。 {delayh(1);} for (j=0;j<4;j++) //收集四组数据 { for (k=0;k<8;k++) //每组数据有8位 { while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。 {delayh(1);} while (!IRIN) //等 IR 变为高电平 {delayh(1);} while (IRIN) //计算IR高电平时长 { delayh(1); N++; if (N>=30) { EX0=1; return;} //0.14ms计数过长自动离开。 } //高电平计数完毕 IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0” if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1” N=0; }//end for k }//end for j if (IRCOM[2]!=~IRCOM[3]) { EX0=1; return; } IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位 IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位 if(IRCOM[5]>9) { IRCOM[5]=IRCOM[5]+0x37;} else IRCOM[5]=IRCOM[5]+0x30; if(IRCOM[6]>9) { IRCOM[6]=IRCOM[6]+0x37;} else IRCOM[6]=IRCOM[6]+0x30; //将红外信号转换成数字 if(IRCOM[6]=='4'&&IRCOM[5]=='5') { nn=10;//关闭 } if(IRCOM[6]=='1'&&IRCOM[5]=='6') { nn=0; } if(IRCOM[6]=='0'&&IRCOM[5]=='C') { nn=1; } if(IRCOM[6]=='1'&&IRCOM[5]=='8') { nn=2; } if(IRCOM[6]=='5'&&IRCOM[5]=='E') { nn=3; } if(IRCOM[6]=='0'&&IRCOM[5]=='8') { nn=4; } if(IRCOM[6]=='1'&&IRCOM[5]=='C') { nn=5; } if(IRCOM[6]=='5'&&IRCOM[5]=='A') { nn=6; } if(IRCOM[6]=='4'&&IRCOM[5]=='2') { nn=7; } if(IRCOM[6]=='5'&&IRCOM[5]=='2') { nn=8; } if(IRCOM[6]=='4'&&IRCOM[5]=='A') { nn=9;//关闭 } beeph(); EX0 = 1; } ///////////////////////////////// void main (void) { init(); Chose=Get_Chose(); if(Chose=='0') //chose为0的时候是悬空状态 { P2=LEDMAP[0]; delay(5000); } if(Chose=='P') { while(1) { if(P2!=~0x5e) //如果按下的不是d(退出键),则继续,如果是d(退出键),则退出,继续选择其他的功能 { if (FlagC==1) { Send_data(Message); FlagC=0; } else { Get_data(Get_Mes); //beeph(); FlagC=1; } } else { P2=0x00; break; } } } if(Chose=='T') { initT(); while (1) { temper = readtemperature(); lcd_pos(0); if (temper < 0) { write_data('-'); temper = 0 - temper; } else write_data('+'); lcd_pos(1); write_data((temper) / 10000 + 0x30); lcd_pos(2); write_data(((temper) % 10000 )/ 1000 + 0x30); lcd_pos(3); write_data('.'); lcd_pos(4); write_data(((temper) % 10000 % 1000 )/ 100 + 0x30); lcd_pos(5); write_data(((temper) %10000 %1000 % 100 )/10 + 0x30); /*lcd_pos(6); write_data((temper) %10000 %1000 % 100 % 10 + 0x30); */ lcd_pos(6); write_data(0xdf); lcd_pos(7); write_data('C'); if(Chose!='T') { /* uint jj=0; for(jj;jj<8;jj++) { write_data(' '); } */ break; } } } if(Chose=='R') //红外控制 { /*P2=LEDMAP[1]; delay(5000); */ IRIN=1;//初始化红外P3.2 P10=1;//初始化蜂鸣器 delay1h(10); IE = 0x81; //允许总中断中断,使能 INT0 外部中断 TCON = 0x01; //触发方式为脉冲负边沿触发 nn=0; P2=LEDMAP[nn]; while(1) { if(nn==10) { EA=0;//关闭中断 break; } else{ P2=LEDMAP[nn]; } if(Chose!='R') {break;} } } } /**************************************************** 串口中断程序 ******************************************************/ void ser_int (void) interrupt 4 using 1 { } 复制代码 复制代码 #include #include typedef unsigned int uint; typedef unsigned char uchar; bit FlagC=1; //接受和发送的标志位 sbit P10=P1^0; //控制蜂鸣器响 sbit IRIN = P3^2; //红外接收器数据线 uchar IRCOM[7]; uint nn=11;//用来判断红外发送的信号是数字几 //////温度液晶//////////////// typedef bit BOOL; sbit DQ = P3 ^ 7; uchar Temp_Value[] = { 0x00, 0x00 }; uchar Display_Digit[] = { 0, 0, 0, 0 }; sbit LCD_RW = P2 ^ 5; //写数据? sbit LCD_RS = P2 ^ 6; sbit LCD_EP = P2 ^ 7; //使能? uchar num; int temper = 0; int CurrentT = 0; bit flag; void delayT(uchar t) { while (t--) ; } void init_ds18b20() { // uchar n; DQ = 1; _nop_(); DQ = 0; delayT(80); _nop_(); DQ = 1; delayT(14); _nop_(); _nop_(); _nop_(); if (DQ == 0) flag = 1; //detect 1820 success! else flag = 0; //detect 1820 fail! delayT(20); //20 _nop_(); _nop_(); DQ = 1; } void write_byte(uchar dat) { uchar i; for (i = 0; i < 8; i++) { DQ = 0; _nop_(); DQ = dat & 0x01; //从最低位开始写 delayT(3); _nop_(); _nop_(); DQ = 1; dat >>= 1; } // delay(4); } uchar read_byte() { uchar i, value = 0; for (i = 0; i < 8; i++) { DQ = 0; value >>= 1; DQ = 1; if (DQ) value |= 0x80; delayT(2); _nop_(); } return value; } int readtemperature() { uchar templ, temph; // int temp; init_ds18b20(); write_byte(0xcc); //跳过ROM write_byte(0x44); //启动温度测量 delayT(300); init_ds18b20(); write_byte(0xcc); write_byte(0xbe); // Temp_Value[0] = ReadOneByte(); // Temp_Value[1] = ReadOneByte(); templ = read_byte(); temph = read_byte(); //CurrentT = ((templ&0xf0)>>4) | ((temph&0x07)<<4); CurrentT = temph*256 +templ; CurrentT = CurrentT * 62.5; return CurrentT; } /****************侧忙函数************************/ BOOL lcd_bz() { BOOL result; LCD_RS = 0; LCD_RW = 1; LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_(); result = (BOOL) (P0 & 0x80); //检测P0最高位是否为1 LCD_EP = 0; return result; } /****************写命令函数************************/ void write_com(uchar cmd) { while (lcd_bz()) ; LCD_RS = 0; LCD_RW = 0; // LCD_EP = 0; _nop_(); _nop_(); P0 = cmd; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 0; } void lcd_pos(uchar pos) { write_com(pos | 0x80); } /****************写数据函数************************/ void write_data(uchar dat) { //写入字符显示数据到LCD while (lcd_bz()) ; LCD_RS = 1; LCD_RW = 0; // LCD_EP = 0; _nop_(); _nop_(); P0 = dat; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 0; } void initT() { // dula=0; // wela=0; LCD_EP = 0; write_com(0x38); //16*2显示 write_com(0x0e); //开显示;显示光标,光标不闪烁 write_com(0x06); //光标自动增加111 write_com(0x01); //显示清屏 // write_com(0x80+0x10); } ////////////////////////////// unsigned int ReData; uchar num=0; const char Message[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; //要发送的数据 char Get_Mes[8]={0x03}; //获取到的数据 uchar i=0; uchar Chose;//判断选择哪一个功能选项 //此表为 LED 的字模, 共阴数码管 0-F uchar code LEDMAP[] = {~0x3f, ~0x06, ~0x5b, ~0x4f, ~0x66, ~0x6d, ~0x7d, ~0x07,~0x7f, ~0x6f, ~0x77, ~0x7c, ~0x39, ~0x5e, ~0x79, ~0x71}; //段码控制 uint LEDN[16]; int n=0; void delay(uint); void Send_data(char p[]) //发送数据 { uchar i; for(i=0;i<1;i++) { SBUF = p[i]; //SUBF接受/发送缓冲器(又叫串行通信特殊功能寄存器) while(!TI); // 等特数据传送 (TI发送中断标志) TI = 0; // 清除数据传送标志 } } void zhuanhuan(char c) //将PC传过来的16进制数转化成对应的十进制数 { switch(c) { case 0x00: { LEDN[0]=0; break; } } } void Get_data(char p[]) //接受数据到数组中 { i=i%8; i++; P2=LEDMAP[SBUF]; p[i]=P2; FlagC=1; while(!RI); // 等特数据传送 (TI发送中断标志) RI = 0; // 清除数据传送标志 } //返回一个选择项 char Get_Chose() { return SBUF; } void delay(uint z) { uchar j; for(z;z>0;z--) for(j=0;j<200;j++) ; } void init() { SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1 PCON|= 0x80; TMOD|= 0x20; //定时器工作方式2 TH1 = 0xF3; // //baud*2 /* 波特率4800、数据位8、停止位1。效验位无 (12M) TL1 = 0xF3; TR1 = 1; ES = 1; //开串口中断 EA = 1; // 开总中断 } //蜂鸣器响 void beep(uint t) { uint time=0; for(time;time { P10=1; delay(100); P10=0; delay(100); } } /////////红外////////////////// void beeph() { unsigned char i; for (i=0;i<100;i++) { delay(4); P10=!P10; //BEEP取反 } P10=1; //关闭蜂鸣器 } void delayh(unsigned char x) //x*0.14MS { unsigned char i; while(x--) { for (i = 0; i<13; i++) {} } } void delay1h(int ms) { unsigned char y; while(ms--) { for(y = 0; y<250; y++) { _nop_(); _nop_(); _nop_(); _nop_(); } } } void IR_IN() interrupt 0 using 0 { unsigned char j,k,N=0; EX0 = 0; delayh(15); if (IRIN==1) { EX0 =1; return; } //确认IR信号出现 while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。 {delayh(1);} for (j=0;j<4;j++) //收集四组数据 { for (k=0;k<8;k++) //每组数据有8位 { while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。 {delayh(1);} while (!IRIN) //等 IR 变为高电平 {delayh(1);} while (IRIN) //计算IR高电平时长 { delayh(1); N++; if (N>=30) { EX0=1; return;} //0.14ms计数过长自动离开。 } //高电平计数完毕 IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0” if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1” N=0; }//end for k }//end for j if (IRCOM[2]!=~IRCOM[3]) { EX0=1; return; } IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位 IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位 if(IRCOM[5]>9) { IRCOM[5]=IRCOM[5]+0x37;} else IRCOM[5]=IRCOM[5]+0x30; if(IRCOM[6]>9) { IRCOM[6]=IRCOM[6]+0x37;} else IRCOM[6]=IRCOM[6]+0x30; //将红外信号转换成数字 if(IRCOM[6]=='4'&&IRCOM[5]=='5') { nn=10;//关闭 } if(IRCOM[6]=='1'&&IRCOM[5]=='6') { nn=0; } if(IRCOM[6]=='0'&&IRCOM[5]=='C') { nn=1; } if(IRCOM[6]=='1'&&IRCOM[5]=='8') { nn=2; } if(IRCOM[6]=='5'&&IRCOM[5]=='E') { nn=3; } if(IRCOM[6]=='0'&&IRCOM[5]=='8') { nn=4; } if(IRCOM[6]=='1'&&IRCOM[5]=='C') { nn=5; } if(IRCOM[6]=='5'&&IRCOM[5]=='A') { nn=6; } if(IRCOM[6]=='4'&&IRCOM[5]=='2') { nn=7; } if(IRCOM[6]=='5'&&IRCOM[5]=='2') { nn=8; } if(IRCOM[6]=='4'&&IRCOM[5]=='A') { nn=9;//关闭 } beeph(); EX0 = 1; } ///////////////////////////////// void main (void) { init(); Chose=Get_Chose(); if(Chose=='0') //chose为0的时候是悬空状态 { P2=LEDMAP[0]; delay(5000); } if(Chose=='P') { while(1) { if(P2!=~0x5e) //如果按下的不是d(退出键),则继续,如果是d(退出键),则退出,继续选择其他的功能 { if (FlagC==1) { Send_data(Message); FlagC=0; } else { Get_data(Get_Mes); //beeph(); FlagC=1; } } else { P2=0x00; break; } } } if(Chose=='T') { initT(); while (1) { temper = readtemperature(); lcd_pos(0); if (temper < 0) { write_data('-'); temper = 0 - temper; } else write_data('+'); lcd_pos(1); write_data((temper) / 10000 + 0x30); lcd_pos(2); write_data(((temper) % 10000 )/ 1000 + 0x30); lcd_pos(3); write_data('.'); lcd_pos(4); write_data(((temper) % 10000 % 1000 )/ 100 + 0x30); lcd_pos(5); write_data(((temper) %10000 %1000 % 100 )/10 + 0x30); /*lcd_pos(6); write_data((temper) %10000 %1000 % 100 % 10 + 0x30); */ lcd_pos(6); write_data(0xdf); lcd_pos(7); write_data('C'); if(Chose!='T') { /* uint jj=0; for(jj;jj<8;jj++) { write_data(' '); } */ break; } } } if(Chose=='R') //红外控制 { /*P2=LEDMAP[1]; delay(5000); */ IRIN=1;//初始化红外P3.2 P10=1;//初始化蜂鸣器 delay1h(10); IE = 0x81; //允许总中断中断,使能 INT0 外部中断 TCON = 0x01; //触发方式为脉冲负边沿触发 nn=0; P2=LEDMAP[nn]; while(1) { if(nn==10) { EA=0;//关闭中断 break; } else{ P2=LEDMAP[nn]; } if(Chose!='R') {break;} } } } /**************************************************** 串口中断程序 ******************************************************/ void ser_int (void) interrupt 4 using 1 { }
上一篇:按键数码管数值前移
下一篇:利用外部中断和时间中断计数0-999显示在数码管上
推荐阅读最新更新时间:2024-03-16 15:31