Светодиодная матрица с использованием контроллера AVR

Я создал светодиодную матрицу 8x8, которая управляется микроконтроллером (в частности, Atmega8), 8-битным сдвиговым регистром (HEF4794) и массивом драйверов (MIC2981). Проблема, с которой я сталкиваюсь, заключается в том, что шаблон, который должен отображаться, не центрирован. Его нужно сдвинуть влево на один столбец и вниз на две строки. Любая помощь приветствуется.

Я получил идею этого проекта отсюда: 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
}

person Scott Gardner    schedule 05.05.2012    source источник
comment
Удалось ли вам определить, какая процедура или процедуры могут быть ошибочными? Это гигантская куча кода, которую нужно попытаться отладить без доступа к оборудованию, чтобы показать, что происходит...   -  person sarnold    schedule 06.05.2012
comment
Я думаю, что проблема в подпрограмме Write_Char.   -  person Scott Gardner    schedule 06.05.2012


Ответы (1)


Похоже, вы должны просто изменить этот код:

  //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 для столбцов. Возможно, вам придется возиться с циклами, чтобы в конечном итоге вы не записывали в память за пределами памяти, но это выглядит так, как будто он устанавливает пиксели, поэтому просто посмотрите, что делает изменение номеров строк и столбцов, и вы должен быть в состоянии выяснить, как центрировать его.

person Justin    schedule 06.05.2012
comment
Спасибо за помощь. Я попытался перейти на 6 и 7, и это слишком сильно компенсировало это, поэтому я сделал обе 7, и теперь они отцентрированы и работают отлично. Спасибо еще раз. - person Scott Gardner; 06.05.2012