Программа дисплея на сдвиговых регистрах
- Войдите на сайт для отправки комментариев
Доброго времени суток! Собрал четырёхразрядный дисплей на регистрах 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
Это схема

Видимо, не совсем непредсказуемо, а "наоборот"? Т.е. позиция точки правильная если считать не слева направо, а справа налево. Так?
Если так, попробуйте её перевернуть. Вы же все цифры перевернули, а точка чем хуже?
Вместо
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 displayFloat(uint8_t pin, float val, uint8_t precision, bool padZeros) { uint8_t dot = 0x08; // !!!!! while (precision) { val *= 10; --precision; dot >>= 1; // !!!!!! } displayInt(pin, (int)val, padZeros, dot);Отпишите, что вышло и, если проблема не ушла, пожалуйста проведите такой эксперимент.
1. Возьмите одно и то же число в последовательно выведите его с точностями от 0 до 3.
2. Зафискисруйте и опишите в какую позицию попадала при этом точка (при каждой точности).
Уж и не думал, что тема оживёт! Спасибо за совет, на днях всё испробую, отпишусь. Дисплей у меня работает, но точка ведёт себя непостижимым образом. Я пока сделал так: Раз в функцию displayInt передаётся переменная dot (я так понимаю, это маска точек), я пробовал организовать вывод информации этой функцией, но вручную загонял в неё 0b00001111. Должна же работать, нет, так удаётся засветить только точки в третьем и четвёртом разряде. Первый- горит всегда, второй-никогда. Возвращаю библиотечный файл в исходный вид, разряды "переворачиваются", за то точки моим способом (да и штатным тоже) попадают на свои разряды. И точка второго раряда оживает! Первый по-прежнему горит постоянно. Вобщем, я голову сломал. Теперь сделаю как советуете и опишу точно результат. Сам принцип такой схемы мне интересен. Только мне предстоит понять суть построения программы для него, чтобы я мог, например, увеличить количество разрядов. Библиотеку, видимо писали опытные программисты, могли что-то упростить, сократить, а в результате код мне не понятен.