C语言 使用 AVR 控制器的 LED 矩阵



我创建了一个8x8 LED矩阵,由一个微调控制器(特别是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
}

似乎您应该能够更改此代码:

  //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。您可能不得不弄乱循环,这样您最终就不会写入越界内存,但这就是它看起来正在设置像素的地方,所以只需看看更改行号和列号的作用,您应该能够弄清楚如何居中它。

最新更新