前几天做好了板子 最近几天一直在写程序
经过几天的奋斗(并不) 总算写完了!
俗话说: 电路简单 程序就麻烦 我算是体会到了 555
以后再也不图省事了 软件可比硬件让人头大多啦!
这个温度计所有的显示部分都是一个IO来控制 用的型号是STC15W104 扩展用的2片 74HC595
当时看中它的程序空间大 结果其实也没那么大,嘎嘎 结果EEPROM只有1K了
温度
湿度
最大最小值显示,这里显示的是最大温度
好了 进入正题 我先自吹自擂一下 (啊?! 谁扔的臭鸡蛋!)
从左到右 三个按钮 1 2 3
按钮1:短按 查看最大最小温湿度 每按一次切换显示1个 这些数据全部存储在内部的FlashRom中 会自动更新
长按 清除内部FlashRom存储的数据 并用当前的测量值全部填充
按钮2:显示模式轮换,三个模式:温湿度自动轮换 仅温度 仅湿度
其中温湿度自动轮换时间可调 显示的数值是每次切换温湿度的时候测量的
仅温度 仅湿度 这两个的数据是 每半秒更新一次(不可调 但是可以在编译前调好,我设置的是半秒)
这2个模式貌似每次更新的时候 LED会闪一下 没办法 设计缺陷555 谁叫他1个IO干完全部的显示呢?
按钮3:切换自动轮换的时间 ,我设置了3个挡位 2.5s 5s 10s ,同时这个还会自动存储在FlashROM里,只需要设定时间一次~~
P.S 最后加点感想: 这次又学到了很多东西,还专门写了2个C文件模块,模块化编程好啊~ 赞美C语言!
昨天晚上写这个程序,写的头很大,来来回回删了又写写了又删 ,起码删了300行,可谓是绞尽脑汁,我那10毫升的大脑都要变成浆糊啦!
今晚折腾出来了 我甚开心,赶紧拍下照片发帖留念了,MCU的世界真是美妙....我永远喜欢单片机!
单片机源程序如下:
- #include "stc15f2k60s2.h"
- #include "dht11.h"
- #include "iaprom.h"
- #define u8 unsigned char
- #define u16 unsigned int
- u8 code SMGtable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//最后这个是负号
- void IOinit();
- void LEDsDisplay(u8 Number,u8 position);
- void Timer0Init();
- void hc595activate();
- void hc595send (u8 sbyte);
- void Delay10ms();
- void AllDisplay(u8 Integer,u8 Decimal);
- void keyscan();
- void CheckMaxMin();
- void NormalMode();
- void TemponlyMode();
- void HumionlyMode();
- void ModeInit();
- void ModeSelect(); //选择3种模式
- void ViewMaxMin(); //查看最大最小温湿度
- sbit LCHCK=P3^2; //595的时钟
- sbit SFTCK=P3^3;
- sbit sb1=P3^4; //MaxMin按钮1 检查max min,4 组数据切换,长按清空flash存储区
- sbit sb2=P3^5; //mode按钮sb2 切换模式 湿度温度自动切换 长温度 长湿度
- sbit sb3=P3^0; //切换时间sb3 自动切换时间调整 2.5S 5S 10S 三档 50 100 200
- extern bit TempPoOrNe; //温度正负位
- bit TempHumiSelect=1; //1=Temp 0=Humi
- int Temp,Humi;
- u8 Time50ms=0; //50ms标志位
- u8 SetTimes=50; //设定的时间 分别是 50(默认) 100 200
- u8 SetMode=0x00; //模式标志位 分别为 0x00 0x11 0x22 自动切换 长温度 长湿度
- u8 ConditionLeds=0x0f; //后4位控制4个LED灯泡的亮灭 0x01 MAX ,0x02 Min ,0x04 Temp ,0x08 Humi
- void main()
- {
- IOinit();
- Delay1000ms();//延时1s 等待传感器就位
- Timer0Init(); //定时器0初始化
- EA=1;ET0=1; //开中断,开定时器0中断
- GetTempAndHumi(); // 先读取一次温湿度
- ModeInit(); //从ROM中读取mode 进行初始化
- while(1)
- {
- ModeSelect(); //选择模式 每个模式也负责读取温度
- CheckMaxMin();
- keyscan();
- }
- }
- void keyscan()
- {
- if(sb1==0||sb2==0||sb3==0)
- {
- Delay10ms();
- if(sb1==0)
- {
- Timer0Init();
- Time50ms=0;
- while(!sb1);
- Delay10ms();
- if(Time50ms>20) //>1000ms
- {
- IapEraseSector(0x0000);
- IapProgramWord(0x0000,Temp);
- IapProgramWord(0x0002,Humi);
- IapProgramWord(0x0004,Temp);
- IapProgramWord(0x0006,Humi);
- }
- else
- {
- ViewMaxMin(); //短按操作
- }
- Timer0Init(); //复位中断
- Time50ms=0;
- }
- if(sb2==0) //切换模式
- {
- if(SetMode==0x00) SetMode=0x11;
- else if(SetMode==0x11) SetMode=0x22;
- else if(SetMode==0x22) SetMode=0x00;
- else SetMode=0x00;
- while(!sb2);
- Delay10ms();
- IapEraseSector(0x0200); //擦除扇区
- IapProgramByte(0x0200,SetMode); //写入更改后的模式
- Time50ms=0;
- }
- if(sb3==0&&SetMode==0x00) //调整自动切换时间 2.5s 5s 10s
- {
- while(!sb3);
- Delay10ms();
- if(SetTimes==50) SetTimes=100;
- else if(SetTimes==100) SetTimes=200;
- else if(SetTimes==200) SetTimes=50;
- else SetTimes=50;
- }
- }
- }
- void CheckMaxMin() //将读取到的温度湿度和存储的最大最小值对比,如果有更大/更小的,就写入
- {
- int MaxTemp,MaxHumi,MinTemp,MinHumi;
- Temp=TempInteger*10+TempDecimal; //把温度转化带正负的Int 如24.4 -> 244
- if(TempPoOrNe!=1) Temp=Temp*-1; //判断温度正负
- Humi=HumiInteger*10+HumiDecimal; //湿度转化 ,其实可以用无符号 因为湿度是不可能是负数.但是我偷懒了
- MaxTemp=IapReadWord(0x0000); //从Rom中读取一些参数 做个留存保护
- MaxHumi=IapReadWord(0x0002);
- MinTemp=IapReadWord(0x0004);
- MinHumi=IapReadWord(0x0006);
- if(Temp>MaxTemp||Temp<MinTemp||Humi>MaxHumi||Humi<MinHumi) //如果需要更新
- {
- IapEraseSector(0x0000);
- if(Temp>MaxTemp) IapProgramWord(0x0000,Temp); else IapProgramWord(0x0000,MaxTemp);
- if(Temp<MinTemp) IapProgramWord(0x0004,Temp); else IapProgramWord(0x0004,MinTemp);
- if(Humi>MaxHumi) IapProgramWord(0x0002,Humi); else IapProgramWord(0x0002,MaxHumi);
- if(Humi<MinHumi) IapProgramWord(0x0006,Humi); else IapProgramWord(0x0006,MinHumi);
- }
-
- }
- void ModeInit()
- {
- SetMode=IapReadByte(0x0200);
- }
- void ViewMaxMin() //查看最大最小
- {
- int cache;
- u8 cache1,cache2;
- Time50ms=0;
- while(sb1) //有按下就会继续往下执行 否则return
- {
- ConditionLeds=0x05; //最大温度灯亮
- cache=IapReadWord(0x0000);
- if(cache<0)
- {
- TempPoOrNe=0;
- cache=cache*-1;
- }
- else TempPoOrNe=1;
- cache1=cache/10;cache2=cache%10;
- AllDisplay(cache1,cache2);//这是最大温度
- if(Time50ms>100)
- {
- Time50ms=0;
- GetTempAndHumi();
- TempHumiSelect=1;
- return; //五秒不再按按钮就会自动退出
- }
- }
- Delay10ms(); //按键消抖
- while(!sb1); //等你松手
- Delay10ms(); //按键消抖
- Time50ms=0;
- while(sb1) //等你继续按下
- {
- ConditionLeds=0x09; //最大湿度灯亮
- cache=IapReadWord(0x0002);
- cache1=cache/10;cache2=cache%10;
- AllDisplay(cache1,cache2);//这是最大温度
- if(Time50ms>100)
- {
- Time50ms=0;
- GetTempAndHumi();
- TempHumiSelect=1;
- return; //五秒不再按按钮就会自动退出
- }
- }
- Delay10ms(); //按键消抖
- while(!sb1); //等你松手
- Delay10ms(); //按键消抖
- Time50ms=0;
- while(sb1) //等你继续按下
- {
- ConditionLeds=0x06; //最小温度
- cache=IapReadWord(0x0004);
- if(cache<0)
- {
- TempPoOrNe=0;
- cache=cache*-1;
- }
- else TempPoOrNe=1;
- cache1=cache/10;cache2=cache%10;
- AllDisplay(cache1,cache2);//这是最小温度
- if(Time50ms>100)
- {
- Time50ms=0;
- GetTempAndHumi();
- TempHumiSelect=1;
- return; //五秒不再按按钮就会自动退出
- }
- }
- Delay10ms(); //按键消抖
- while(!sb1); //等你松手
- Delay10ms(); //按键消抖
- Time50ms=0;
- while(sb1) //等你继续按下
- {
- ConditionLeds=0x0a;
- cache=IapReadWord(0x0006);
- cache1=cache/10;cache2=cache%10;
- AllDisplay(cache1,cache2);//这是最小湿度
- if(Time50ms>100)
- {
- Time50ms=0;
- GetTempAndHumi();
- TempHumiSelect=1;
- return; //五秒不再按按钮就会自动退出
- }
- }
- Delay10ms(); //按键消抖
- while(!sb1); //等你松手
- GetTempAndHumi();
- Delay10ms(); //按键消抖
- TempHumiSelect=1;
- Time50ms=0;
- }
- void NormalMode() //常规模式
- {
- if(TempHumiSelect)
- {
- ConditionLeds=0x04; //亮温度灯
- AllDisplay(TempInteger,TempDecimal);
- }
- else
- {
- ConditionLeds=0x08; //亮湿度灯
- AllDisplay(HumiInteger,HumiDecimal);
- }
- if(Time50ms>SetTimes)
- {
- Time50ms=0;
- TempHumiSelect=~TempHumiSelect;
- GetTempAndHumi();//每次切换时读取一次温湿度
- }
- }
- void TemponlyMode() //仅温度
- {
- ConditionLeds=0x04; //亮温度灯
- AllDisplay(TempInteger,TempDecimal);
- if(Time50ms>10) //500ms
- {
- Time50ms=0;
- GetTempAndHumi();//每次切换时读取一次温湿度
- }
- }
- void HumionlyMode() //仅湿度
- {
- ConditionLeds=0x08; //亮湿度灯
- AllDisplay(HumiInteger,HumiDecimal);
- if(Time50ms>10) //500ms
- {
- Time50ms=0;
- GetTempAndHumi();//每次切换时读取一次温湿度
- }
- }
- void ModeSelect()
- {
- if(SetMode==0x00) NormalMode();
- else if(SetMode==0x11) TemponlyMode();
- else if(SetMode==0x22) HumionlyMode();
- else NormalMode();
- }
- void IOinit(void)
- {
- //P3 0 1 2 3 4 5 x x
- // 阻 默 默 默 阻 阻 x x
- //M1 1 0 0 0 1 1 x x
- //M0 0 0 0 0 0 0 x x
- P3M1=0x31;
- P3M0=0x00;
- }
- void LEDsDisplay(u8 Number,u8 position) //在单个数码管和所有led灯珠显示内容 ,会自动在第三位上加上小数点
- {
- u8 i=0,j=0xf0;
- i=(clrbit(j,position+3))+ConditionLeds; // 计算需要输出的位选+led指示灯亮灭情况
- hc595send(i); //发送位选和状态显示灯状态位
- if(position==3) hc595send(SMGtable[Number]|0x80); //第三位加个小数点
- else hc595send(SMGtable[Number]);
- hc595activate();
- }
- void AllDisplay(u8 Integer,u8 Decimal) //扫描显示所有4个数码管和led灯珠 //也进行显示正负
- {
- if(TempPoOrNe!=1)
- {
- LEDsDisplay(10,1); //显示负号位 ,否则不显示
- }
- if(Integer/10%10!=0) //判断十位是否需要消隐
- {
- LEDsDisplay(Integer/10%10,2); //十位
- }
- LEDsDisplay(Integer/1%10,3); //个位
- LEDsDisplay(Decimal/1%10,4); //小数点后1位
- }
- void Timer0Init() // 50ms @12Mhz 计时器0初始化
- {
- AUXR &= 0x7F; //12T
- TMOD &= 0xF0;
- TL0 = 0xB0;
- TH0 = 0x3C;
- TF0 = 0;
- TR0 = 1;
- }
- void Timer0 () interrupt 1 //计时器0中断
- {
- Time50ms++;
- }
- void hc595send (u8 sbyte) //移位输出8位数据至移位寄存器中 高位先进入移位寄存器
- {
- u8 i=0;
- for(i=0;i<8;i++)
- {
- SFTCK=0;
- dat11=getbit(sbyte,7-i);
- SFTCK=1;
- }
- }
- void hc595activate() //让595输出寄存器输出移位寄存器保存的结果
- {
- LCHCK=0;
- LCHCK=1;
- LCHCK=0;
- }
- void Delay10ms() //@12.000MHz 软延时10ms
- {
- unsigned char i, j;
- i = 117;
- j = 184;
- do
- {
- while (--j);
- } while (--i);
- }
复制代码
最后就是程序 仅供学习
禁止其他任何用途(如作业等)
不然与本人初衷不符
全部资料51hei下载地址:
温湿度计.zip
(6.15 KB, 下载次数: 31)
|