Программа дисплея на сдвиговых регистрах
- Войдите на сайт для отправки комментариев
Доброго времени суток! Собрал четырёхразрядный дисплей на регистрах 595 по схеме с сайта Амперки. При трассировке печатной платы неверно понял задумку автора и перепутал регистры местами. Вместо 1->2->3->4 сделал 4-3-2-1. Дисплей заработал, но цифры стал показывать в обратном порядке (что и понятно). Плату портить не хочется, полез в библиотеку QuadDislay (а управление регистрами как-то хитро сделано, на один всё провод). В файле QuadDislay.h ничего интересно не обнаружил, там только маски цифр, а вот в QuadDislay.cpp нашел функцию
void displayDigits(uint8_t pin, uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4) { pinMode(pin, OUTPUT); //turnOffPWM work here: digitalWrite(pin, HIGH); sendByte(pin, digit4);//Здесь было digit1 sendByte(pin, digit3);//Здесь было digit2 sendByte(pin, digit2);//Здесь было digit3 sendByte(pin, digit1);//Здесь было digit4 latch(pin); }
И поправил в ней порядок загрузки цифр в регистры. Всё заработало верно, кроме функции
void displayFloat(uint8_t pin, float val, uint8_t precision, bool padZeros) { uint8_t dot = 0x1; while (precision) { val *= 10; --precision; dot <<= 1; } displayInt(pin, (int)val, padZeros, dot);
Которая призвана выводить дробные числе с заданой точностью. При разных значениях точности, точка ведёт себя непредсказуемо, но в свой разряд не попадает. Так вот вопрос, кто б мне помог библиотеку поправить, чтоб точка на место встала, или объясните, где я загнался!?
Это файл срр
#include <Arduino.h> #include "QuadDisplay.h" #include "pins_arduino.h" #ifndef _VARIANT_ARDUINO_DUE_X_ #define MACRO_DIGITAL_WRITE(a,b) (fastDigitalWrite(a,b)) //Fast version of digitalWrite, without using turnOffPWM // void fastDigitalWrite(uint8_t pin, uint8_t val) { //uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *out; if (port == NOT_A_PIN) return; // If the pin that support PWM output, we need to turn it off // before doing a digital write. // DELETED. Timer is already off here . Amperka // if (timer != NOT_ON_TIMER) turnOffPWM(timer); out = portOutputRegister(port); uint8_t oldSREG = SREG; cli(); if (val == LOW) { *out &= ~bit; } else { *out |= bit; } SREG = oldSREG; } #else #define MACRO_DIGITAL_WRITE(a,b) (digitalWrite(a,b)) #endif const static uint8_t numerals[] = {QD_0, QD_1, QD_2, QD_3, QD_4, QD_5, QD_6, QD_7, QD_8, QD_9}; static void sendByte(uint8_t pin, byte data, byte n = 8) { for (byte i = n; i > 0; i--) { if (data & 1) { noInterrupts(); MACRO_DIGITAL_WRITE(pin, LOW); MACRO_DIGITAL_WRITE(pin, HIGH); interrupts(); delayMicroseconds(30); } else { MACRO_DIGITAL_WRITE(pin, LOW); delayMicroseconds(15); MACRO_DIGITAL_WRITE(pin, HIGH); delayMicroseconds(60); } data >>= 1; } } static void latch(uint8_t pin) { MACRO_DIGITAL_WRITE(pin, LOW); delayMicroseconds(60); MACRO_DIGITAL_WRITE(pin, HIGH); delayMicroseconds(300); } void displayDigits(uint8_t pin, uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4) { pinMode(pin, OUTPUT); //turnOffPWM work here: digitalWrite(pin, HIGH); sendByte(pin, digit4);//Здесь было digit1 sendByte(pin, digit3);//Здесь было digit2 sendByte(pin, digit2);//Здесь было digit3 sendByte(pin, digit1);//Здесь было digit4 latch(pin); } void displayClear(uint8_t pin) { displayDigits(pin, QD_NONE, QD_NONE, QD_NONE, QD_NONE); } void displayInt(uint8_t pin, int val, bool padZeros, uint8_t dots) { uint8_t digits[4] = {0xff, 0xff, 0xff, 0xff}; if (!padZeros && !val) digits[3] = numerals[0]; else { bool negative = val < 0; val = abs(val); int8_t i; for (i = 4; i--; ) { uint8_t digit = val % 10; digits[i] = (val || padZeros) ? numerals[digit] : 0xff; val /= 10; if (!val && !padZeros) break; } if (negative) digits[max(0, i-1)] = QD_MINUS; for (i = 4; i--; ) { if (dots & (1 << i)) digits[4 - i] &= QD_DOT; } } displayDigits(pin, digits[0], digits[1], digits[2], digits[3]); } void displayFloat(uint8_t pin, float val, uint8_t precision, bool padZeros) { uint8_t dot = 0x1; while (precision) { val *= 10; --precision; dot <<= 1; } displayInt(pin, (int)val, padZeros, dot); } void displayTemperatureC(uint8_t pin, int val, bool padZeros) { uint8_t digits[4] = {0xff, 0xff, QD_DEGREE, QD_C}; if (!padZeros && !val) digits[1] = numerals[0]; else { bool negative = val < 0; val = abs(val); int8_t i; for (i = 2; i--; ) { uint8_t digit = val % 10; digits[i] = (val || padZeros) ? numerals[digit] : 0xff; val /= 10; if (!val && !padZeros) break; } if (negative) digits[max(0, i-1)] = QD_MINUS; } displayDigits(pin, digits[0], digits[1], digits[2], digits[3]); }
Это файл .h
/* * Copyright (c) 2014 by Amperka LLC * QuadDisplay Driver Library * Authors: * - Victor Nakoryakov <victor at amperka.ru> * * This file is free software; you can redistribute it and/or modify * it under the terms of either the GNU General Public License version 2 * or the GNU Lesser General Public License version 2.1, both as * published by the Free Software Foundation. */ #ifndef QUAD_DISPLAY #define QUAD_DISPLAY #include <inttypes.h> /* ___7___ / \ | | 2| |6 \___1___/ / \ | | 3| |5 \___4___/ *0 */ #define QD_NONE 0b11111111 #define QD_DOT 0b11111110 #define QD_MINUS 0b11111101 #define QD_UNDERSCORE 0b11101111 #define QD_DEGREE 0b00111001 #define QD_0 0b00000011 #define QD_1 0b10011111 #define QD_2 0b00100101 #define QD_3 0b00001101 #define QD_4 0b10011001 #define QD_5 0b01001001 #define QD_6 0b01000001 #define QD_7 0b00011111 #define QD_8 0b00000001 #define QD_9 0b00001001 #define QD_A 0b00010001 #define QD_a 0b00000101 #define QD_b 0b11000001 #define QD_C 0b01100011 #define QD_c 0b11100101 #define QD_d 0b10000101 #define QD_E 0b01100001 #define QD_f 0b01110001 #define QD_F QD_f #define QD_H 0b10010001 #define QD_h 0b11010001 #define QD_I QD_1 #define QD_J 0b10001111 #define QD_L 0b11100011 #define QD_n 0b11010101 #define QD_o 0b11000101 #define QD_O QD_0 #define QD_P 0b00110001 #define QD_r 0b11110101 #define QD_S 0b01001001 #define QD_t 0b11100001 #define QD_u 0b11000111 #define QD_U 0b10000011 #define QD_Y 0b10001001 void displayInt(uint8_t pin, int val, bool padZeros=false, uint8_t dots=0x00); void displayFloat(uint8_t pin, float val, uint8_t precision, bool padZeros=false); void displayDigits(uint8_t pin, uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4); void displayClear(uint8_t pin); void displayTemperatureC(uint8_t pin, int val, bool padZeros=false); #endif
Это схема
Видимо, не совсем непредсказуемо, а "наоборот"? Т.е. позиция точки правильная если считать не слева направо, а справа налево. Так?
Если так, попробуйте её перевернуть. Вы же все цифры перевернули, а точка чем хуже?
Вместо
напишите
Отпишите, что вышло и, если проблема не ушла, пожалуйста проведите такой эксперимент.
1. Возьмите одно и то же число в последовательно выведите его с точностями от 0 до 3.
2. Зафискисруйте и опишите в какую позицию попадала при этом точка (при каждой точности).
Уж и не думал, что тема оживёт! Спасибо за совет, на днях всё испробую, отпишусь. Дисплей у меня работает, но точка ведёт себя непостижимым образом. Я пока сделал так: Раз в функцию displayInt передаётся переменная dot (я так понимаю, это маска точек), я пробовал организовать вывод информации этой функцией, но вручную загонял в неё 0b00001111. Должна же работать, нет, так удаётся засветить только точки в третьем и четвёртом разряде. Первый- горит всегда, второй-никогда. Возвращаю библиотечный файл в исходный вид, разряды "переворачиваются", за то точки моим способом (да и штатным тоже) попадают на свои разряды. И точка второго раряда оживает! Первый по-прежнему горит постоянно. Вобщем, я голову сломал. Теперь сделаю как советуете и опишу точно результат. Сам принцип такой схемы мне интересен. Только мне предстоит понять суть построения программы для него, чтобы я мог, например, увеличить количество разрядов. Библиотеку, видимо писали опытные программисты, могли что-то упростить, сократить, а в результате код мне не понятен.