Electronics > Projects, Designs, and Technical Stuff

16 bit to 4 digit 7 segment decoder

<< < (11/16) > >>

Buriedcode:
Wow, these solutions are varied but have run away.   I'm unsure of the exact restrictions, but 30 5V IO, ease of use and cost, I will stand by an Atmega8515.  $2.50, has Arduino support if you're up for fast development, easily available etc.. you just need current limiting resistors for the segments and maybe transistors for the commons (but often you can just drive from the IO) and thats it.  Why all the glue logic and memories?

Sure you could use a CPLD, but quite a lot of the cells will be used to store your 16-bit data, plus they tend to be more expensive than an MCU (especially the 5V tolerant ones).

GeorgeOfTheJungle:

--- Quote from: Buriedcode on December 23, 2019, 07:35:38 pm ---Wow, these solutions are varied but have run away.   I'm unsure of the exact restrictions, but 30 5V IO, ease of use and cost, I will stand by an Atmega8515.  $2.50, has Arduino support if you're up for fast development, easily available etc..

--- End quote ---

A blue pill can do it as well and it's faster, smaller and only $1. Just sayin'  :)

westfw:
Lots of ~40pin micros are in the $1 range and could do this fine.  Some in DIPs, even (Atmega4809 is currently cheaper than ATmega8515, and ATmega32as are available for about $0.75 on Aliexpress...

Or two smaller microcontrollers with a serial link between them (extensible!) - it's a human-readable display, right?  It doesn't need to update as fast as the inputs can change...

obiwanjacobi:
Yep, just for debugging and verification at very low clock rates. I also want a latch signal on there as well in order to be able to capture specific bus events.

I have ordered the ATmega8515 to give it a try. (waiting...)

obiwanjacobi:
Made a breadboard test setup and used an Arduino Uno to program the Atmega8515. Came up with something like this.



Have a quick and dirty Arduino sketch that demonstrates it working.

I have setup a timer interrupt to do the multiplexing and the main loop just reads in the two ports and bit-shifts it into 4 digit (volatile) variables that are used by the timer interrupt to display.

I am now building a perf board to test it further and actually use it - see if I come up with more features.

I made a quick PCB layout and routing and could get all traces on one side  8)

I will put it on my github when its a little less rough...


--- Code: ---const uint8_t DecoderTable_size = 17;
uint8_t DecoderTable[DecoderTable_size] =
    {
        0b00000001,
        0b01111110,
        0b00001100,
        0b10110110,
        0b10011110,
        0b11001100,
        0b11011010,
        0b11111010,
        0b00001110,
        0b11111110,
        0b11001110,
        0b11101110,
        0b11111000,
        0b01110010,
        0b10111100,
        0b11110010,
        0b11100010,
};

uint8_t decode7(uint8_t value)
{
  if (value >= DecoderTable_size)
    return DecoderTable[0];

  return DecoderTable[value + 1];
}

void outputDigit4(uint8_t value, int digit)
{
  uint8_t cathode = ~(1 << digit) & 0x0F;
  uint8_t b = (PORTB & 0xF0);

  PORTD = 0;
  PORTB = b | cathode;
  PORTD = decode7(value);
}

// digit values that will be displayed
// timer interrupt will drive 7-seg
const uint8_t digitValue_size = 4;
// 0-3 => left to right
volatile uint8_t _digitValue[digitValue_size];

// what digit are we writing?
volatile uint8_t _digitIndex;

// called when ORC1A is reached
ISR(TIMER1_COMPA_vect)
{
  outputDigit4(_digitValue[_digitIndex], _digitIndex);

  if (_digitIndex < digitValue_size)
  {
    _digitIndex++;
  }
  else
  {
    _digitIndex = 0;
  }
}

void setupTimer()
{
  OCR1A = 0x1FF;
  TCCR1B |= 0b010;        // prescaler: CS1[2:0]
  TCCR1B |= (1 << WGM12); // CTC mode
  TIMSK |= (1 << OCIE1A); // enable interrupt
}

void setupPorts()
{
  // input sampling ports
  DDRA = 0;
  DDRC = 0;

  // 7-seg drivers
  DDRB |= 0x0F;
  DDRD = 255;
}

void setup()
{
  setupTimer();
  setupPorts();
  sei();
}

void printDigit16(uint8_t msb, uint8_t lsb)
{
  _digitValue[0] = msb >> 4;
  _digitValue[1] = msb & 0x0F;
  _digitValue[2] = lsb >> 4;
  _digitValue[3] = lsb & 0x0F;
}

void loop()
{
  uint8_t msb = PINA;
  uint8_t lsb = PINC;

  printDigit16(msb, lsb);
}

int main()
{
  setup();
  while (true)
  {
    loop();
  }
}

--- End code ---

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod