- /*
- 功能:显示0-70℃范围室内温度,分辨0.5℃
- 采用红色超高亮度共阳的4位数码管,以及输出平衡程序代码,使得数码管之间亮度基本平衡
- 温度计随着电源电压波动会产生较大误差,按照USB口输出电池电压4.7V设计;如果脱机使用3节5号电池供电,电压4.0-4.5V,这时温度显示会偏高
- */
- //把部分模拟口改成数字口:A0~A5对应D15~D19
- int a = 15;//设置A1口连接数码管a段
- int b = 19;//设置A5口连接数码b段
- int c = 7;//设置D7口连接数码管c段
- int d = 5;//设置D5口连接数码管d段
- int e = 4;//设置D4口连接数码管e段
- int f = 16;//设置A2口连接数码管f段
- int g = 8;//设置D8口连接数码管g段
- int dp = 6;//设置D6口连接数码管dp段
- int tempPin = 7;//lm35信号端连接A7
- int d1 = 14;//设置A0口连接第一个数码管公共阴极
- int d2 = 17;//设置A3口连接第二个数码管公共阴极
- int d3 = 18;//设置A4口连接第三个数码管公共阴极
- int d4 = 9;//设置D9口连接第四个数码管公共阴极
- //设置变量
- int n = 0;//设置温度的变量
- int del = 2; //此处数值对各位数码管之间的亮度进行微调,越大该位数码管越亮
- unsigned long m=0;//设置一个消除数码管频繁闪亮的计时器变量
-
- //以下用数组给数码管的管脚赋值,程序很简洁
- byte segs[7] = { a, b, c, d, e, f, g };//将除了小数点外的7段笔划作为一个数组
- byte seven_seg_digits[10][7] = { { 1,1,1,1,1,1,0 },//设置数码管显示0的数组
- { 0,1,1,0,0,0,0 },//设置数码管显示1的数组
- { 1,1,0,1,1,0,1 },//设置数码管显示2的数组
- { 1,1,1,1,0,0,1 },//设置数码管显示3的数组
- { 0,1,1,0,0,1,1 },//设置数码管显示4的数组
- { 1,0,1,1,0,1,1 },//设置数码管显示5的数组
- { 1,0,1,1,1,1,1 },//设置数码管显示6的数组
- { 1,1,1,0,0,0,0 },//设置数码管显示7的数组
- { 1,1,1,1,1,1,1 },//设置数码管显示8的数组
- { 1,1,1,1,0,1,1 }//设置数码管显示9的数组
- };
- /****************************初始化设置函数****************************/
- void setup()
- {
- pinMode(d1, OUTPUT); //设置引脚为输出状态
- pinMode(d2, OUTPUT); //同上
- pinMode(d3, OUTPUT); //同上
- pinMode(d4, OUTPUT); //同上
- pinMode(a, OUTPUT); //同上
- pinMode(b, OUTPUT);// 同上
- pinMode(c, OUTPUT);// 同上
- pinMode(d, OUTPUT);// 同上
- pinMode(e, OUTPUT);// 同上
- pinMode(f, OUTPUT);// 同上
- pinMode(g, OUTPUT);// 同上
- pinMode(dp, OUTPUT);// 同上
- pinMode(11, OUTPUT);//设置蜂鸣器输出状态
- digitalWrite(11, LOW);//蜂鸣器关闭
- Serial.begin(9600);//设置模拟口的采样频率
- }
- /***************************主程序(循环)******************************/
- void loop()//运行程序
- {
- //float tempval= (3.5* analogRead(tempPin))*1000/1024;//将温度传感器获得的电压模拟量赋值给变量temval
- //从模拟口A0输入温度传感器LM35的温度转换电压,0℃:0V,+1℃:+10mV
- //float tempval=analogRead(tempPin)* 4.88;//5V电压,是理想的电源电压
- float tempval=analogRead(tempPin)* 4.6;//4.7V,是电脑USB口输出的实测电压
- //float tempval=analogRead(tempPin)* 4.0;//4.1V,3节5号电池电压
- // float tempval=map(10*analogRead(tempPin),0,460,0,220);//数值区间影射函数,把一个区间的数值,线性地影射到另一个区间;这里把模拟输出采集的数值0-300(应该是0-200左右),影射到0℃-100℃,因为有一位小数,故乘以10
- if (m%30==0) n=int(tempval); //设定温度的刷新时间为0.3秒,也可消除数码管闪烁的语句
- /*数码管闪烁的原因是因为采样速率高达9600,所以温度数值变化很快,而数据处理产生近似值不是连续的,导致显示数值经常闪烁,影响读数。
- 如果用延时方法,则数码管的最右边数字特别亮,其他数字亮度很低,所以采用自设的计时器“m”,用求余数除法,过30个计时单位才采集一次显示温度数值,有效地消除了闪烁现象,并且不影响程序的正常运行*/
- if (n>300) digitalWrite(11, HIGH);//大于30度时,蜂鸣器报警
- if (n<=300) digitalWrite(11, LOW);//小于30度时,蜂鸣器停止鸣叫
- //以下显示温度的数值,可显示xxx.x℃
- clearLEDs();//数码管数字显示清屏
- delay(del);//延时2ms(为什么是2ms)
- lightSegments(n/1000%10);//显示百位数值
- //如果到100度,这位数码管点亮
- pickDigit((n/1000%10>0));//如果不到100度,则这位数码管熄灭
-
- clearLEDs();//数码管数字显示清屏
- delay(del);//延时2sm
- pickDigit(2); //点亮第二个数码管
- lightSegments(n/100%10);//显示十位数值
- delay(del+2);//延时增加50%,以增加这个数码管的亮度
-
- clearLEDs();//数码管数字显示清屏
- pickDigit(3);//左边第三个数码管点亮
- lightSegments(n/10%10);//显示个位数值
- dispDec(3);//这个数码管要有小数点(哪个?)
- delay(del+2);//这个数码管增加亮度
-
- clearLEDs();//数码管数字显示清屏
- delay(del);//这个数码管亮度减弱
- pickDigit(4);//点亮左边第四个数码管
- lightSegments(n%10);//显示十分位数值
- delay(del-1);//这个数码管减少亮度
- m++;//消除数码管闪烁的计时器变量
-
- //发送到串口监视窗口,以便观察变量数值
- Serial.println(analogRead(tempPin));//串口调试器显示A7引脚读取数值
- Serial.println(n);//串口调试器显示温度数值
- }
- /*实测结果表明,这个温度计受电源电压的影响较大,原因是LM35自带稳压,工作电压:4V-20V,输出电压稳定;当电池电压降低后,这个稳定的电压在模拟口的输出数值就会增大,导致误差;此外,由于模拟口的分别率只有1024级,温度数值的误差也大*/
- /*****************************打开数码管子函数**************************/
- void pickDigit(int x) //定义pickDigit(x),轮流打开4位数码管中的一个
- {
- digitalWrite(d1, LOW);//共阳极数码管,LOW则关闭
- digitalWrite(d2, LOW);//共阳极数码管,LOW则关闭
- digitalWrite(d3, LOW);//共阳极数码管,LOW则关闭
- digitalWrite(d4, LOW);//共阳极数码管,LOW则关闭
- switch(x)
- {
- case 1:
- digitalWrite(d1, HIGH); //打开最左边的高位数码管,即数码管的百位
- break;
- case 2:
- digitalWrite(d2, HIGH); //打开最左边的高位数码管,即数码管的十位
- break;
- case 3:
- digitalWrite(d3, HIGH); //打开最左边的高位数码管,即数码管的个位
- break;
- case 4:// default: //打开最左边的高位数码管,十分位
- digitalWrite(d4, (m%100>=30)); //用余数的区间产生数字闪烁,周期大概是1秒,30%的时间熄灭
- //这样便于观察结果,特别是温度保持不变的时候,给人以设备正常运行的感觉
- //这个方法也可用在时钟里,可产生闪烁的效果,通过模的数值和条件的改变,得到各种闪烁效果
- break;
- }
- }
- /*****************************点亮小数点子函数*************************/
- void dispDec(int x)
- {
- digitalWrite(dp, LOW);//点亮小数点
- }
- /******************************清屏子函数******************************/
- void clearLEDs()
- {
- for (int i = 0; i < 7; i++) //变量i在0到6直接变化
- {
- digitalWrite(segs[i], HIGH);//共阳数码管,笔画段高电平熄灭
- }
- digitalWrite(dp, HIGH);//小数点熄灭
- }
- /***********************点亮对应数字的数码管*************************/
- void lightSegments(int x) //数码管显示数字子函数
- {
- for (int i = 0; i < 7; i++) //变量在0到6之间变化
- {
- digitalWrite(segs[i], 1-seven_seg_digits[x][i]);//由于笔画字段是按照共阴级数码管编写的,这里要用算术转换成共阳极数码管的输出结果
- }
- }
复制代码
【效果】最终效果图如下