仿真 代码 原理图 PCB实物已设计整理好!各位下载可直接使用
这是本人做的关于51单片机的一个小设计,主要将论坛里的温度报警器和计算器代码进行了整合,简单的说可以当做计算器使用也可以当做温度报警器使用。PCB也对各个版本进行了优化,原理图划分了功能块方便看不懂的小伙伴,这主要针对一些不会做手工PCB的小伙伴,而且现在立创和捷配的打样活动也比自己手工做PCB成本低很多,鉴于能白嫖就白嫖的原则,请大家不要错过。
功能简单介绍:
一、温度报警器功能
插电后打开开关(开关可直接短接)初始化完成后LCD1602第一行居中显示实时温度,第二行显示HT:60 LT:2表示默认设置的温度上限以及下限,若温度超过上限或者低于下限值,对应led发光以提示用户。按下k2键,可进入温度报警器的设置模式,此时lcd显示屏幕上第一行最末尾出现H或者L,表示此时可按K3,K4对对应的HT或者LT的上下限值进行加减来改变报警阈值,并且这三个按键按下时蜂鸣器会有响声提醒。
二、计算器功能
按下K1键可切换为计算器模式,此时矩阵键盘生效,lcd显示屏幕清空,进入计算器模式,矩阵键盘上PCB丝印字体对应按键按下的值。其余不多做解释,按照正常计算器玩法操作。再按下K1键可切换回温度报警器模式。
代码篇幅有限,这里不做介绍,上传文件中可自行查阅。有其他建议联系我哈。
制作出来的实物图如下:
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:
- /*******************************************************************************
- * 标题: LCD1602简易计算器 *
- * *
- * 实验说明:1602简易计算器,可以实现四位数以内的加减乘除, *
- ********************************************************************************
- * 实验心得:当内部ram不够用的时候,可以定义成xdata,使用外部ram,但是有一个问题*
- 就是在用proteus仿真的时候,如果有xdata的代码,可能仿真会出现点问题,因为peoteus*
- 不支持外部扩展ram *
- ********************************************************************************/
- #include<reg52.h>
- #include"lcd.h"
- #include"math.h"
- #include"temp.h"
- #include"intrins.h"
- //--定义使用的IO口--//
- #define GPIO_KEY P1
- sbit K_set=P3^3;
- sbit K_up=P3^5;
- sbit K_down=P3^6;
- sbit bee_key=P3^7;
- sbit ledL=P2^3;
- sbit ledH=P2^4;
- unsigned char setting_flag=0,up_flag=0,down_flag=0;
- //--定义全局变量--//
- unsigned char code XuJian[16]="01470258=369+-x/";
- long value[16];
- unsigned char Num[8];//此处写成unsigend char xdata Num[8]时,实物可以用,但是仿真有点问题,因为proteus不支持外部扩展ram.
- unsigned long result;//运算结果
- unsigned int flag=0;//标志位
- unsigned int m;
- unsigned int c=0;
- long First=0;//输入的第一位数
- long Second=0;//输入的第二位数
- unsigned int Key;//符号判断,如果key=12,为+,13,为-,14为×,15为/。
- unsigned char KeyValue=-1;
- //用来存放读取到的键值
- //--声明全局函数--//
- int KeyScan(void);//键值判断函数
- void Delay10ms(unsigned int c); //误差 0us
- void RES();//结果运算函数
- //
- //模式切换标致
- unsigned char moshi_flag=0,temp_max=60,temp_min=2,lcd_flag=0;
- unsigned int temp=0;
- uchar code Init1[]=" DB:000 "; //初始化时1行显示
- uchar code Init2[]=" HT:000 LT:000 "; //初始化时2行显示
- void Init1602_temp()
- {
- uchar i=0;
- LcdWriteCom(0x38);//屏幕初始化
- LcdWriteCom(0x0c);//打开显示 无光标 无光标闪烁
- LcdWriteCom(0x06);//当读或写一个字符是指针后一一位
- LcdWriteCom(0x01);//清屏
- LcdWriteCom(0x80);//设置位置
- for(i=0;i<16;i++)
- {
- LcdWriteData(Init1[i]); //1行初始化显示
- }
- LcdWriteCom(0x80+0x40);
- for(i=0;i<16;i++)
- {
- LcdWriteData(Init2[i]);//2行初始化显示
- }
- }
- //显示实时温度
- void display_temp(unsigned int temp)
- {
- unsigned char a,b,c;
-
- a=temp/1000%10;
- b=temp/100%10;
- c=temp/10%10;
-
- LcdWriteCom(0x80+7);
- LcdWriteData(a+0x30);
- LcdWriteData(b+0x30);
- LcdWriteData('.');
- LcdWriteData(c+0x30);
- }
- //显示温度上下限
- void display_temp_M(unsigned char temp_max,unsigned char temp_min)
- {
- unsigned char a,b,c;
- a=temp_max/100;
- b=temp_max/10%10;
- c=temp_max%10;
- LcdWriteCom(0x80+0x40+5);
- LcdWriteData(a+0x30);
- LcdWriteData(b+0x30);
- LcdWriteData(c+0x30);
- a=temp_min/100;
- b=temp_min/10%10;
- c=temp_min%10;
- LcdWriteCom(0x80+0x40+12);
- LcdWriteData(a+0x30);
- LcdWriteData(b+0x30);
- LcdWriteData(c+0x30);
- }
- void Delay500us() //@11.0592MHz
- {
- unsigned char i, j;
- _nop_();
- _nop_();
- i = 6;
- j = 93;
- do
- {
- while (--j);
- } while (--i);
- }
- void bee_anjian(unsigned int c )
- {
- unsigned char a, b;
- bee_key=0;
- //--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
- for (;c>0;c--)
- {
- bee_key=!bee_key;
- Delay500us();
-
- }
- bee_key=0;
- }
- void temp_scan()//按键扫描
- { unsigned char dis_play_flag=0;
- if(K_set==0) //判断设置是否按下
- {
- Delay10ms(1);
- if(K_set==0)
- { bee_key=0;
- setting_flag=setting_flag+1;
- dis_play_flag=1;
- if(setting_flag>2)
- {setting_flag=0;}
- // bee_anjian(100);
- //bee_anjian(100);
- Delay10ms(50);
-
- }
- }
- if(dis_play_flag)
- {
-
- if(setting_flag==1)
- {
- LcdWriteCom(0x80+15);
- LcdWriteData('H');
- }
- else if(setting_flag==2)
- {
- LcdWriteCom(0x80+15);
- LcdWriteData('L');
- }
- else
- {
- LcdWriteCom(0x80+15);
- LcdWriteData(' ');
- }
- dis_play_flag=0;
-
- }
- if(setting_flag) //设置按下
- {
- if(K_up==0)
- {
- Delay10ms(1);
- if(K_up==0)
- {
- bee_key=0;
- up_flag=1;
- }
- }
- }
- if(setting_flag)
- {
- if(K_down==0)
- {
- Delay10ms(1);
- if(K_down==0)
- {
- bee_key=0;
- down_flag=1;
- }
- }
- }
- if(up_flag==1)
- {
- if(setting_flag==1)
- {
- temp_max=temp_max+1;
- if(temp_max>99)
- {temp_max=99;}
- display_temp_M(temp_max,temp_min);
-
- // bee_anjian(50);
- //bee_anjian(100);
- Delay10ms(50);
- up_flag=0;
- }
- else if(setting_flag==2)
- {
- temp_min=temp_min+1;
- if(temp_min>99)
- {temp_min=99;}
- display_temp_M(temp_max,temp_min);
- // bee_anjian(50);
- //bee_anjian(100);
- Delay10ms(50);
- up_flag=0;
- }
- }
- if(down_flag==1)
- {
- if(setting_flag==1)
- {
- temp_max=temp_max-1;
- if(temp_max<1)
- {temp_max=1;}
- display_temp_M(temp_max,temp_min);
- Delay10ms(50);
- // bee_anjian(100);
- down_flag=0;
- }
- else if(setting_flag==2)
- {
- temp_min=temp_min-1;
- if(temp_min<1)
- {temp_min=1;}
- display_temp_M(temp_max,temp_min);
- Delay10ms(50);
- //bee_anjian(100);
- down_flag=0;
- }
- }
- bee_key=1;
- }
- //中断函数初始化
- void Init_INT()
- {
- IT0 = 1; //设置为下降沿触发
- EX0 = 1; //外部中断0中断允许位
- EA = 1;
- }
- void EX0_ISR(void) interrupt 0 //中断服务函数的书写格式
- {
-
- moshi_flag=!moshi_flag;
- lcd_flag=moshi_flag+1;
-
-
- }
- /*******************************************************************************
- * 函 数 名 : main
- * 函数功能 : 主函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void main(void)
- {
- LcdInit();
- // for(i=0;i<7;i++)
- // {
- // LcdWriteData(TiShi[i]);
- // }
- Init_INT();//开启外部中断
- Init1602_temp();
- bee_anjian();
- while(1)
- {
- if(lcd_flag==1)
- {
- Init1602_temp();
- lcd_flag=0;
- }
- else if(lcd_flag==2)
- {
- LcdInit();
- lcd_flag=0;
- }
- if(moshi_flag==1)
- {
- KeyValue=KeyScan();
- switch(KeyValue)
- {
- case(0):
- LcdWriteCom(0x01);
- KeyValue=-1;
- First=0;
- Second=0;
- c=0;
- break;
- case(1):
- if(flag==0)//flag为0时,正常计算
- {
- LcdWriteData(XuJian[1]);
- KeyValue=-1;
- if(c==0)
- First=10*First+1;
- else if(c==1)
- Second=10*Second+1;
- }
- else if(flag==1)//flag为1时,可以在第一次运算好后,继续输入数字,开始第二次计算
- {
- LcdWriteCom(0x01);
- LcdWriteData(XuJian[1]);
- KeyValue=-1;
- First=0;
- Second=0;
- c=0;
- flag=0;
-
- ................限于篇幅代码请下载附件................
- do
- {
- value[i]=result%10;
- result/=10;
- i++;
- }while((result/10)!=0);
- value[i]=result;
- m=i;
- for(j=0;j<=i;j++) //for循环如果是for(j=i;j>=0;j++)就会出现不同的结果,很奇怪
- {
- Num[j]=value[j]+'0';
- }
- for(i=0;i<=m;i++)//这里的for循环也是和上面一样的结果,改成for(i=m;i>=0;i--)就会出现奇怪的结果,有兴趣的可以试试。
- {
- LcdWriteData(Num[m-i]);
- }
-
- }
- /*******************************************************************************
- * 函 数 名 : KeyScan
- * 函数功能 : 检测有按键按下并读取键值
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- int KeyScan(void) //测试行(row)的时候就是线是竖着的的那一列为1,测试列(col)的时候就是线是横着的那几行为1
- {
- char a = 0;
- GPIO_KEY=0x0f;
- if(GPIO_KEY!=0x0f)//读取按键是否按下
- {
- Delay10ms(1);//延时10ms进行消抖
- if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
- {
-
- //测试列
- GPIO_KEY=0X0F;
- switch(GPIO_KEY)
- {
- case(0X07): KeyValue=0;break;
- case(0X0b): KeyValue=4;break;
- case(0X0d): KeyValue=8;break;
- case(0X0e): KeyValue=12;break;
- }
- //测试行
- GPIO_KEY=0XF0;
- switch(GPIO_KEY)
- {
- case(0X70): KeyValue=KeyValue+3;break;
- case(0Xb0): KeyValue=KeyValue+2;break;
- case(0Xd0): KeyValue=KeyValue+1;break;
- case(0Xe0): KeyValue=KeyValue;break;
- }
- while((a<50) && (GPIO_KEY!=0xf0)) //检测按键松手检测
- {
- Delay10ms(1);
- a++;
- }
- }
- }
- return KeyValue;
- }
- /*******************************************************************************
- * 函 数 名 : Delay10ms
- * 函数功能 : 延时函数,延时10ms
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Delay10ms(unsigned int c) //误差 0us
- {
- unsigned char a, b;
- //--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
- for (;c>0;c--)
- {
- for (b=38;b>0;b--)
- {
- for (a=130;a>0;a--);
- }
- }
- }
复制代码
所有资料51hei提供下载:
温度报警加简易计算器资料.7z
(3.52 MB, 下载次数: 76)
|