4

I have created a 8x8 LED Matrix that is controlled by a mircocontroller (specifically Atmega8), an 8-bit shift register (HEF4794), and a driver array (MIC2981). The problem I having is that the pattern that is supposed to be displayed is not centered. It needs to be shifted to the left one column and down two rows. Any help would be much appreciated.

I got the idea for this project from here: http://www.instructables.com/id/LED-matrix-using-shift-registers/

/*
 * AVRGCC3.c
 *
 * Created: 4/28/2012 1:39:29 PM
 *  Author: Scott
 */ 

#define F_CPU 12000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "font8x8.h"

#define ShiftPort   PORTC
#define ShiftDDR    DDRC
#define LatchPin    (1 << 0)
#define DataPin     (1 << 1)
#define ClkPin      (1 << 2)
#define OE          (1 << 3)

#define RowPort     PORTD
#define RowDDR      DDRD
#define RowPin0     (1 << 0)
#define RowPin1     (1 << 1)
#define RowPin2     (1 << 2)
#define RowPin3     (1 << 3)
#define RowPin4     (1 << 4)
#define RowPin5     (1 << 5)
#define RowPin6     (1 << 6)
#define RowPin7     (1 << 7)

#define ScrollSpeed 75  //How many milliseconds to pause before shifting columns left

typedef unsigned char u8;
typedef unsigned int u16;

u8 row_track = 0;

volatile u8 row_buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

void Delay_ms(int cnt)  //Function delays a give number of milliseconds.  Depends on F_CPU being defined
{
  while (cnt-->0) _delay_ms(1);
}   

static inline void InitPorts(void)  //Function used once to initialize the ports
{
  ShiftDDR |= (LatchPin | ClkPin | DataPin | OE);   //Setup shift register control pins
  RowDDR |= (RowPin0 | RowPin1 | RowPin2 | RowPin3 | RowPin4 | RowPin5 | RowPin6 | RowPin7); //Setup row driver pins

  ShiftPort |= OE;
  RowPort |= RowPin0;               //Drive first row and enable shift registers

  ShiftPort |= LatchPin;                //Set latch pin high
  ShiftPort &= ~(ClkPin | DataPin);             //Set ClkPin and DataPin low
}

static inline void InitTimers(void) //Function used once to set up the timer
{
  TCCR1B |= 1<<WGM12 | 1<<CS11 | 1<<CS10;       //Start timer1 in CTC mode with prescaler of 64
  TIMSK |= 1<<OCIE1A;                   //Enable compare match interrupt
  OCR1A = 0x00BB;                   //Set compare value for 1 mSec
  sei();                        //Enable global interrupts
}

void Shift_Int(u8 shiftData)        //Function used to shift in data
{
  ShiftPort &= ~(LatchPin | ClkPin | DataPin);      //All pins low: LatchPin low signals a write operation

  for (char i=0; i<8; i++)
  {
    ShiftPort &= ~ClkPin;               //Set ClkPin low

    if (shiftData & (1<<i)) ShiftPort |= DataPin;       //Set DataPin high if current bit is 1
    else ShiftPort &= ~DataPin;             //Set DataPin low if current bit is 0

    ShiftPort |= ClkPin;                //Set ClkPin high to increment shift register
    ShiftPort &= ~DataPin;              //Set DataPin low to prepare for next write
  }

  ShiftPort |= LatchPin;                //Set LatchPin high to signal end of write operation
  ShiftPort &= ~(ClkPin | DataPin);             //Reset ClkPin and DataPin to low
}

void Write_Char(u8 pattern)     //Function that writes one pattern to the LED Matrix
{
  //Writes a char to the led matrix
  //Patterns come from font8x8[] in progmem (font8x8.h)
  pattern -= 32;                        
  char temp;
  for (char i=0; i<8; i++)              //Read one column of char at a time
  {
    temp = pgm_read_byte((char *)((int)font8x8 + (8 * pattern) + i));   //Get column from progmem
    for (char j=0; j<8; j++)                        //Cycle through each bit in column
    {
      //Write bits to appropriate row_buffer location
      if (temp & (1<<j)) row_buffer[8-j] |= 1<<(8-i);
      else row_buffer[8-j] &= ~(1<<(8-i));
    }
  }
}

int main(void)
{
    InitPorts();
    InitTimers();
    while(1)
    {
        for (char x = 0; x<255; x++)
        {
            Write_Char(x);
            Delay_ms(500);
        }

    }
}

ISR(TIMER1_COMPA_vect)              //Interrupt Service Routine handles the display.
{
  if(++row_track == 8) row_track = 0;       //Row tracking
  Shift_Int(row_buffer[row_track]);     //Shift in data for next row

  ShiftPort &= ~OE;             //Used to prevent ghosting
  if (row_track == 0)               //Shut down high side controller
  {
    RowPort &= ~(1<<7);             //If Row0 is next, shutdown Row7
  }
  else
  {
    RowPort &= ~(1<<(row_track-1));     //Shutdown previous row
  }

  ShiftPort |= LatchPin;            //Latch low side shift registers
  RowPort |= (1<<row_track);            //Drive high side controller
  ShiftPort |= OE;              //Used to prevent ghosting
}
4

1 回答 1

3

看来您应该能够更改此代码:

  //Write bits to appropriate row_buffer location
  if (temp & (1<<j)) row_buffer[8-j] |= 1<<(8-i);
  else row_buffer[8-j] &= ~(1<<(8-i));

也许对此,只是一个猜测:

  //Write bits to appropriate row_buffer location
  if (temp & (1<<j)) row_buffer[6-j] |= 1<<(7-i);
  else row_buffer[6-j] &= ~(1<<(7-i));

将行的 8 更改为 6,将列的 8 更改为 7。有可能你可能不得不弄乱循环,这样你就不会最终写入越界内存,但这看起来像是在设置像素,所以只要看看改变行号和列号会做什么,你应该能够弄清楚如何将其居中。

于 2012-05-06T05:56:32.557 回答