74HC595 с 4-значным 7-сегментным дисплеем. Есть ли способ избавиться от ведущих нулей?
Я работаю над считывателем температуры на базе Arduino, используя ИС температуры DS18B20. Дисплей представляет собой 4-значный 7-сегментный светодиодный дисплей с общим анодом, управляемый одним сдвиговым регистром 74HC595. В настоящее время он настроен на считывание переменной, назначенной числом, для тестирования части дисплея. Он отображает число с точностью до десятых долей после запятой, но у меня возникают проблемы при попытке избавиться от ведущих нулей. Когда переменной 'tempF' присваивается число, например 12.3, дисплей выдает 012.3, а если переменной присваивается число, например 1.2, дисплей выдает 001.2. В то же время я хотел, чтобы она ставила знак минус (-), когда число меньше нуля. Пока что примеры, которые я нахожу в Интернете, не соответствуют коду, с которым я сейчас работаю, или вообще не работают. Я не смог найти скетч, который бы работал для этого типа установки. Я разместил ниже код, с которым я работаю. Оригинальный код был получен по ссылке, указанной в скетче.
В скетче не предусмотрены средства считывания отрицательных температур или подавления ведущих нулей.
/*
* www.pial.net/arduino-controlling-a-4-digit-seven-segment-display/
*/
//#include <OneWire.h>
//#include <DallasTemperature.h>
//#define ONE_WIRE_BUS 2
//OneWire oneWire(ONE_WIRE_BUS);
//DallasTemperature sensors(&oneWire);
//DeviceAddress insideThermometer;
const int ledPin = 13;// LED connected to digital pin 13
const int latchPin = 8;//Pin connected to ST_CP of 74HC595
const int clockPin = 9;//Pin connected to SH_CP of 74HC595
const int dataPin = 10;//Pin connected to DS of 74HC595
const int digitPins[4] = {
3,4,5,6}; //pins to control the 4 common anode pins of the display
const byte digit[10] = //seven segment digit bits
{
B00111111, //0
B00000110, //1
B01011011, //2
B01001111, //3
B01100110, //4
B01101101, //5
B01111101, //6
B00000111, //7
B01111111, //8
B01101111, //9
// B00000000, //all segments off
// B01000000 //-
};
int digitBuffer[4] = {
1};
int digitScan = 0;
int soft_scaler = 0;
float tempC, tempF;
int tmp;
void setup() {
TCCR2A = 0;
TCCR2B = (1<<CS21);
TIMSK2 = (1<<TOIE2);
TCNT2 = 0;
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
for(int i=0;i<4;i++)
{
pinMode(digitPins[i],OUTPUT);
}
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
// sensors.begin();
// sensors.getAddress(insideThermometer, 0);
}
ISR(TIMER2_OVF_vect) {
soft_scaler++;
if(soft_scaler==15)
{
refreshDisplay();
soft_scaler = 0;
}
};
void refreshDisplay()
{
for(byte k=0;k<4;k++)
{
digitalWrite(digitPins[k], LOW);
}
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, B11111111);
digitalWrite(latchPin, HIGH);
delayMicroseconds(50);
digitalWrite(digitPins[digitScan], HIGH);
digitalWrite(latchPin, LOW);
// if (digitScan==3)
// {
// shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitBuffer[digitScan]] | B00000000)); //inserting the blank
// }
// else
// {
// shiftOut(dataPin, clockPin, MSBFIRST, digit[digitBuffer[digitScan]]);
// }
if(digitScan==1)
{
shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitBuffer[digitScan]] | B10000000)); //inserting the dot
}
else
{
shiftOut(dataPin, clockPin, MSBFIRST, ~digit[digitBuffer[digitScan]]);
}
digitalWrite(latchPin, HIGH);
digitScan++;
if(digitScan>3) digitScan=0;
}
void loop()
{
digitalWrite(ledPin, HIGH);
boolean sign = false;
//sensors.requestTemperatures();
//tempC = sensors.getTempC(insideThermometer);
//tempF = DallasTemperature::toFahrenheit(tempC);
//tmp = int(tempF*100);
tempF = 0.2;
tmp = int(tempF*10);
// if (digitScan == 4 ){
// shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitScan] | B00000000)); //inserting the blank
// }
// else
// {
// shiftOut(dataPin, clockPin, MSBFIRST, digit[digitBuffer[digitScan]]);
// }
//if (tmp < 0){
//sign = true;
//tmp = abs(tmp);
//}
//if (digitScan == 3) {
// if (tmp < 0){
// shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitBuffer[digitScan]] | B01000000)); // outputs minus sign
// }
// else {
// shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitBuffer[digitScan]] | B00000000));
// }
// tmp = abs(tmp);
// }
// else if (digitScan == 3 && digit[digitScan-1] == 0) { // writing on the second display (tens; if there are none, outputs nothing)
// shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitBuffer[digitScan]] | B00000000));
// }
// else if (i == 2) { // writing on the third display, where decimal point is needed
// shiftOut(data_pin, clk_pin, MSBFIRST, digit[digitBuffer[i-1]]);
// }
// else { // writing on "other" displays (in fact fourth display AND seecond display only if there are some tens)
// shiftOut(data_pin, clk_pin, MSBFIRST, digit[digitBuffer[i-1]]);
// }
digitBuffer[3] = int(tmp)/1000;
digitBuffer[2] = (int(tmp)%1000)/100;
digitBuffer[1] = (int(tmp)%100)/10;
digitBuffer[0] = (int(tmp)%100)%10;
Serial.print("number assigned to the variable 'tmp' = ");
Serial.println(tmp);
Serial.print("number assigned to the variable 'tempF' = ");
Serial.println(tempF);
digitalWrite(ledPin, LOW);
delay(500);
}
Закомментированные команды в скетче были попытками удалить ведущие нули и добавить знак минус, когда это было необходимо, но не увенчались успехом. Я также разместил схему проекта. Микросхема 74HC595 была использована таким образом, чтобы освободить выводы для последующего использования в проекте глубокой заморозки.
Я ни в коем случае не являюсь опытным программистом, но если кто-то может помочь мне или дать какое-то представление о том, как решить эту проблему, я буду очень признателен.
Конечно, но два условия должны быть верны:
у вас есть информация о шрифте для "blank"; для этого вам нужно снять комментарий в коде.
вам нужно избавиться от ведущих нулей после вычисления буфера дисплея.
редактировать:
вот пример реализации концепции, описанной выше, на PIC12F675, управляющем двумя HC595. Число, которое нужно вывести на 4-значный дисплей - "12". Бланкирование сделано на первых трех цифрах -> вы можете убедиться в этом, посмотрев на значение дисплейного буфера lRAM[4]. 0x11 - это мой обозначитель пробела.
Неполное отображение '1' обусловлено мультиплексированием. Код в основном основан на том, что я написал здесь: https://dannyelectronics.wordpress.com/2017/03/03/driving-7-segment-leds/, модифицированный для управления через HC595s.
Это должно работать на любой микросхеме с минимальными изменениями.
edit 2: вот ваш код, управляющий CC дисплеем напрямую. число, которое должно отображаться на дисплее, 1.23, с убранными ведущими нулями в старших двух цифрах.