Fixed data corruption issue due to incorrect PROGMEM usage

Added switchable shift register order
Added potentiometer-controlled delay for demonstration purposes
This commit is contained in:
Mark van Renswoude 2016-11-27 23:14:17 +01:00
parent 2e1cb6e054
commit 4c16260e55
6 changed files with 136 additions and 32 deletions

View File

@ -4,26 +4,36 @@ SegmentDisplay* display;
void setup()
{
pinMode(A3, INPUT);
display = new SegmentDisplay();
//display->setClockSpeed(4000000UL);
display->setDigits(2);
display->setClockPin(12);
display->setDataPin(11);
display->setLatchPin(10);
display->setDigits(6);
display->begin();
}
unsigned long currentTime;
unsigned long lastCounterTime = 0;
uint32_t counter = 0;
uint32_t delayValue;
void loop()
{
unsigned long currentTime = millis();
currentTime = millis();
if (currentTime - lastCounterTime > 1000UL)
if (currentTime - lastCounterTime > 100UL)
{
counter++;
if (counter > 99)
if (counter > 999999)
counter = 0;
lastCounterTime = currentTime;
delayValue = ((uint32_t)analogRead(A3) * 100);
display->setDigitDelayMicroseconds(delayValue);
}
display->writeNumber(counter);

View File

@ -1,10 +1,12 @@
#include "SegmentDisplayConfig.h"
#include "SegmentDisplay.h"
void SegmentDisplay::begin()
{
#if !defined(SDSupportSPI)
pinMode(latchPin, OUTPUT);
#if !defined(SDUseSPI)
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
@ -12,11 +14,13 @@ void SegmentDisplay::begin()
digitalWrite(dataPin, LOW);
#endif
writeDisplay(0, 0);
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
digitalWrite(latchPin, HIGH);
#if defined(SDSupportSPI)
#if defined(SDUseSPI)
SPI.begin();
#endif
}
@ -24,7 +28,7 @@ void SegmentDisplay::begin()
void SegmentDisplay::end()
{
#if defined(SDSupportSPI)
#if defined(SDUseSPI)
SPI.end();
#endif
}
@ -64,15 +68,15 @@ void SegmentDisplay::writeText(char* value)
// Lowercase
if (charValue >= ASCIILowercaseA && charValue <= ASCIILowercaseZ)
writeDisplay(SDCharacterSegments[charValue - ASCIILowercaseA], digitMask);
writeDisplay(pgm_read_byte_near(SDCharacterSegments + (charValue - ASCIILowercaseA)), digitMask);
// Uppercase
else if (charValue >= ASCIIUppercaseA && charValue <= ASCIIUppercaseZ)
writeDisplay(SDCharacterSegments[charValue - ASCIIUppercaseA], digitMask);
writeDisplay(pgm_read_byte_near(SDCharacterSegments + (charValue - ASCIIUppercaseA)), digitMask);
// Numbers
else if (charValue >= ASCIIZero && charValue <= ASCIINine)
writeDisplay(SDNumberSegments[charValue - ASCIIZero], digitMask);
writeDisplay(pgm_read_byte_near(SDNumberSegments + (charValue - ASCIIZero)), digitMask);
// Space / unknown
else
@ -95,29 +99,43 @@ void SegmentDisplay::writeText(char* value)
inline void SegmentDisplay::writeDigit(byte value, byte digitMask)
{
writeDisplay(SDNumberSegments[value], digitMask);
delayMicroseconds(digitDelayMicroseconds);
writeDisplay(pgm_read_byte_near(SDNumberSegments + value), digitMask);
if (digitDelayMicroseconds > 1000)
delay(digitDelayMicroseconds / 1000);
else
delayMicroseconds(digitDelayMicroseconds);
}
#if defined(SDSupportSPI)
#if defined(SDUseSPI)
inline void SegmentDisplay::writeDisplay(byte characterMask, byte digitMask)
inline void SegmentDisplay::writeDisplay(byte segmentMask, byte digitMask)
{
SPI.beginTransaction(SPISettings(clockSpeed, MSBFIRST, SPI_MODE0));
SPI.transfer(characterMask);
#if defined(SDPushSegmentsFirst)
SPI.transfer(segmentMask);
SPI.transfer(digitMask);
#else
SPI.transfer(digitMask);
SPI.transfer(segmentMask);
#endif
SPI.endTransaction();
}
#else
inline void SegmentDisplay::writeDisplay(byte characterMask, byte digitMask)
inline void SegmentDisplay::writeDisplay(byte segmentMask, byte digitMask)
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, characterMask);
#if defined(SDPushSegmentsFirst)
shiftOut(dataPin, clockPin, MSBFIRST, segmentMask);
shiftOut(dataPin, clockPin, MSBFIRST, digitMask);
#else
shiftOut(dataPin, clockPin, MSBFIRST, digitMask);
shiftOut(dataPin, clockPin, MSBFIRST, segmentMask);
#endif
digitalWrite(latchPin, HIGH);
}

