某宝上买的实验面包板和四位LED数码管到货了,继续折腾我的Arduino UNO R3。为了这货上周某天下班路上心血来潮还去买了一盒乐高给它搭了一个外壳。
先看下效果吧。偷懒了不用74HC595了,但这几乎耗尽了全部GPIO。
这次买到的四位数码管是共阴的3641AS,共12个引脚。其中第12、9、8、6脚分别为第一、二、三、四位的选中信号,其余的为8段(7段+小数点)显示管。发光的前提是,段引脚加高电平,Unit选择引脚是低电平。
举例而言,比如要仅仅显示第二位的小数点,则可以:
第一步,Unit 2脚,也就是第9脚设为低电平,其12脚、6脚、8脚都设为高电平(或处于断路状态,如果用自己的电源做测试的话)
第二步,DP脚,也就是第3脚设为高电平,其余脚设置为低电平。
同理,如果要显示1.8,则需要轮流显示Unit 1的1.(注意要显示小数点),以及Unit 2的8。其实每次只显示一位,但由于速度足够快,肉眼认为是在同时显示。
第一步,12脚低电平,其余片选脚高电平,使得Unit被选中。
第二步,11脚(a)、7脚(b)加高电平,3脚(dp)也加高电平,其余段码脚低电平,使得显示“1”和小数点;
第三步,9脚低电平,其余片选脚高电平,使得Unit 2被选中;
第四步,a到g脚全部高电平,dp脚低电平。
如果要显示更多位,继续片选和相应的段码电平设置。
以上只是理论上的,真要这么做可能会出现所谓的“鬼影”,也就是每个显示的数字有相互间的影响,导致显示起来有一种诡异的效果,看不清到底是在显示什么。通常需要在片选动作之前或之后先做一次全部不显示的操作。
温度继续用18B20。做这个实验如果实在没温度探头也没关系,自己指定一个需要被显示的float数就行。本实验的接线方式在上图中已有提示。漏了标注温度探头的接线,是连在A0上的。代码头部的注释也可以参考。
代码如下。有个缺点是隔段时间就暗一下用来采样,暂时还没想到什么解决办法,留着将来再改进下。
/*
Unit1 A1
Unit2 A2
Unit3 A3
Unit4 A4
A-G,DP 3-10
A0 18B20's data pin
*/
#include
#include
#define TempSensor A0
OneWire oneWire(TempSensor);
DallasTemperature sensors(&oneWire);
#define EyesDelay 1
void SelectUnit(int ID)
{
switch (ID)
{
case 1:
digitalWrite(A1, LOW);
digitalWrite(A2, HIGH);
digitalWrite(A3, HIGH);
digitalWrite(A4, HIGH);
break;
case 2:
digitalWrite(A1, HIGH);
digitalWrite(A2, LOW);
digitalWrite(A3, HIGH);
digitalWrite(A4, HIGH);
break;
case 3:
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A3, LOW);
digitalWrite(A4, HIGH);
break;
case 4:
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A3, HIGH);
digitalWrite(A4, LOW);
break;
default:
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A3, HIGH);
digitalWrite(A4, HIGH);
break;
}
}
void ShowData(int UnitID, char * data)
{
SelectUnit(UnitID);
for (int i = 0; i < 8; i++)
{
if (data[i] == '0')
{
digitalWrite(i + 3, LOW);
}
else
{
digitalWrite(i + 3, HIGH);
}
}
}
void ShowNone()
{
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A3, HIGH);
digitalWrite(A4, HIGH);
for (int i = 3; i <= 10 ; i++)
{
digitalWrite(i, LOW);
}
}
void Show(int UnitID, char a)
{
ShowNone();
switch (a)
{
case '0':
ShowData(UnitID, "11111100");
break;
case '1':
ShowData(UnitID, "01100000");
break;
case '2':
ShowData(UnitID, "11011010");
break;
case '3':
ShowData(UnitID, "11110010");
break;
case '4':
ShowData(UnitID, "01100110");
break;
case '5':
ShowData(UnitID, "10110110");
break;
case '6':
ShowData(UnitID, "10111110");
break;
case '7':
ShowData(UnitID, "11100000");
break;
case '8':
ShowData(UnitID, "11111110");
break;
case '9':
ShowData(UnitID, "11110110");
break;
case '.':
ShowData(UnitID, "00000001");
break;
case '-':
ShowData(UnitID, "00000010");
break;
default:
ShowNone();
break;
}
delay(EyesDelay);
}
void setup() {
// put your setup code here, to run once:
for (int i = 3; i <= 10; i++)
{
pinMode(i, OUTPUT);
}
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
pinMode(A4, OUTPUT);
sensors.begin();
}
void ShowTemp(float val)
{
char buf[8];
for (int i = 0; i < 8; i++)
{
buf[i] = '\0';
}
dtostrf(val, 1, 3, buf);
if (buf[1] == '.') //0.123
{
Show(1, buf[0]);
Show(1, '.');
Show(2, buf[2]);
Show(3, buf[3]);
Show(4, buf[4]);
}
if (buf[2] == '.') //11.12
{
Show(1, buf[0]);
Show(2, buf[1]);
Show(2, '.');
Show(3, buf[3]);
Show(4, buf[4]);
}
if (buf[3] == '.') //111.12
{
Show(1, buf[0]);
Show(2, buf[1]);
Show(3, buf[2]);
Show(3, '.');
Show(4, buf[4]);
}
if (buf[4] == '.') //1112.12
{
Show(1, buf[0]);
Show(2, buf[1]);
Show(3, buf[2]);
Show(4, buf[3]);
Show(4, '.');
}
}
void loop() {
// Get 18B20 Data
sensors.requestTemperatures();
float t = sensors.getTempCByIndex(0);
delay(1000);
for (int i = 0; i < 600; i++)
{
ShowTemp(t);
}
ShowNone();
}