醍醐灌顶的东西(搬运自我的笔记,所以有些格式不是太完美)
大家注意:只有P0口需要外界上拉电阻(内部结构决定的),其他口不加也能仿真出结果
一、 流水灯代码
1. 最初版本
#include <reg51.h>
void delay(unsigned int time) //定义延时函数
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--); //用两个循环是为了保证延时函数的正确性
}
void main (void)
{
while (1)
{
P1=0xfe;
delay(1000);
P1=0xfd;
delay(1000);
P1=0xfb;
delay(1000);
P1=0xf7;
delay(1000);
P1=0xef;
delay(1000);
P1=0xdf;
delay(1000);
P1=0xbf;
delay(1000);
P1=0x7f;
delay(1000);
}
}
2. 简化版本
#include <reg51.h>
#include <intrins.h>
void delay(unsigned int time) //定义延时函数
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--); //用两个循环是为了保证延时函数的正确性
}
void main()
{
P1=0x7f;
while (1)
{
P1=_crol_(P1,1); //P1的值整体左移一位
delay(1000);
}
}
3. Proteus仿真图
二、 外部中断代码
1. 最初版本
#include <reg51.h>
sbit KEY = P3^3; //外部中断1是P3.3
unsigned int i,j,k,m,n; //说一下这个unsigned吧,无符号型,也就是从0开始,没有负数
void IntInit() //定义中断
{
IT1 = 1; //设置外部中断1的触发方式 1是下降沿 0是低电平
EX1= 1; //打开外部中断1
EA = 1; //打开总中断开关
}
void delay() //定义1s延时函数
{
for(m=200;m>0;m--)
for(n=500;n>0;n--);
}
void Delay10s() //定义10s延时函数
{
unsigned char i=58, j=3, k=227;
do
{
do
{
while (--k);
}
while (--j);
}
while (--i);
}
void main()
{
IntInit(); //对中断进行声明
while (1) //流水灯程序
{
P1=0xfe;
delay();
P1=0xfd;
delay();
P1=0xfb;
delay();
P1=0xf7;
delay();
P1=0xef;
delay();
P1=0xdf;
delay();
P1=0xbf;
delay();
P1=0x7f;
delay();
}
}
void Int () interrupt 2 //外部中断1 中断号是2
{
if(KEY==0) //判断P3.3口是否被按下
P1=~P1; //取反
Delay10s(); //延时10s钟
}
2. 修改建议
这里咱们用的是外部中断1 也就是传说中的 INT1,如果用外部中断0(INT0)的话,需要修改的地方有:
代码部分:
sbit KEY = P3^3; //外部中断1是P3.3 第2行
IT1 = 1; //设置外部中断1的触发方式 第7行
EX1= 1; //打开外部中断1 第8行
void Int() interrupt 2 //外部中断1 中断号是2 第55行
sbit KEY = P3^2; //外部中断0是P3.2 第2行
IT0= 1; //设置外部中断0的触发方式 第7行
EX0= 1; //打开外部中断0 第8行
void Int() interrupt 0 //外部中断0 中断号是0 第55行
原理图部分:
把proteus中按钮的引脚从P3.3改到P3.2
3. 简化版本
这个版本有个小问题,就是按键按下去之后,不会自己恢复,需要重新按键才会回到正常程序运行,再研究一下有没有好的解决方案(感觉是延时和中断出冲突了,但是没有找到问题所在😢)
键抖也考虑一下
已经解决掉😍
#include <reg51.h>
#include <intrins.h>
sbit KEY = P3^3; //外部中断1是P3.3
unsigned int i,j,k;
void delay( unsigned int i) //定义延时函数
{
unsigned char j=3, k=227;
do
{ do
{ while (--k);
}
while (--j);
}
while (--i);
}
void main()
{
IT1 = 1;
EX1= 1;
EA = 1;
P1=0x7f;
while (1)
{
P1=_crol_(P1,1); //P1的值整体左移一位
delay(10);
}
}
void Int() interrupt 2
{
if(KEY==0)
P1=~P1;
delay(60);//延时10s
if(KEY==1)
P1=~P1;
}
4. Proteus仿真图
三、 定时器代码
1. 最初版本
#include <reg51.h> //51头文件
unsigned char count=0,num=0; //定义两个无符号字符型变量
unsigned char code led[]=
{0xfa,0xf5,0xaf,0x5f,0xaa,0x55,0x00,0xff};
//对每种情况进行声明,前两个分别是1 3亮,2 4亮,后面以此类推,和题目保持一致
void main()
{
TMOD=0X10;//这里用的是高四位,如果是低四位是0x01
TH1=0X3C; //2^16-50ms/1us 65536-50000=15536 十六进制是3CB0H 这是高位
TL1=0XB0; //这是低位(上面用50ms参与运算是因为题目中说每隔0.05s T1溢出一次)
EA=1; //打开总中断开关
ET1=1; //打开定时器1的中断,0是定时器1不中断
TR1=1; //定时器1工作,0是不工作
while(1) //超循环
{
P1=led[num]; //用总线运算点亮P1端口的led
}
}
void Timer() interrupt 3 using 0 //using 0可以省略,这个是中断函数.
//interrupt后面是中断号3,是因为中断源符号是T1,如果是T0,后面中断号3换成1
{
TH1=0X3C; //2^16-50ms/1us 65536-50000=15536 十六进制是3CB0H 这是高位
TL1=0XB0; //这是低位(上面用50ms参与运算是因为题目中说每隔0.05s T1溢出一次)
count++; //每中断一次 count+1
if(count==20)// 20*50ms正好是一秒种
{
count=0; //让count归零,方便下次中断计数
num++; //中断完成,返回主函数,继续执行main函数,即是 让led按照预定程序改变亮灯方式
if(num==8)
num=0;
}
}
2. 修改建议
这里咱们用的是定时器1 也就是传说中的 T1,如果用定时器0(T0)的话,需要修改的地方有:
代码部分:
TMOD=0X10; //设置定时器1工作方式为01(传说中的方式1) TMOD是工作方式寄存器
TH1=0X3C; //写入T1的高位初值
TL1=0XB0; //写入T1的低位初值
EA=1; //开总中断
ET1=1;//开定时器1中断
TR1=1;//启动定时器1
void Timer() interrupt 3 using 0 //T1的中断号是3
TMOD=0X01; //设置定时器1工作方式为01 TMOD是工作方式寄存器 第8行
TH0=0X3C; //写入T0的高位初值 第9行
TL0=0XB0; //写入T0的低位初值 第10行
EA=1; //开总中断 😎这行不用改
ET0=1;//开定时器0中断 第12行
TR0=1;//启动定时器0 第13行
void Timer() interrupt 1 using 0 //T0的中断号是1 第19行
2.无注释代码 (其实也有一点儿😊)
#include <reg51.h>
unsigned char count=0,num=0;
unsigned char code led[]=
{0xfa,0xf5,0xaf,0x5f,0xaa,0x55,0x00,0xff};
void main()
{
TMOD=0X10;
TH1=0X3C; //也可写为(65536-50000/256
TL1=0XB0; //也可写为(65536-50000)%256
EA=1;
ET1=1;
TR1=1;
while(1)
{
P1=led[num];
}
}
void Timer() interrupt 3 using 0
{
count++;
if(count==20)
{
count=0;
num++;
if(num==8)
num=0;
}
}
3. Proteus仿真图
四、 数码管代码
这里给出共阴极数码管0~9,和部分字母的显示十六进制数😉
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x37, //"n"
0x3E, //"u"
0x73, //"P"
0x5C, //"o"
0x40, //"-"
0x00 //熄灭
按照题目要求
只需修改下列代码第四行 { } 内的十六进制数就行😋
cc是共阴极数码管,ca是共阳极数码管
1. 最初版本
#include <reg51.h>
unsigned char cnt=0;
unsigned char code table[]=
{0x5b,0x5b,0x6f,0x5b,0x06,0x6d}; //229215 共阴极数码管
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void main(void)
{
P2=table[cnt];
while (1)
{
P2=table[cnt];
delay(50);
P2=0x00; //数组中的数全部显示一遍后,将数码管熄灭
delay(50);
cnt++;
if(cnt==6) //判断数组中的数据是否溢出,溢出则清零显示
{ cnt=0;delay(200);}
}
}
2. Proteus仿真图
五、 独立按键代码
1. 最初版本
#include <reg51.h>
sbit P1_4=P1^4;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P1_7=P1^7;
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void main(void)
{
P0=0x00; // 熄灯
P2=0x00; //熄灯
P3=0x00; //熄灯
while (1)
{
if(P1_4==0)
{ delay(10); //按下去键抖
P0=0x3E; // U
P2=0x73; // P
P3=0x06; //1
while(P1_4==0) ;//松手去键抖
delay(10);
}
if(P1_5==0)
{ delay(10); //去键抖
P0=0x5E; //D
P2=0x5C;//O
P3=0x5B; //2
while(P1_5==0);
delay(10);
}
if(P1_6==0)
{ delay(10); //去键抖
P0=0x38; // L
P2=0x79; // E
P3=0x4F;//3
while(P1_6==0);
delay(10);
}
if(P1_7==0)
{ delay(10); //去键抖
P0=0x77; // R
P2=0x06; // I
P3=0x66;//4
while(P1_7==0);
delay(10);
}
}
}
2. 简化版本
这个版本有个小问题,初始状态会默认按键1按下,但是不影响后续结果,符合题目要求。
#include <reg51.h>
unsigned char cnt=0;
unsigned char code LED1[]={0x3E,0x5E,0x38,0x77};
unsigned char code LED2[]={0x73,0x5C,0x79,0x06};
unsigned char code LED3[]={0x06,0x5B,0x4F,0x66};
sbit P1_4=P1^4;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P1_7=P1^7;
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void main()
{
while (1)
{
switch(P1)
{case(0xef):cnt=0;break; //按键1按下
case(0xdf):cnt=1;break; //按键2按下
case(0xbf):cnt=2;break; //按键3按下
case(0x7f):cnt=3;break; //按键4按下
}
delay(20); //去按下键抖
P0=LED1[cnt];
P2=LED2[cnt];
P3=LED3[cnt];
while(0); //去松手键抖
delay(20);
}
}
3. Proteus仿真图
4. 调试版本(有错误,仅供展览)
#include <reg51.h>
unsigned char cnt=0;
unsigned char code LED1[0x3E,0x5E,0x38,0x77];
unsigned char code LED2[0x73,0x5C,0x79,0x06];
unsigned char code LED3[0x06,0x5B,0x4F,0x66];
sbit P1_4=P1^4;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P1_7=P1^7;
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void main(void)
{
P0=P1=P2=0x00;
switch(k)
{
case 0:cnt=0;
case 1:cnt=1;
case 2:cnt=2;
case 3:cnt=3;
}
while (1)
{
P0=LED1[cnt];
P2=LED2[cnt];
P3=LED3[cnt];
}
}
unsigned char code LED1[]={0x3E,0x5E,0x38,0x77,0x00};
unsigned char code LED2[]={0x73,0x5C,0x79,0x06,0x00};
unsigned char code LED3[]={0x06,0x5B,0x4F,0x66,0x00};
#include <reg51.h>
#define uchar unsigned char;
#define uint unsigned int;
uchar num=0;
uchar code table[]={0x3F,0x06, 0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
void delay(unsigned int time)
{
unsigned int i=120;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void key_scan()
{
unsigned char temp1=0,temp2=0,temp=0;
P1=0xf0;
if(P1!=0xf0)
{
delay(20);
temp1=P1;
P1=0x0f;
if(P1!=0x0f)
{
delay(20);
temp2=P1;
}
}
temp=temp1+temp2;
if(temp==0xee)
{
num=0;
}
}
void main(void)
{
while(1)
{
key_scan();
P2=table[num];
}
}
六、 矩阵按键代码
1. 最初版本
#include <reg51.h>
unsigned char num=99; //让LED初始为熄灭状态
unsigned char code table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void key_scan() //按键扫描
{
unsigned char temp0=0,temp1=0,temp;
P1=0xf0;
if(P1!=0xf0) //检测按键是否被按下
{
delay(20);
temp0=P1;
P1=0x0f;
if(P1!=0x0f)
{
temp1=P1;
}
}
temp=temp0+temp1;
if(temp==0xee)
{ num=0;}
if(temp==0xed)
{ num=1;}
if(temp==0xeb)
{ num=2;}
if(temp==0xe7)
{ num=3;}
if(temp==0xde)
{ num=4;}
if(temp==0xdd)
{ num=5;}
if(temp==0xdb)
{ num=6;}
if(temp==0xd7)
{ num=7;}
if(temp==0xbe)
{ num=8;}
if(temp==0xbd)
{ num=9;}
if(temp==0xbb)
{ num=10;}
if(temp==0xb7)
{ num=11;}
if(temp==0x7e)
{ num=12;}
if(temp==0x7d)
{ num=13;}
if(temp==0x7b)
{ num=14;}
if(temp==0x77)
{ num=15;}
}
void display()
{
P2=table[num];
}
void main()
{
while(1)
{
key_scan();
display();
}
}
2. 简化版本
#include <reg51.h>
unsigned char num=99;
unsigned char code table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void key_scan()
{
unsigned char temp0=0,temp1=0,temp;
P1=0xf0;
if(P1!=0xf0)
{
delay(20);
temp0=P1;
P1=0x0f;
if(P1!=0x0f)
{ temp1=P1; }
}
temp=temp0+temp1;
switch(temp)
{
case(0xee):num=0;break;
case(0xed):num=1;break;
case(0xeb):num=2;break;
case(0xe7):num=3;break;
case(0xde):num=4;break;
case(0xdd):num=5;break;
case(0xdb):num=6;break;
case(0xd7):num=7;break;
case(0xbe):num=8;break;
case(0xbd):num=9;break;
case(0xbb):num=10;break;
case(0xb7):num=11;break;
case(0x7e):num=12;break;
case(0x7d):num=13;break;
case(0x7b):num=14;break;
case(0x77):num=15;break;
}}
void main()
{
while(1)
{
key_scan();
P2=table[num];
}
}
3. Proteus仿真图
七、 串行口代码
1. 最初版本
#include <reg51.h>
unsigned char flag=0;
unsigned char recdata=0;
void init_scon()
{
SCON=0x50; //0101 0000 工作方式1,没有多机通信,允许接受
TMOD=0x20; //0010 0000 8位定时器 定时器1(高四位) 定时模式
TH1=256-3; //波特率为9600
TL1=256-3;
EA=1; //打开总中断
ES=1; // 打开串口中断
TR1=1; //打开定时器1
}
void send_data() //发送数据
{
SBUF=recdata;
while(TI==0);
TI=0;
}
void main()
{
init_scon(); //初始化串口
while(1)
{
if(flag==1)
{
send_data();
flag=0;
}
}
}
void scon_interrupt() interrupt 4 //串口中断中断号是4,中断服务函数
{
recdata=SBUF; //接收的数据就是缓存寄存器中的数据
RI=0; //接收中断手动清0,等待下次中断
flag=1; //标志位
}
2. 无注释版本
#include <reg51.h>
unsigned char flag=0;
unsigned char recdata=0;
void init_scon()
{
SCON=0x50;
TMOD=0x20;
TH1=256-3;
TL1=256-3;
EA=1;
ES=1;
TR1=1;
}
void send_data()
{
SBUF=recdata;
while(TI==0);
TI=0;
}
void main()
{
init_scon();
while(1)
{
if(flag==1)
{
send_data();
flag=0;
}
}
}
void scon_interrupt() interrupt 4
{
recdata=SBUF;
RI=0;
flag=1;
}
3. Proteus仿真图
4. Proteus仿真现象
八、计数器代码
1. 最初版本
#include <reg51.h>
sbit key=P1^7;
unsigned char cnt 0;
unsigned char code table[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void main(void)
{
P0=P2=table[0];
while (1)
{
if(key==0)
{
cnt++;
if(cnt>=99)
cnt=0;
P0=table[cnt/10]; //取整
P2=table[cnt%10]; //取余
while(key==0);
}
}
}
2. Proteus仿真图
九、 流水灯拓展
1. 最初版本
#include <reg51.h>
unsigned char led[]={0xfe,0xfd,0xfb,0xf7}; // 默认从下往上点亮跑马灯
void delay(unsigned int time) //延时
{
unsigned int i=120;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void main()
{
bit dir=0,run=0;
char n;
while(1)
{
switch(P0&0x0f)
{
case 0x0e:run=1;break; //开始运行
case 0x0d:run=0,dir=0;break; //停止运行
case 0x0b:dir=1;break; //从上到下点亮
case 0x07:dir=0;break; //从下到上点亮
}
if(run==1)
if(dir==1)
for(n=0;n<=3;n++)
{ P2=led[n];
delay(200);
}
else
for(n=3;n>=0;n--)
{ P2=led[n];
delay(200);
}
else
P2=0xff; //熄灭所有灯
}
}
2. Proteus仿真图
十、 动态数码管拓展
1. 最初版本
#include <reg51.h>
unsigned char wei[]={ 0x01,0x02,0x04,0x08,0x10,0x20 };//位选码 1 2 3 4 5 6
unsigned char duan[]={ 0x5b,0x5b,0x6f,0x5b,0x06,0x6d };//段选码 2 2 9 2 1 5
void delay(unsigned int time) //延时
{
unsigned int i=120;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void pro() //子函数
{
int k=0;
for(k;k<6;k++)
{
P3=~wei[k]; //位选低电平有效
P2=duan[k];
delay(10);
}
}
void main()
{
while (1)
{
pro();
}
}
2. Proteus仿真图
3. 改进版本(减少IO口占用)
#include <reg51.h>
unsigned char wei[]={ 0x00,0x01,0x02,0x03,0x04,0x05 };
unsigned char duan[]={0x5b,0x5b,0x6f,0x5b,0x06,0x6d};
void delay(unsigned int time)
{
unsigned int i=120;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void pro()
{ int k=0;
for(k;k<6;k++)
{
P3=wei[k];
P2=duan[k];
delay(10);
}
}
void main()
{
while (1)
{
pro();
}
}
4. Proteus仿真图
十一、 LCD1602的初试及应用
1. 最初版本
#include <reg51.h>
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
unsigned char str[]={"what's u problem"};
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
P2=dat;
delay(5);
E=1;
E=0;
}
void display()
{
unsigned char i=0;
writecom(0x80+0x40);
while(str[i]!='\0')
{
writedat(str[i]);
delay(5);
i++;
}
writecom(0x80);
delay(5);
writedat('J');
delay(5);
writedat('L');
delay(5);
writedat('A');
delay(5);
writedat('U');
delay(5);
writedat(':');
delay(5);
}
void initlcd()
{
writecom(0x38);//设置16*2显示,5*7点阵,8位数据接口
writecom(0x0c); //设置开显示,不显示光标
writecom(0x06); //写一个字符后地址指针加1
writecom(0x01);//显示清零,数据指针清零
}
void main()
{
initlcd();
while(1)
{
display();
}
}
2. Proteus仿真图
3. Proteus仿真现象
十二、 简易示波器的制作
方波 锯齿波 正弦波 三角波 咱都能生成 还能调幅值和频率😢
1. 最初版本
#include <reg51.h>
unsigned int code sin[256]={0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,0x15,0x13,0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80}; //正弦表
sbit key0=P1^0;
sbit key1=P1^1;
sbit key2=P1^2;
sbit key3=P1^3;
sbit key4=P1^4;
sbit key5=P1^5;
unsigned int flag1=0,flag2=0,cnt=50,count=0;
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void square() //方波
{
unsigned int m;
for(m=0;m<=400;m++)
{
P2=0x00;
delay(40);
P2=0xff;
delay(cnt);
}
}
void sinwave() //正弦波
{ unsigned int i,m;
for(m=0;m<=100;m++)
{
for(i=0;i<255;i++)
P2=sin[i];
}
}
void sawtooth () //锯齿波
{
unsigned int i,m;
for(m=0;m<=50;m++)
{ for(i=0;i<=255;i++)
{
P2=i;
if(i==255)
P2=0;
}
}
}
void tri_wave() //三角波
{
unsigned int i,j,m;
for(m=0;m<=15;m++)
{
for(i=0;i<255;i++)
P2=i;
for(j=255;j>0;j--)
P2=j;
}
}
void key() //调整方波的频率
{
if(key4==0&&flag1==0)
flag1=1;
if(key4==1&&flag1==1)
{ cnt=cnt+10;
flag1=0;
}
if(key5==0&&flag2==0)
flag2=1;
if(key5==1&&flag2==1)
{ cnt=cnt-10;
flag2=0;
}
}
void main()
{
while(1)
{
key(); //默认刚仿真的时候可以调方波频率
P2=0x00;
delay(50);
P2=0xff;
delay(cnt);
switch(P1)
{
case(0xfe):square();break;
case(0xfd):sinwave();break;
case(0xfb):sawtooth();break;
case(0xf7):tri_wave();break;
}
}
}
2. 待调试版本
/*#include <reg51.h>
unsigned int code sin[256]={0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,0x15,0x13,0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80}; //正弦表
sbit key0=P1^0;
sbit key1=P1^1;
sbit key2=P1^2;
sbit key3=P1^3;
sbit key4=P1^4;
sbit key5=P1^5;
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
unsigned char data str1[]={"The time: "};
unsigned int flag1=0,flag2=0,cnt=50,count=0;
signed int hour=0,min=0,sec=0,week=1,k=0,i=0;
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void inittimer0() //定时器0初始化
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
void writecom(unsigned char com) //写命令
{
RS=0;
RW=0;
E=0;
P0=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat) //写数据
{
RS=1;
RW=0;
E=0;
P0=dat;
delay(5);
E=1;
E=0;
}
void square() //方波
{
unsigned int m;
for(m=0;m<=400;m++)
{
P2=0x00;
delay(50);
P2=0xff;
delay(cnt);
}
}
void sinwave() //正弦波
{ unsigned int i,m;
for(m=0;m<=100;m++)
{
for(i=0;i<255;i++)
P2=sin[i];
}
}
void sawtooth() //锯齿波
{
unsigned int i,m;
for(m=0;m<=50;m++)
{ for(i=0;i<=255;i++)
{
P2=i;
if(i==255)
P2=0;
}
}
}
void tri_wave()//三角波
{
unsigned int i,j,m;
for(m=0;m<=15;m++)
{
for(i=0;i<255;i++)
P2=i;
for(j=255;j>0;j--)
P2=j;
}
}
void key()
{
if(key4==0&&flag1==0)
flag1=1;
if(key4==1&&flag1==1)
{ cnt=cnt+10;
flag1=0;
}
if(key5==0&&flag2==0)
flag2=1;
if(key5==1&&flag2==1)
{ cnt=cnt-10;
flag2=0;
}
}
void initlcd() //初始化LCD1602
{
writecom(0x38); //设置16*2显示,5*7点阵,8位数据接口
writecom(0x0c); //设置开显示,不显示光标
writecom(0x06); //写一个字符后地址指针加1
writecom(0x01); //显示清零,数据指针清零
}
void display ()
{
unsigned char temp0=0,temp1=0,temp2=0,temp3=0,temp4=0,temp5=0;//如果不是int 是 char 还用不用加0x30
temp0=hour/10;
temp1=hour%10;
temp2=min/10;
temp3=min%10;
temp4=sec/10;
temp5=sec%10;
writecom(0x80+0x44);
delay(5);
writedat(temp0+0x30);
delay(5);
writedat(temp1+0x30);
delay(5);
writedat(':');
delay(5);
writedat(temp2+0x30);
delay(5);
writedat(temp3+0x30);
writedat(':');
delay(5);
writedat(temp4+0x30);
delay(5);
writedat(temp5+0x30);
delay(5);//等会儿全放到中断里弄试试
}
void initlcd() //初始化1602
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void main()
{ inittimer0();
initlcd();
while(1)
{
display ();
key();
// P2=0x00;
// delay(50);
// P2=0xff;
// delay(cnt);
// switch(P1)
//{
// case(0xfe):square();break;
// case(0xfd):sinwave();break;
// case(0xfb):sawtooth();break;
// case(0xf7):tri_wave();break;
//}
}
}
void timer0_isr() interrupt 1 //定时器0的中断函数
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20)
{ sec++; count=0; }
if(sec==60)
{ min++;sec=0; }
if(min==60)
{ hour++;min=0; }
if(hour==24)
{ week++; hour=0; }
if(week==8)
{week=1;}
}
*/
#include <reg51.h>
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;
sbit k6=P1^5;
unsigned char str[]={"Set up the time:"};
unsigned char str1[]={"The time:"};
unsigned char cnt=0,flag=0;
unsigned int hour=0,min=0,sec=0;
void delay(unsigned int time)
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
P0=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
P0=dat;
delay(5);
E=1;
E=0;
}
void inittimer0()
{ TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
void display ()
{
unsigned char temp0=0,temp1=0,temp2=0,temp3=0,temp4=0,temp5=0;//如果不是int 是 char 还用不用加0x30
temp0=hour/10;
temp1=hour%10;
temp2=min/10;
temp3=min%10;
temp4=sec/10;
temp5=sec%10;
writecom(0x80);
delay(5);
writedat(temp0+0x30);
delay(5);
writedat(temp1+0x30);
delay(5);
writedat(':');
delay(5);
writedat(temp2+0x30);
delay(5);
writedat(temp3+0x30);
writedat(':');
delay(5);
writedat(temp4+0x30);
delay(5);
writedat(temp5+0x30);
delay(5);//等会儿全放到中断里弄试试
}
void initlcd() //初始化1602
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void main()
{ inittimer0();
initlcd();
while(1)
{
display();
}
}
void timer0_isr() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
cnt++;
if(cnt==20)
{ sec++;
cnt=0;
}
if(sec==60)
{
min++;
sec=0;
}
if(min==60)
{
hour++;
min=0;
}
if(hour==24)
{
hour=0;
}
}
3. Proteus仿真图
十三、密码锁的制作(画饼中😢)
1. 最初版本
2. Proteus仿真图
十四、简易电子钟的制作(后期代码暂时不公开😎)
初期版本可以实现24小时制的日期显示,有需要的可以联系我加入星期 天 月 年和文字修饰和居中对齐。这样代码行数就多啦,看起来很高级😁
1. 最初版本(这个可以考虑用一下)
用这个的俺提供技术支持(PPT Visio word咱都可以参考)
#include <reg51.h>
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
unsigned char str[]={""};
unsigned char cnt=0;
unsigned int hour=0,min=0,sec=0; //设置初始时间
void delay(unsigned int time)
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
P2=dat;
delay(5);
E=1;
E=0;
}
void inittimer0()
{ TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
void display()
{
unsigned char temp0=0,temp1=0,temp2=0,temp3=0,temp4=0,temp5=0;//如果不是int 是 char 还用不用加0x30
temp0=hour/10;
temp1=hour%10;
temp2=min/10;
temp3=min%10;
temp4=sec/10;
temp5=sec%10;
writecom(0x80);
delay(5);
writedat(temp0+0x30);
delay(5);
writedat(temp1+0x30);
delay(5);
writedat(':');
delay(5);
writedat(temp2+0x30);
delay(5);
writedat(temp3+0x30);
writedat(':');
delay(5);
delay(5);
writedat(temp4+0x30);
delay(5);
writedat(temp5+0x30);
delay(5);//等会儿全放到中断里弄试试
}
void initlcd()
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void main()
{ inittimer0();
initlcd();
while(1)
{
display();
}
}
void timer0_isr() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
cnt++;
if(cnt==20)
{ sec++;
cnt=0;
}
if(sec==60)
{
min++;
sec=0;
}
if(min==60)
{
hour++;
min=0;
}
if(hour==24)
{
hour=0;
}
}
2. Proteus仿真图
3. 工程中后器期代码(这个俺用了)
#include <reg51.h>
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;
sbit k6=P1^5;
unsigned char str[]={"Set up the time:"};
unsigned char str1[]={"The time:"};
unsigned char cnt=0,flag=0;
unsigned int hour=0,min=0,sec=0;
void delay(unsigned int time)
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
P2=dat;
delay(5);
E=1;
E=0;
}
void inittimer0()
{ TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
void keys()
{
if(k1==0)
{
delay(10);
if(k1==0)//设置
{
ET0=0;
flag++;
if(flag==4)
flag=0;
}}
if(k2==0);//开始
{delay(10);
if(k2==0)
{ET0=1;}
while(k2==0);
}
if(k3==0);//停止
{
delay(10);
if(k3==0)
{ET0=0;}
while(k3==0);
}
if(k4==0);//清零
{
delay(10);
if(k4==0)
{hour=0;min=0;sec=0;ET0=0;}
while(k4==0);
}
if(k5==0) //加
{ delay(10);
if(k5==0)
{
if(flag==1)
{
hour++;
if(hour==60)
{
hour=0;
}
}
else if(flag==2)
{min++;
if(min==60)
{
min=0;
}
}
else if (flag==3)
{
sec++;
if(sec==60)
{
sec=0;
}
}
} while(k5==0);
}
if(k6==0) //减
{
delay(10);
if(k6==0)
{
if(flag==1)
{
hour--;
if(hour<0)
{hour=23;}
}
else if(flag==2)
{min--;
if(min<0)
{min=59;}
}
else if(flag==3)
{sec--;
if(sec<0)
{sec=59;}
}
} while(k6==0);
}
}
void display ()
{
unsigned char temp0=0,temp1=0,temp2=0,temp3=0,temp4=0,temp5=0;//如果不是int 是 char 还用不用加0x30
temp0=hour/10;
temp1=hour%10;
temp2=min/10;
temp3=min%10;
temp4=sec/10;
temp5=sec%10;
writecom(0x80);
delay(5);
writedat(temp0+0x30);
delay(5);
writedat(temp1+0x30);
delay(5);
writedat(':');
delay(5);
writedat(temp2+0x30);
delay(5);
writedat(temp3+0x30);
writedat(':');
delay(5);
writedat(temp4+0x30);
delay(5);
writedat(temp5+0x30);
delay(5);//等会儿全放到中断里弄试试
}
void initlcd() //初始化1602
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void main()
{ inittimer0();
initlcd();
while(1)
{
display();
keys();
}
}
void timer0_isr() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
cnt++;
if(cnt==20)
{ sec++;
cnt=0;
}
if(sec==60)
{
min++;
sec=0;
}
if(min==60)
{
hour++;
min=0;
}
if(hour==24)
{
hour=0;
}
}
4. 后期Proteus仿真图(这个俺用了)
十五、 抢答器的制作(画饼中😋)
1. 最初版本
2. Proteus仿真图
十六、 数字电压表的制作
DAC转换 实时把变化的电压显示到LCD屏幕上
1. 最初版本
#include <reg51.h>
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
sbit START=P3^3;
sbit EOC=P3^4;
sbit OE=P3^5;
unsigned int vol=0;
unsigned char str[]={"Voltage:"};
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void ADC ()
{
START=0;
START=1;
delay(5);
START=0;
while(EOC!=1);
OE=1;
vol=P1;
OE=0;
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
P2=dat;
delay(5);
E=1;
E=0;
}
void initlcd()
{
writecom(0x38);//设置16*2显示,5*7点阵,8位数据接口
writecom(0x0c); //设置开显示,不显示光标
writecom(0x06); //写一个字符后地址指针加1
writecom(0x01);//显示清零,数据指针清零
}
void display()
{
unsigned int temp1,temp2,temp3,i=0;
vol=(vol*100)/51; // (vol*5)/255
temp1=vol/100;
temp2=(vol%100)/10; // 不加括号对不对 试一下
temp3=vol%10;
writecom(0x80);
delay(5);
for(i=0;i<=7;i++)
{
writedat(str[i]);
delay(5);
}
writecom(0x80+0x40+0x04);
delay(5);
writedat(temp1+0x30);
delay(5);
writedat('.');
delay(5);
writedat(temp2+0x30);
delay(5);
writedat(temp3+0x30);
delay(5);
writedat('V');
delay(5);
}
void main()
{
initlcd();
while(1)
{ ADC();
display();
}
}
2. Proteus仿真图
十七、 简单乐曲的演奏(画饼中😋)
透露下思路 利用矩阵按键,把每个音调对应的频率和公式加到相应按键中,当按键按下,加入蜂鸣器产生声音的代码。若想提前播放已有的歌曲,把对应的数据提前放入数组中,利用循环进行播放。
1. 最初版本
2. Proteus仿真图
十八、 温度传感器的应用(已有人用)
用温度传感器获取当前温度 并显示到LCD1602屏幕上
1. 最初版本
#include <reg51.h>
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
sbit DQ=P3^3;
unsigned int readtemp=0;
unsigned char code str[]={"Temperature: "};
void delay_18B20(unsigned int i)
{
for(;i>0;i--);
}
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ拉高
delay_18B20(8); //稍作延时
DQ = 0; //DQ拉低
delay_18B20(80); //延时大于480us
DQ = 1; //拉高总线
delay_18B20(14);
x=DQ; //若x=0初始化成功,若x=1初始化失败
delay_18B20(20);
}
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 拉低总线
dat>>=1;//每读取移位向右移移位
DQ = 1; //拉高总线
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
if(DQ){delay_18B20(1);DQ=1;}
else{delay_18B20(5);DQ = 1;}
dat>>=1;
}
}
unsigned char ReadTemperature(void)
{
unsigned int a=0,b=0,temp=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序列号操作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(100); //
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序列号操作
WriteOneChar(0xBE); //读取温度寄存器
delay_18B20(100);
a=ReadOneChar(); //读温度低位
b=ReadOneChar(); //读温度高位
temp=((b*256+a)>>4); //当前采集温度除16得到实际温度
return(temp);
}
void delay(unsigned int time)
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
P2=dat;
delay(5);
E=1;
E=0;
}
void display()
{
unsigned char temp0=0,temp1=0,temp2=0,z=0;
temp0=readtemp/100;
temp1=(readtemp%100)/10;
temp2=readtemp%10;
writecom(0x80);
delay(5);
while(str[z]!='\0')
{writedat(str[z]); delay(5);z++;}
z=0;
delay(5);
writecom(0x80+0x46);
delay(5);
writedat(temp0+0x30);
delay(5);
writedat(temp1+0x30);
delay(5);
writedat(temp2+0x30);
delay(5);
writedat(0xdf);
delay(5);
writedat('C');
delay(5);
}
void initlcd()
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void main()
{
initlcd();
while(1)
{
readtemp=ReadTemperature();
display();
}
}
2. Proteus仿真图
十九、 蜂鸣器代码
滴~ 学生卡~~~
按键按下 蜂鸣器会响一段时间
1. 最初版本
#include <reg51.h>
sbit sounder=P3^0;
unsigned int k=0;
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void main()
{
sounder=0;
while(1)
{
sounder=~sounder;
delay(1);
k++;
if(k==2000)
{
sounder=1;
k=0;
while(1);
}
}
}
2. Proteus仿真图
二十、 直流电机代码
爱的魔力转圈圈😍
1. 最初版本
#include <reg51.h>
sbit IN1=P2^0;
sbit IN2=P2^1;
sbit EN1=P2^2;
void delay(unsigned int time)
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void motor()
{
EN1=1;
IN2=0;
IN1=1;
delay(50);
IN1=0;
delay(50);
}
void main()
{
while(1)
{
motor();
}
}
2. Proteus仿真图
二十一、 步进电机代码
每秒旋转45度😁
1. 最初版本
#include <reg51.h>
unsigned char step[]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//1001 1000 1100 0100 0110 0010 0011 0001
void delay(unsigned int time)
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void display()
{
unsigned char i=0;
for(i=0;i<=7;i++)
{
P2=step[i];
delay(1000);
}
}
void main()
{
while(1)
{
display();
}
}
#include <reg51.h>
unsigned char step[]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//1001 1000 1100 0100 0110 0010 0011 0001
unsigned char cnt=0,i=0;
void initimer0()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
void main()
{
initimer0();
while(1)
{
}
}
void timer0_isr () interrupt 1
{
TH0=0x3c;
TL0=0xb0;
cnt++;
if(cnt==20)
{
P2=step[i];
i++;
if(i==8)
{ i=0;}
cnt=0;
}
}
2. Proteus仿真图
二十二、DS1302制作的万年历(已有人用)
这是一个万年历 可以显示年月日星期时分秒 并对闰年和月份有自动计算补偿功能 修改时间的时候也很方便,在主函数里面用BCD码格式修改就行了,非常直观😊
~~唉~~我去年买了个表~~~~
1. 最初版本
#include <reg51.h>
#include <intrins.h>//因为要调用nop函数,所以添加这个库函数
#define uchar unsigned char
#define uint unsigned int
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
sbit T_RST=P3^3;
sbit T_CLK=P3^4;
sbit T_IO=P3^5;
uchar datechar[]={"DATE:"};
uchar timechar[]={"TIME:"};
uchar datebuffer[10]={0x32,0x30,0,0,0x2d,0,0,0x2d,0,0}; //0x32表示2,0x30表示0,0x2d表示 -
uchar timebuffer[8]={0,0,0x3a,0,0,0x3a,0,0}; //0x3a表示冒号
uchar weekbuffer={0x30};
void WriteB(uchar dat) //单字节写
{
uchar i;
for(i=8; i>0; i--)
{
T_IO=dat&0x01;
T_CLK = 1;
T_CLK = 0;
dat = dat >> 1;
}
}
void W1302(uchar address,uchar dat) //单字节写
{
T_RST = 0;
T_CLK = 0;
_nop_();
_nop_();
T_RST = 1;
_nop_();
_nop_();
WriteB(address);
WriteB(dat);
T_CLK = 1;
T_RST =0;
}
uchar ReadB(void) //单字节读
{
uchar i,readdat=0;
for(i=8; i>0; i--)
{
readdat=readdat>>1;
if(T_IO)
{
readdat|=0x80;
}
T_CLK = 1;
T_CLK = 0;
}
return(readdat);
}
uchar R1302(uchar address)//单字节读(读和写都是从低位开始)
{
uchar dat=0;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
WriteB(address);
dat = ReadB();
T_CLK = 1;
T_RST =0;
return(dat);
}
void delay(unsigned int time) //延时
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void writecom(unsigned char com) //LCD1602的写命令
{
RS=0;
RW=0;
E=0;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat) //LCD1602的写数据
{
RS=1;
RW=0;
E=0;
P2=dat;
delay(5);
E=1;
E=0;
}void initlcd() //LCD1602的初始化
{
writecom(0x38);//设置16*2显示,5*7点阵,8位数据接口
writecom(0x0c); //设置开显示,不显示光标
writecom(0x06); //写一个字符后地址指针加1
writecom(0x01);//显示清零,数据指针清零
}
void display()
{
int i=0,temp=0;
temp=R1302(0x8d); // read year
datebuffer[2]=0x30+temp/16;
datebuffer[3]=0x30+temp%16;
temp=R1302(0x8b); // read week
weekbuffer=0x30+temp;
temp=R1302(0x89); // read month
datebuffer[5]=0x30+temp/16;
datebuffer[6]=0x30+temp%16;
temp=R1302(0x87); // read day
datebuffer[8]=0x30+temp/16;
datebuffer[9]=0x30+temp%16;
temp=R1302(0x85); // read hour
temp=temp&0x7f;
timebuffer[0]=0x30+temp/16;
timebuffer[1]=0x30+temp%16;
temp=R1302(0x83); // read minute
timebuffer[3]=0x30+temp/16;
timebuffer[4]=0x30+temp%16;
temp=R1302(0x81); // read second
timebuffer[6]=0x30+temp/16;
timebuffer[7]=0x30+temp%16;
writecom(0x80); //第一行开始写"DATE:"
for(i=0;i<5;i++)
{
writedat(datechar[i]);
}
writecom(0xc0); //0x80+0x40 第一行开始写"TIME:"
for(i=0;i<5;i++)
{
writedat(timechar[i]);
}
writecom(0x86); //display calender
for(i=0;i<10;i++)
{
writedat(datebuffer[i]);
}
writecom(0xc6); //display time
for(i=0;i<8;i++)
{
writedat(timebuffer[i]);
}
writedat(' ');
writedat(weekbuffer); //display week
}
void main()
{
initlcd();
W1302(0x8e,0); //打开写保护
W1302(0x8c,0x22); //写入年,BCD码
W1302(0x8a,0x01); //写入星期
W1302(0x88,0x05); //写入月
W1302(0x86,0x09); //写入日
W1302(0x84,0x20); //写入小时
W1302(0x82,0x02); //写入分
W1302(0x80,0x50); //写入秒
W1302(0x8e,0x80);//关闭写保护
while(1)
{
display();
}
}
2. Proteus仿真图
3. Proteus仿真现象
二十三、年轻人的第一台洗衣机(已有人用)
这台洗衣机可以让你摆脱在农大用手洗衣服的困扰,它小巧精悍:
有两个模式 正转还有反转(分别对应模式1和模式2)
可以设置倒计时洗衣服(最大300s)
当你发现洗衣服的时候忘洗了一件,我们贴心的为你准备了一个暂停功能
可以随时控制洗衣机的开和关😎
本实验是实验 5 11 20的整合
1. 最初版本
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit IN0=P1^5;
sbit IN1=P1^4;
sbit key0=P1^0;
sbit key1=P1^1;
sbit inctime=P1^2;
sbit dectime=P1^3;
sbit ST=P1^6;
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^4;
uint max_time=300;//定时最大值,可以修改
uchar s[]={"0123456789"};
uchar str[]={"MODE:"};
uchar str1[]={"TIME:"};
int dtime=0;//设定的时间
uint count=0,num=0;
char flag=0,flag0=0,flag1=0,flag2=0,flag3=0;
char mode=0;
void motor_forward()
{
IN0=0;
IN1=1;
}
void motor_flip()
{
IN0=1;
IN1=0;
}
void inittimer()
{
TMOD=0x10;
TH1=0x3c;//设置定时器1为50ms延时
TL1=0xb0;
ET1=1;
EA=1;
}
void machine_mode()
{
if(mode==1)
{
motor_forward();
}
if(mode==2)
{
motor_flip();
}
}
void datdeal()
{
if(key0==0&&flag==0)//模式加
{
flag=1;
}
if(flag==1&&key0==1)
{
mode++;
flag=0;
}
if(key1==0&&flag0==0)//模式减
{
flag0=1;
}
if(flag0==1&&key1==1)
{
mode--;
flag0=0;
}
if(ST==0&&flag1==0)//开始运行
{
flag1=1;
}
if(flag1==1&&ST==1)
{
machine_mode();
if(dtime>0)
{
TR1=1;
}
else TR1=0;
flag1=0;
}
if(inctime==0&&flag2==0)//增加设定时间
{
flag2=1;
}
if(flag2==1&&inctime==1)
{
dtime++;
flag2=0;
}
if(dectime==0&&flag3==0)//减少设定时间
{
flag3=1;
}
if(flag3==1&&dectime==1)
{
dtime--;
flag3=0;
}
if(mode>2)
{
mode=0;
}
else if(mode<0)
{
mode=0;
}
if(dtime<0)//当时间为0时,电机停止运行
{
dtime=0;
TR1=0;
IN1=0;
IN0=0;
}
if(dtime>max_time)
{
dtime=max_time;
}
}
void delay(unsigned int t)
{
unsigned int i=0,j=0;
for(i=0;i<t;i++)
{
for(j=0;j<120;j++);
}
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
E=1;
P2=dat;
delay(5);
E=0;
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
E=1;
P2=com;
delay(5);
E=0;
}
void display()
{
uchar temp0=0;
uchar ttemp0=0,ttemp1=0,ttemp2=0;
uchar i=0,j=0;
temp0=mode%10;
ttemp0=dtime/100;
ttemp1=dtime%100/10;
ttemp2=dtime%10;
writecom(0x80);//第一行显示mode
while(str[i]!='\0')
{
writedat(str[i]);
i++;
}
writedat(':');
writedat(s[temp0]);
writecom(0x80+0x40);//第二行显示time
while(str1[j]!='\0')
{
writedat(str1[j]);
j++;
}
writedat(s[ttemp0]);
writedat(s[ttemp1]);
writedat(s[ttemp2]);
writedat('s');
}
void initex()//初始化外部中断0
{
IE0=1;
EX0=1;
}
void initlcd()
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void main()
{
initex();//初始化外部中断
inittimer();//初始化定时器
initlcd();//初始化lcd
while(1)
{
datdeal();
display();
}
}
void ex_isr() interrupt 0//停止运行电机
{
TR1=0;
IN1=0;
IN0=0;
}
void timer1_isr() interrupt 3//每一秒钟设定时间减1
{
TH1=0x3c;
TL1=0xb0;
num++;
if(num==20)
{
dtime--;
num=0;
}
}
2. Proteus仿真图
二十四、年轻人的第一个风扇(已有人用)
这个小风扇可以实现在LCD1602上实时显示 当前温度
并且在温度大于30度的时候,开始启动风扇,且温度越高,风扇的转速越快
风扇开启关闭还有提示哦😋
让你在农大拥有一个美好的夏天!!!!😉
1. 最初版本
#include <reg51.h>
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
sbit DQ=P3^4;
sbit IN0=P1^0;
sbit IN1=P1^1;
sbit EN=P1^2;
unsigned int readtemp=0;
unsigned char code str[]={"Temperature: "};
void delay_18B20(unsigned int i)
{
for(;i>0;i--);
}
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ拉高
delay_18B20(8); //稍作延时
DQ = 0; //DQ拉低
delay_18B20(80); //延时大于480us
DQ = 1; //拉高总线
delay_18B20(14);
x=DQ; //若x=0初始化成功,若x=1初始化失败
delay_18B20(20);
}
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 拉低总线
dat>>=1;//每读取移位向右移移位
DQ = 1; //拉高总线
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
if(DQ){delay_18B20(1);DQ=1;}
else{delay_18B20(5);DQ = 1;}
dat>>=1;
}
}
unsigned char ReadTemperature(void)
{
unsigned int a=0,b=0,temp=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序列号操作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(100); //
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序列号操作
WriteOneChar(0xBE); //读取温度寄存器
delay_18B20(100);
a=ReadOneChar(); //读温度低位
b=ReadOneChar(); //读温度高位
temp=((b*256+a)>>4); //当前采集温度除16得到实际温度
return(temp);
}
void delay(unsigned int time)
{
unsigned int i;
for(time;time>0;time--)
for(i=120;i>0;i--);
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
P2=dat;
delay(5);
E=1;
E=0;
}
void display()
{
int temp=0;
unsigned char temp0=0,temp1=0,temp2=0,z=0;
temp0=readtemp/100;
temp1=(readtemp%100)/10;
temp2=readtemp%10;
temp=100*temp0+10*temp1+temp2;
if(temp>30) //温度大于30℃时
{
IN1=0;
IN0=1;
delay(10*temp);
IN0=0;
delay(5);
EN=1;
writecom(0x80+0x40);
delay(5);
writedat('O');
delay(5);
writedat('N');
delay(5);
writedat(' ');
delay(5);
}
else if(temp<=30)//温度小于等于30℃时
{
IN0=0;
IN1=0;
writecom(0x80+0x40);
delay(5);
writedat('O');
delay(5);
writedat('F');
delay(5);
writedat('F');
delay(5);
}
writecom(0x80);
delay(5);
while(str[z]!='\0')
{writedat(str[z]); delay(5);z++;}
z=0;
delay(5);
writecom(0x80+0x46);
delay(5);
writedat(temp0+0x30);
delay(5);
writedat(temp1+0x30);
delay(5);
writedat(temp2+0x30);
delay(5);
writedat(0xdf);
delay(5);
writedat('C');
delay(5);
}
void initlcd()
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void main()
{
initlcd();
while(1)
{
readtemp=ReadTemperature();
display();
}
}
2. Proteus仿真图
3. Proteus仿真现象
二十五、正弦波频率发生器(已有人用)
用按键控制生成可变频率的正弦波并在LCD1602上显示相关频率信息
1. 最初版本
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit key0=P1^0;
sbit key1=P1^1;
sbit start=P1^2;
sbit RS=P3^3;
sbit RW=P3^4;
sbit E=P3^5;
code unsigned char sin[256]=
{
0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,
0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc5,
0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,
0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,
0xea,0xec,0xee,0xef,0xf1,0xf2,0xf4,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,
0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,
0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,
0xf5,0xf4,0xf2,0xf1,0xef,0xee,0xec,0xea,
0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,
0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,
0xc5,0xc2,0xbf,0xbc,0xba,0xb7,0xb4,0xb1,
0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,
0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,
0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,
0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,
0x4e,0x4c,0x48,0x45,0x43,0x40,0x3d,0x3a,
0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,
0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,
0x15,0x13,0x11,0x10,0x0e,0x0d,0x0b,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,
0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,
0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,
0x3a,0x3d,0x40,0x43,0x45,0x48,0x4c,0x4e,
0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66,
0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80
}; //正弦表
uint count=0,fre=0;
uchar flag=0,flag0=0,flag1=0;
uchar timeh=0,timel=0;
uchar str[]={"Frequence:"};
void delay(unsigned int t)
{
unsigned int i=0,j=0;
for(i=0;i<t;i++)
{
for(j=0;j<120;j++);
}
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0;
E=1;
P0=dat;
delay(5);
E=0;
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0;
E=1;
P0=com;
delay(5);
E=0;
}
void initlcd()
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void key()
{
if(key0==0&&flag==0)
{
flag=1;
}
if(flag==1&&key0==1)
{
fre=fre+1;
flag=0;
}
if(key1==0&&flag0==0)
{
flag0=1;
}
if(flag0==1&&key1==1)
{
fre=fre-1;
flag0=0;
}
if(start==0&&flag1==0)
{
flag1=1;
}
if(flag1==1&&start==1)
{
TR0=1;
flag1=0;
}
}
void datdeal()
{
uint temp=0;//temp里面是初值
temp=62500/(fre*16); // 计算公式:1000000/(fre*256)=1/fre/256*1000000
timeh=(65536-temp)/256;
timel=(65536-temp)%256;
}
void inittimer()
{
TMOD=0x01;
TH0=timeh;
TL0=timel;
ET0=1;
EA=1;
}
void init_exit1()
{
IE0=1;
EX0=1;
}
void display()
{
uchar temp0=0,temp1=0,temp2=0;
uchar i=0;
temp0=fre/100;
temp1=fre%100/10;
temp2=fre%10;
writecom(0x80);
while(str[i]!='\0')
{
writedat(str[i]);
i++;
}
writecom(0x80+0x46);
writedat( temp0+0x30);
writedat( temp1+0x30);
writedat( temp2+0x30);
writedat('H');
writedat('Z');
}
void main()
{
init_exit1();
inittimer();
initlcd();
while(1)
{
key();
datdeal();
display();
}
}
void ex_isr() interrupt 0
{
TR0=0;
}
void timer_isr() interrupt 1
{
TH0=timeh;
TL0=timel;
count++;
P2=sin[count];
if(count==256)
{
count=0;
}
}
2. Proteus仿真图
3. Proteus仿真现象
二十六、16*16点阵的应用😁
1. 最初版本
#include <reg51.h>
unsigned int row[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
code unsigned int column[]=
{
0x0000,0x2088,0x1108,0x13C8,0x0248,0x03DC,0x7248,0x13C8,0x1268,0x17D8,0x10C8,0x1148,0x1A48,0x1448,0x00D8,0x0000,//谢
0x0000,0x2088,0x1108,0x13C8,0x0248,0x03DC,0x7248,0x13C8,0x1268,0x17D8,0x10C8,0x1148,0x1A48,0x1448,0x00D8,0x0000,//谢
0x0000,0x0100,0x0100,0x7FFC,0x0100,0x0100,0x3FF0,0x0810,0x0820,0x0440,0x0280,0x0100,0x0280,0x0C60,0x701C,0x0000,//支
0x0000,0x1040,0x1040,0x11F8,0x7C40,0x1040,0x13FC,0x1410,0x1810,0x73FC,0x1010,0x1110,0x1090,0x1010,0x7070,0x0000,//持
};
unsigned char num=0,count=0;
unsigned char row_num=16,column_num=16;
unsigned int temp=0;
void delay(unsigned int t)
{
unsigned int i=0,j=0;
for(i=0;i<t;i++)
{
for(j=0;j<120;j++);
}
}
void matrix()
{
unsigned char i=0;
for(i=0;i<row_num;i++)
{
P1=row[i]/256;
P0=row[i]%256;
temp=(column[i+column_num*count])>>num;
P3=~(temp/256);
P2=~(temp%256);
delay(1);
}
num++;
delay(40);
if(num==16)//num移动次数
{
num=0;
count++;
}
if(count==4)//count汉字的个数
{
count=0;
}
}
void main()
{
while(1)
{
matrix();
}
}
2. Proteus仿真图
3. Proteus仿真现象
二十七、基于51单片机频率检测计的实现
1. 最初版本
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar count=0,valueH=0,valueL=0;
uchar str1[]={"Frequence:"};
uint fre=0;
sbit RS=P1^0;
sbit RW=P1^1;
sbit E=P1^2;
void initex0() //初始化外部中断0
{
IT0=1;
EX0=1;
EA=1;
}
void inittimer0() //初始化定时器0
{
TMOD=0x01;
TH0=0x00;
TL0=0x00;
}
void datadeal() //数据处理
{
uint value=0;
value=valueH*256+valueL;
fre=10000000/value;
}
void delay(unsigned int t)//延时函数
{
unsigned int i=0,j=0;
for(i=0;i<t;i++)
{
for(j=0;j<120;j++);
}
}
void writecom(unsigned char com)//写命令
{
RS=0;
RW=0;
E=0;
E=1;
P2=com;
delay(5);
E=0;
}
void writedat(unsigned char dat) //写数据
{
RS=1;
RW=0;
E=0;
E=1;
P2=dat;
delay(5);
E=0;
}
void initlcd() //初始化LCD1602
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void display() //演示函数
{
uchar temp0=0,temp1=0,temp2=0,temp3=0,temp4=0;
uchar i=0;
temp0=(fre%100000)/10000; //万
temp1=(fre%10000)/1000; // 千
temp2=(fre%1000)/100; //百
temp3=(fre%100)/10; // 十
temp4=fre%10; //个
writecom(0x80);
delay(1);
while(str1[i]!='\0')
{
writedat(str1[i]); //写Frequence
delay(1);
i++;
}
writecom(0x80+0x40+4);
delay(1);
writedat(temp0+0x30);
delay(1);
writedat(temp1+0x30);
delay(1);
writedat(temp2+0x30);
delay(1);
writedat(temp3+0x30);
delay(1);
writedat('.'); //小数点
delay(1);
writedat(temp4+0x30);
delay(1);
writedat('H');
delay(1);
writedat('Z');
delay(1);
}
void main()
{
initex0();
inittimer0();
initlcd();
while(1)
{
datadeal();
display();
}
}
void ex0_isr() interrupt 0
{
if(count==0)
{
TH0=0x00;
TL0=0x00;
TR0=1;
}
else if(count==1)
{
TR0=0;
valueH=TH0;
valueL=TL0;
count=0;
}
count++;
}
2. Proteus仿真图
二十八、贪吃蛇游戏的实现
1. 最初版本
#include "reg52.h"
#include "stdlib.h"
typedef unsigned char u8; //0~255
typedef unsigned int u16; //0~65535
typedef unsigned long u32; //0~4294967295
sbit D0=P2^0;
sbit D1=P2^1;
sbit D2=P2^2;
sbit D3=P2^3;
sbit KEY1=P3^5;
sbit KEY2=P3^4;
sbit KEY3=P3^3;
sbit KEY4=P3^2;
#define X1 P0
#define X2 P1
u8 Date[32]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};//点阵屏显示数据
u8 snake_turn_point[20]={0};//存储蛇尾的转折点
u32 snake_turn=0;//相应转点为左转还是右转 0为左转1为右转
u8 snake_cd=2;//蛇的长度 初始值为2
u8 smake_head_x=10;//蛇头的x轴坐标
u8 smake_head_y=10;//蛇头的y轴坐标
u8 smake_tail_x=10;//蛇尾的x轴坐标
u8 smake_tail_y=11;//蛇尾的y轴坐标
u8 snake_fx=3;//蛇的运动方向 1:上 2:下 3:左 4:右
u8 snake_sd=10;//运动速度
u8 snake_turn_time=0;//蛇的尾巴剩余转点
u8 snake_tail_fx=3;//蛇尾运动方向
u8 food_x=5;//食物的x轴坐标
u8 food_y=5;//食物的y轴坐标
u8 food_x_next=10;//下一个食物的x轴坐标
u8 food_y_next=10;//下一个食物的y轴坐标
void Display(void);//显示函数
void InitTimer0(void);//定时器中断初始化 10ms
void Key_Scan(void);//按键扫描函数
void Write_Date(u8 x,u8 y,u8 a);//对点的写操作
void snake_move(void);//蛇的移动
void game_over(void);//游戏结束 显示完
void creat_food();//生产食物
void main(void)
{
InitTimer0();//初始化定时器
Write_Date(food_x,food_y,1);
while(1)
{
Display();
Key_Scan();
}
}
void InitTimer0(void)
{
TMOD = 0x01;
TH0 = 0x0D8;
TL0 = 0x0F0;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void Display(void)
{
X1=0x00; X2=0x00; D3=0; D2=0; D1=0; D0=0; X1=Date[0]; X2=Date[1];
X1=0x00; X2=0x00; D3=0; D2=0; D1=0; D0=1; X1=Date[2]; X2=Date[3];
X1=0x00; X2=0x00; D3=0; D2=0; D1=1; D0=0; X1=Date[4]; X2=Date[5];
X1=0x00; X2=0x00; D3=0; D2=0; D1=1; D0=1; X1=Date[6]; X2=Date[7];
X1=0x00; X2=0x00; D3=0; D2=1; D1=0; D0=0; X1=Date[8]; X2=Date[9];
X1=0x00; X2=0x00; D3=0; D2=1; D1=0; D0=1; X1=Date[10]; X2=Date[11];
X1=0x00; X2=0x00; D3=0; D2=1; D1=1; D0=0; X1=Date[12]; X2=Date[13];
X1=0x00; X2=0x00; D3=0; D2=1; D1=1; D0=1; X1=Date[14]; X2=Date[15];
X1=0x00; X2=0x00; D3=1; D2=0; D1=0; D0=0; X1=Date[16]; X2=Date[17];
X1=0x00; X2=0x00; D3=1; D2=0; D1=0; D0=1; X1=Date[18]; X2=Date[19];
X1=0x00; X2=0x00; D3=1; D2=0; D1=1; D0=0; X1=Date[20]; X2=Date[21];
X1=0x00; X2=0x00; D3=1; D2=0; D1=1; D0=1; X1=Date[22]; X2=Date[23];
X1=0x00; X2=0x00; D3=1; D2=1; D1=0; D0=0; X1=Date[24]; X2=Date[25];
X1=0x00; X2=0x00; D3=1; D2=1; D1=0; D0=1; X1=Date[26]; X2=Date[27];
X1=0x00; X2=0x00; D3=1; D2=1; D1=1; D0=0; X1=Date[28]; X2=Date[29];
X1=0x00; X2=0x00; D3=1; D2=1; D1=1; D0=1; X1=Date[30]; X2=Date[31];
}
void Key_Scan(void)
{
static fx=3;
if(KEY1==0)
snake_fx=1;
if(KEY2==0)
snake_fx=2;
if(KEY3==0)
snake_fx=3;
if(KEY4==0)
snake_fx=4;
if(fx!=snake_fx)
{
snake_turn_point[snake_turn_time]|=snake_fx*16;//保存蛇尾拐点方向
if(snake_fx==1||snake_fx==2)
snake_turn_point[snake_turn_time]+=smake_head_y;
else if(snake_fx==3||snake_fx==4)
snake_turn_point[snake_turn_time]+=smake_head_x; //保存蛇尾拐点的坐标
snake_turn_time++;
fx=snake_fx;
}
}
void tail_turn()
{
u8 i;
for(i=0;i<snake_turn_time;i++)
{
snake_turn_point[i]=snake_turn_point[i+1];
}
snake_turn_time-=1;
}
void res_food()
{
food_x=food_x_next;
food_y=food_y_next;
Write_Date(food_x,food_y,1);
}
void snake_move(void)
{
u8 dat=0x01;
u8 bj_get_food=0;
if(smake_head_y==0&&snake_fx==3)
game_over();
if(smake_head_x==0&&snake_fx==1)
game_over(); //判断蛇头是否碰到上、左墙壁
if(snake_fx==1)
{
if(!((smake_head_x-1==food_x)&&(smake_head_y==food_y)))
{
Write_Date(smake_tail_x,smake_tail_y,0); //熄灭蛇尾
bj_get_food=1;
}
}
else if(snake_fx==2)
{
if(!((smake_head_x+1==food_x)&&(smake_head_y==food_y)))
{
Write_Date(smake_tail_x,smake_tail_y,0); //熄灭蛇尾
bj_get_food=1;
}
}
else if(snake_fx==3)
{
if(!((smake_head_y-1==food_y)&&(smake_head_x==food_x)))
{
Write_Date(smake_tail_x,smake_tail_y,0); //熄灭蛇尾
bj_get_food=1;
}
}
else if(snake_fx==4)
{
if(!((smake_head_y+1==food_y)&&(smake_head_x==food_x)))
{
Write_Date(smake_tail_x,smake_tail_y,0); //熄灭蛇尾
bj_get_food=1;
}
}
if(!bj_get_food)
{
res_food();
} //如果吃食物了 点亮下一个食物
if((snake_tail_fx==1)&&(smake_tail_x==(snake_turn_point[0]&0x0f)))
{
snake_tail_fx=snake_turn_point[0]/16;
tail_turn();
}
else if((snake_tail_fx==2)&&(smake_tail_x==(snake_turn_point[0]&0x0f)))
{
snake_tail_fx=snake_turn_point[0]/16;
tail_turn();
}
else if((snake_tail_fx==3)&&(smake_tail_y==(snake_turn_point[0]&0x0f)))
{
snake_tail_fx=snake_turn_point[0]/16;
tail_turn();
}
else if((snake_tail_fx==4)&&(smake_tail_y==(snake_turn_point[0]&0x0f)))
{
snake_tail_fx=snake_turn_point[0]/16;
tail_turn();
}
//判断蛇尾是否需要转向
if(bj_get_food)
{
if(snake_tail_fx==1)
smake_tail_x-=1;
else if(snake_tail_fx==2)
smake_tail_x+=1;
else if(snake_tail_fx==3)
smake_tail_y-=1;
else if(snake_tail_fx==4)
smake_tail_y+=1; //蛇尾巴移动
}
if(snake_fx==1)
smake_head_x-=1;
else if(snake_fx==2)
smake_head_x+=1;
else if(snake_fx==3)
smake_head_y-=1;
else if(snake_fx==4)
smake_head_y+=1; //蛇头移动
if(smake_head_y==16||smake_head_x==16)
game_over(); //判断蛇头是否碰到下、右墙壁
if(smake_head_y<8)
{
dat=dat<<smake_head_y;
if((Date[2*smake_head_x]&dat)&&bj_get_food)
game_over();
}
else
{
dat=dat<<(smake_head_y-8);
if((Date[2*smake_head_x+1]&dat)&&bj_get_food)
game_over();
} //判断蛇头是否碰到了身子
}
void Write_Date(u8 x,u8 y,u8 a)
{
u8 i;
u8 dat;
if(a==0)
{
dat=0xfe;
if(y<8)
{
for(i=0;i<y;i++)
{
dat=dat<<1;
dat|=0x01;
}
Date[2*x]&=dat;
}
else if(y<16)
{
y-=8;
for(i=0;i<y;i++)
{
dat=dat<<1;
dat|=0x01;
}
Date[2*x+1]&=dat;
}
}
else
{
dat=0x01;
if(y<8)
{
dat=dat<<y;
Date[2*x]|=dat;
}
else if(y<16)
{
y-=8;
dat=dat<<y;
Date[2*x+1]|=dat;
}
}
}
void game_over()
{
u8 wan[32]=
{
0x40,0x00,0x80,0x00,0xFE,0x7F,0x02,0x40,0x01,0x20,0xF8,0x0F,0x00,0x00,0x00,0x00,
0xFE,0x3F,0x20,0x02,0x20,0x02,0x20,0x02,0x10,0x22,0x10,0x22,0x08,0x22,0x06,0x3C,
};
u8 i;
for(i=0;i<32;i++)
Date[i]=wan[i];
EA=0;
}
void creat_food()
{
u8 dat=0x01;
u8 x,y,next_x,next_y;
u8 bj=0;
y=food_y_next;
x=food_x_next;
do
{
bj=0;
next_x=(rand()%16);
next_y=(rand()%16);
if(next_y>=8)
{
bj=1;
next_y-=8;
}
dat=0x01;
dat=dat<<next_y;
}while(dat==Date[2*next_x+bj]);
food_x_next=next_x;
food_y_next=next_y+8*bj;
}
void Timer0Interrupt(void) interrupt 1
{
static u8 js=0;
if(js<snake_sd) js++;
else if(js==snake_sd)
{
js=0;
creat_food();
snake_move();
Write_Date(smake_head_x,smake_head_y,1);
}
TH0 = 0x0D8;
TL0 = 0x0F0;
}
二十九、智能计算器的实现
1. 最初版本
/* S16 S12 S8 S4分别是123+
S15 S11 S7 S3分别是456-
S14 S10 S6 S2分别是789*
S13 S9 S5 S1分别是0 CLR = /
*/
/* 实现两个数的运算,每个数的位数至少可以八位 */
#include<reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit rw=P2^5;
sbit rs=P2^6;
sbit e=P2^7;
sbit led=P3^7;
sbit beep=P2^0;
uint8 key,num;
uint8 fuhao;//定义具体的那个符号,是加减还是乘除。
uint8 flag; //定义有没有按下符号键,这个是统称
long a,b,c,d; //定义运算数据的第一个和第二个及等于的数变量
uint8 k; //定义小数点后面显示的位数
uint8 biao;
uint8 dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };//保存显示的数据
void delay(uint16 i)
{
while(i--);
}
void lcdwrc(uint8 c)
{
delay(1000);
rs=0;
rw=0;
e=0;
P0=c;
e=1;
delay(1000);
e=0;
}
void lcdwrd(uint8 dat)
{
delay(1000);
rs=1;
rw=0;
e=0;
P0=dat;
e=1;
delay(1000);
e=0;
rs=0;
}
void lcdinit()
{
delay(1500);
lcdwrc(0x38);
delay(500);
lcdwrc(0x38);
delay(500);
lcdwrc(0x38);
delay(500);
lcdwrc(0x38);
lcdwrc(0x08);
lcdwrc(0x01);
lcdwrc(0x06);
lcdwrc(0x0c);
key=0;
num=0;
flag=0;
fuhao=0;
a=0;
b=0;
c=0;
d=0;
biao=0;
led=0;
}
void keyscan()
{
P1=0xfe; //令第一行为0,然后判断是哪一列按下
if(P1!=0xfe)
{
delay(1000);
if(P1!=0xfe)
{
key=P1&0xf0;
switch(key)
{
case 0xe0: num=0;break; //1
case 0xd0: num=1;break; //2
case 0xb0: num=2;break; //3
case 0x70: num=3;break; //加
}
}
while(P1!=0xfe);
if(num==0||num==1||num==2) //确认第一行的数1,2,3
{
if(flag==0) //没有按下符号键
{
//led=1;
a=a*10+dat1[num];
}
else
{
//led=1;
b=b*10+dat1[num];
}
}
if(num==3)
{
//led=0;
flag=1;
fuhao=1;//加号+
}
lcdwrd(0x30+dat1[num]);
}
P1=0xfd; //令第二行为0,判断是哪一列按下
if(P1!=0xfd)
{
delay(1000);
if(P1!=0xfd)
{
key=P1&0xf0;
switch(key)
{
case 0xe0: num=4;break; //4
case 0xd0: num=5;break; //5
case 0xb0: num=6;break; //6
case 0x70: num=7;break; //减—
}
}
while(P1!=0xfd);
if(num==4||num==5||num==6)
{
if(flag==0) //没有按下符号键
{
//led=1;
a=a*10+dat1[num];
}
else
{
//led=1;
b=b*10+dat1[num];
}
}
else
{
flag=1;
fuhao=2;//带表减号
}
lcdwrd(0x30+dat1[num]);
}
P1=0xfb; //令第三行为0,判断哪一列按下
if(P1!=0xfb)
{
delay(1000);
if(P1!=0xfb)
{
key=P1&0xf0;
switch(key)
{
case 0xe0: num=8;break; //7
case 0xd0: num=9;break; //8
case 0xb0: num=10;break; //9
case 0x70: num=11;break; //乘*
}
}
while(P1!=0xfb);
if(num==8||num==9||num==10)
{
if(flag==0) //没有按下符号键
{
//led=1;
a=a*10+dat1[num];
}
else
{
//led=1;
b=b*10+dat1[num];
}
}
else
{
flag=1;
fuhao=3;//带表乘号*
}
lcdwrd(0x30+dat1[num]);
}
P1=0xf7; //令第四行为0,判断哪一列按下
if(P1!=0xf7)
{
delay(1000);
if(P1!=0xf7)
{
key=P1&0xf0;
switch(key)
{
case 0xe0: num=12;break; //0
case 0xd0: num=13;break; //清除rst
case 0xb0: num=14;break; //等号=
case 0x70: num=15;break; //除/
}
}
while(P1!=0xf7);
switch(num)
{
case 12:
if(flag==0) //没有按下符号键
{
//led=1;
a=a*10+dat1[num];
lcdwrd(0x30);
}
else
{
//led=1;
b=b*10+dat1[num];
lcdwrd(0x30);
}
break;
case 13:
lcdwrc(0x01); //清屏指令
a=0;
b=0;
flag=0;
fuhao=0;
break;
case 15:
flag=1;
fuhao=4;
lcdwrd(0x2f);//除号/
break;
case 14:
if(fuhao==1)//加
{
lcdwrc(0x4f+0x80);
lcdwrc(0x04);//设置光标左移,屏幕不移动
c=a+b;
while(c!=0) //一位一位显示
{
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
}
lcdwrd(0x3d); //显示等于号=
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}
if(fuhao==2) //减
{
lcdwrc(0x4f+0x80);
lcdwrc(0x04);//设置光标左移,屏幕不移动
if(a>b)
c=a-b;
else
c=b-a;
while(c!=0) //一位一位显示
{
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
}
if(a<b) lcdwrd(0x2d); //显示-号
lcdwrd(0x3d); //显示等于号=
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}
if(fuhao==3)//乘法
{
lcdwrc(0x4f+0x80);
lcdwrc(0x04);//设置光标左移,屏幕不移动
c=a*b;
while(c!=0) //一位一位显示
{
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
}
lcdwrd(0x3d); //显示等于号=
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}
if(fuhao==3)//乘法
{
lcdwrc(0x4f+0x80);
lcdwrc(0x04);//设置光标左移,屏幕不移动
c=a*b;
while(c!=0) //一位一位显示
{
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
}
lcdwrd(0x3d); //显示等于号=
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}
if(fuhao==4)
{
k=0;
lcdwrc(0x4f+0x80);
lcdwrc(0x04);//设置光标左移,屏幕不移动
c=(long)(((float)a/b)*1000);//强制转换为long。
while(c!=0) //一位一位显示
{
k++;
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
if(k==3)
{
lcdwrd(0x2e);
k=0;
}
}
if(a/b<0) //如果a比b小的话那么除的结果最高位是0
{
lcdwrd(0x30);
}
lcdwrd(0x3d); //显示等号
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}
break;
}
}
}
void main()
{
lcdinit();
while(1)
{
keyscan();
}
}
三十、孵化环境温湿度监控系统设计
1. 最初版本
#include<reg52.h>
#include "intrins.h"
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit rs=P2^6; // 数据命令选择
sbit rw=P2^5; //读写选择
sbit e=P2^7; //使能
sbit k1=P3^3; //模式
sbit k2=P2^1; //加
sbit k3=P2^2; //减
sbit DHT11_DQ_OUT=P3^2;
sbit led1=P3^6;
sbit led2=P3^7;
sbit dq=P2^0;
uint8 mode=0,xian;
char temph=50,templ=20;
char humih=80,humil=20;
uint8 temp,humi;
uint8 flag; //设定报警标志
uint8 a,c,tempvalue;
uint8 code num[10]="0123456789";
uint8 code str1[]="Temp:"; //温度
uint8 code str2[]="Humi:"; //湿度
uint8 code str3[]="Error";
uint8 code str4[]="Success ";
uint8 code str5[]="%RH";
uint8 code str6[]="TempH:"; //设定温度上限显示
uint8 code str7[]="TempL:"; //设定温度下限显示
uint8 code str8[]="HumiH:"; //设定湿度上限显示
uint8 code str9[]="HumiL:"; //设定湿度下限显示
void delay(uint16 i)
{
while(i--);
}
void delay_ms(uint16 i)
{
while(i--)
delay(90);
}
void wrc(uint8 c) //写命令
{
delay(1000);
rs=0;
rw=0;
e=0;
P0=c;
e=1;
delay(10);
e=0;
}
void wrd(uint8 dat) //写数据
{
delay(1000);
rs=1;
rw=0;
e=0;
P0=dat;
e=1;
delay(10);
e=0;
rs=0;
}
void lcd_init() // LCD1602初始化
{
delay(1000);
wrc(0x38);
wrc(0x38); //功能设置命令,选择8位总线,双行显示 5*7点阵字符
wrc(0x38);
wrc(0x06); //光标和显示模式设置 光标右移 整屏不移动
wrc(0x0c); //显示开关控制 开显示 无光标 光标不闪烁
wrc(0x01); //清零指令 固定的
}
//复位DHT11
void DHT11_Rst()
{
DHT11_DQ_OUT=0; //拉低DQ
delay_ms(20); //拉低至少18ms
DHT11_DQ_OUT=1; //DQ=1
delay(3); //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8 DHT11_Check()
{
uint8 retry=0;
while (DHT11_DQ_OUT&&retry<100)//DHT11会拉低40~50us
{
retry++;
_nop_();
};
if(retry>=100)return 1;
else retry=0;
while (!DHT11_DQ_OUT&&retry<100)//DHT11拉低后会再次拉高40~50us
{
retry++;
_nop_();
};
if(retry>=100)return 1;
return 0;
}
//DHT11初始化
//返回0:初始化成功,1:失败
uint8 DHT11_Init()
{
DHT11_Rst();
return DHT11_Check();
}
//从DHT11读取一个位
//返回值:1/0
uint8 DHT11_Read_Bit(void)
{
uint8 retry=0;
while(DHT11_DQ_OUT&&retry<100)//等待变为低电平 12-14us 开始
{
retry++;
_nop_();
}
retry=0;
while((!DHT11_DQ_OUT)&&retry<100)//等待变高电平 26-28us表示0,116-118us表示1
{
retry++;
_nop_();
}
delay(1);//等待40us
if(DHT11_DQ_OUT)return 1;
else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
uint8 DHT11_Read_Byte(void)
{
uint8 i,dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8 DHT11_Read_Data(uint8 *temp,uint8 *humi)
{
uint8 buf[5];
uint8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}else return 1;
return 0;
}
void ds18b20init() //18b20的初始化
{
dq=1;
delay(1);
dq=0;
delay(80);
dq=1;
delay(5);
dq=0;
delay(20);
dq=1;
delay(35);
}
void ds18b20wr(uint8 dat) //18b20写数据
{
uint8 i;
for(i=0;i<8;i++)
{
dq=0;
dq=dat&0x01;
dat>>=1;
delay(8);//在时序上只有这一块对时序要求最准确,他的时间必须大于15us
dq=1;
delay(1);
}
}
uint8 ds18b20rd() //18b20读数据
{
uint8 value,i;
for(i=0;i<8;i++)
{
dq=0;
value>>=1;
dq=1;
if(dq==1)value|=0x80;
delay(8);//在这一块也对时间要求特别准确,整段程序必须大于60us
}
return value;
}
uint8 readtemp() //读取温度内需要复位的
{
uint8 b;
ds18b20init(); //初始化
ds18b20wr(0xcc); //发送忽略ROM指令
ds18b20wr(0x44); //发送温度转换指令
delay(100);
ds18b20init(); //初始化
ds18b20wr(0xcc); //发送忽略ROM指令
ds18b20wr(0xbe); //发读暂存器指令
a=ds18b20rd(); //温度的低八位
b=ds18b20rd(); //温度的高八位
b<<=4; //ssss s***;s为标志位s=0表示温度值为正数,s=1温度值为负数
c=b&0x80; //温度正负标志位确认
b+=(a&0xf0)>>4;
a=a&0x0f; //温度的小数部分
return b;
}
void key_pros() //按键处理函数
{
if(k1==0)
{
delay(1000);
if(k1==0)
{
mode++;
if(mode==5)mode=0;
wrc(0x01);
}
while(!k1);
}
if(mode==1) //对温度上限设定
{
if(k2==0) //加
{
delay(1000);
if(k2==0)
{
temph++;
if(temph>=80)temph=80;
}
while(!k2);
}
if(k3==0) //减
{
delay(1000);
if(k3==0)
{
temph--;
if(temph<=0)temph=0;
}
while(!k3);
}
}
if(mode==2) //对温度下限设定
{
if(k2==0) //加
{
delay(1000);
if(k2==0)
{
templ++;
if(templ>=80)templ=80;
}
while(!k2);
}
if(k3==0) //减
{
delay(1000);
if(k3==0)
{
templ--;
if(templ<=0)templ=0;
}
while(!k3);
}
}
if(mode==3) //对湿度上限设定
{
if(k2==0) //加
{
delay(1000);
if(k2==0)
{
humih++;
if(humih>=80)humih=80;
}
while(!k2);
}
if(k3==0) //减
{
delay(1000);
if(k3==0)
{
humih--;
if(humih<=0)humih=0;
}
while(!k3);
}
}
if(mode==4) //对湿度下限设定
{
if(k2==0) //加
{
delay(1000);
if(k2==0)
{
humil++;
if(humil>=80)humil=80;
}
while(!k2);
}
if(k3==0) //减
{
delay(1000);
if(k3==0)
{
humil--;
if(humil<=0)humil=0;
}
while(!k3);
}
}
}
void lcd_init_display() //LCD初始化显示
{
uint8 i;
for(i=0;i<5;i++)
{
wrc(0x80+i);
wrd(str1[i]);
}
for(i=0;i<5;i++)
{
wrc(0xc0+i);
wrd(str2[i]);
}
}
void data_pros() //数据处理函数
{
uint8 i;
uint8 temp_buf[2],humi_buf[2];
uint8 temphbuf[2],templbuf[2],humihbuf[2],humilbuf[2];
float dio;
uint16 k;
tempvalue=readtemp();
DHT11_Read_Data(&temp,&humi);
temp_buf[0]=temp/10+0x30;
temp_buf[1]=temp%10+0x30;
humi_buf[0]=humi/10+0x30;
humi_buf[1]=humi%10+0x30;
dio=a*0.0625;
k=dio*10000;//取小数点后两位有效数字
temphbuf[0]=temph/10+0x30;
temphbuf[1]=temph%10+0x30;
templbuf[0]=templ/10+0x30;
templbuf[1]=templ%10+0x30;
humihbuf[0]=humih/10+0x30;
humihbuf[1]=humih%10+0x30;
humilbuf[0]=humil/10+0x30;
humilbuf[1]=humil%10+0x30;
if(mode==0)
{
lcd_init_display();
wrc(0x85);
wrd(num[tempvalue%100/10]);
wrd(num[tempvalue%100%10]);
wrd('.');
wrd(num[k/1000]);
wrd(0xdf);
wrd('C');
for(i=0;i<2;i++)
{
wrc(0Xc5+i);
wrd(humi_buf[i]);
}
for(i=0;i<3;i++)
{
wrc(0Xc7+i);
wrd(str5[i]);
}
}
if(mode==1) //温度上限显示
{
wrc(0x80);
for(i=0;i<6;i++)
{
wrd(str6[i]);
}
wrd(temphbuf[0]);
wrd(temphbuf[1]);
}
if(mode==2) //温度下限显示
{
wrc(0x80);
for(i=0;i<6;i++)
{
wrd(str7[i]);
}
wrd(templbuf[0]);
wrd(templbuf[1]);
}
if(mode==3) //湿度上限显示
{
wrc(0x80);
for(i=0;i<6;i++)
{
wrd(str8[i]);
}
wrd(humihbuf[0]);
wrd(humihbuf[1]);
}
if(mode==4) //湿度下限显示
{
wrc(0x80);
for(i=0;i<6;i++)
{
wrd(str9[i]);
}
wrd(humilbuf[0]);
wrd(humilbuf[1]);
}
}
void baojinpros() //报警处理
{
if(tempvalue>=temph||humi>=humih) //检测温度或者湿度高于设定上限值 降温湿
{
led1=1; //降温湿指示灯
led2=0;
}
if(tempvalue<=templ||humi<=humil) //检测温度或者湿度低于设定下限值 升温湿
{
led1=0;
led2=1; //升高温湿指示灯
}
if((tempvalue>templ&&tempvalue<temph)&&(humi>humil&&humi<humih))
{
led1=0;
led2=0;
}
}
void main()
{
uint8 i=0;
led1=0;
led2=0;
lcd_init();
while(DHT11_Init()) //检测DHT11是否存在
{
for(i=0;i<5;i++)
{
wrc(0x80+i);
wrd(str3[i]);
}
}
wrc(0x01);
lcd_init_display(); //LCD初始化显示
i=0;
while(1)
{
i++;
key_pros();
baojinpros(); //报警处理
if(i==15)
{
i=0;
data_pros(); //读取一次DHT11数据最少要大于100ms
}
delay(1000);
}
}