View File

@ -1,28 +1,27 @@
#ifndef SegmentDisplay_h
#define SegmentDisplay_h
#include "SegmentDisplayConfig.h"
#include "Arduino.h"
#if defined(SDUseSPI)
#include "SPI.h"
#endif
#include "SegmentDisplayChars.h"
/**
* Drives up to 8 digits using two 8-bit shift registers.
*
* Pushes out the segment bits first and the display selection
* second: connect the display select register first and chain the
* segment register to it's output.
* Least significant bit ends up at output pin 0 of the shift register,
* which correlates to Segment A (as defined in SegmentDisplayChars.h).
* The last digit is also assumed to be at output pin 0 of the chained
* shift register.
*
* Least significant bit ends up at pin 0, which correlates to
* (as defined in SegmentDisplayChars.h):
* - Last digit
* - Segment A
* The order in which the shift registers are chained is determined by
* (un)defining SDPushSegmentsFirst.
**/
// Comment to use shiftOut. Set clockPin and dataPin instead.
//#define SDSupportSPI
class SegmentDisplay
{
public:
@ -41,12 +40,12 @@ class SegmentDisplay
uint32_t getDigitDelayMicroseconds() { return digitDelayMicroseconds; }
void setDigitDelayMicroseconds(uint32_t value) { digitDelayMicroseconds = value; }
#if defined(SDSupportSPI)
#if defined(SDUseSPI)
uint32_t getClockSpeed() { return clockSpeed; }
void setClockSpeed(uint32_t value) { clockSpeed = value; }
#endif
#if !defined(SDSupportSPI)
#if !defined(SDUseSPI)
uint32_t getClockPin() { return clockPin; }
void setClockPin(uint32_t value) { clockPin = value; }
@ -63,11 +62,11 @@ class SegmentDisplay
uint32_t digitDelayMicroseconds = 1000;
uint32_t latchPin = SS;
#if defined(SDSupportSPI)
#if defined(SDUseSPI)
uint32_t clockSpeed = 20000000;
#endif
#if !defined(SDSupportSPI)
#if !defined(SDUseSPI)
uint32_t clockPin = SCK;
uint32_t dataPin = MOSI;
#endif

26
SegmentDisplayConfig.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef SegmentDisplayConfig_h
#define SegmentDisplayConfig_h
/**
* Enable SPI support
*
* If not defined, shiftOut will be used. Use setClockPin and
* setDataPin instead to change the defaults.
*
* When using SPI, use setClockSpeed to match your target.
**/
//#define SDUseSPI
/**
* Shift register chaining order
*
* If defined, the segment mask is pushed out first followed
* by the digit mask. In other words, connect D1, D2, etc to
* the first shift register and A, B, etc to the second.
*
* If not defined, the order is reversed.
**/
//#define SDPushSegmentsFirst
#endif

View File

@ -1,4 +1,6 @@
Top view
D1 A F D2 D3 B
__|__|__|__|__|__|__
| |
@ -11,6 +13,22 @@
E D DP C G
Bottom view
B D3 D2 F A D1
__|__|__|__|__|__|__
| |
| |
| |
| |
| |
|_____ __ __ __ __ __|
| | | | |
G C DP D E
Pin Assignment
1 E Bottom Left

View File

@ -0,0 +1,33 @@
O1 O2 O3 O4 O5 O6 O7 O8 GND
__|____|____|____|____|____|____|____|____|__
| |
| |
|\ |
|/ |
| |
|__ ____ ____ ____ ____ ____ ____ ____ ____ __|
| | | | | | | | |
I1 I2 I3 I4 I5 I6 I7 I8 VCC
Pin Assignment
1 I1
2 I2
3 I3
4 I4
5 I5
6 I6
7 I7
8 I8
9 VCC
10 GND Ground
11 O8
12 O7
13 O6
14 O5
15 O4
16 O3
17 O2
18 O1