Hallo
Nachdem ich nun noch etwas an der Software rumgeschnitzt habe, kann sich das Ergebniss wirklich sehen lassen:
Bild hier
http://www.youtube.com/watch?v=EpW4n09WuZA
Das sind jetzt vier deutlich unterscheidbare Helligkeitsstufen. Der Trick: Jetzt wird Timer2 im FastPWM-Mode verwendet. Das ermöglicht zwei getrennte ISR, die Overflow-ISR setzt die LEDs, die OutputCompare-ISR löscht sie wieder:
Code:
// Scrollen mit vier Helligkeitsstufen mic 27.12.2010
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>
#define colors 4 // Anzahl der Farbebenen
volatile uint8_t ebene=0, col = 0;
uint8_t x, y, z, bildspeicher[colors][15];
// alle LEDs in allen Ebenen aus
void cls(void);
// Einen Bildpunkt an x, y setzen. Werte für c: 0 ist aus, 1 ist dunkel, 4 ist hell
void set(uint8_t x, uint8_t y, uint8_t c);
// Potiwerte einlesen, P2 ist Kanal 6, P3 ist Kanal 7
uint16_t readADC(uint8_t channel);
// WatchDog beim Initialisieren ausschalten
// https://www.roboternetz.de/phpBB2/vi...=531597#531597
void kill_WD(void) __attribute__((naked)) __attribute__((section(".init3")));
void kill_WD(void) { MCUSR = 0; wdt_disable(); }
int main(void)
{
cli();
DDRB = 0xff;
DDRC = 0x0f;
DDRD = 0xf0;
TCCR2 = (1<<CS21) | (0<<CS20); // 8-bit Timer mit 1/8 Vorteiler
TCCR2 |= (1<<WGM21) | (1<<WGM20); // Fast PWM
TCCR2 |= (0<<COM21) | (0<<COM20); // no OC2-Pin
OCR2 = 100; // 0=dunkel, 255=hell
TIFR = (1<<OCF2) | (1<<TOV2); // Clear old flags
TIMSK |= (1<<TOIE2) | (1<<OCIE2); // overflow and compare interrupt
// A/D Conversion (aus der asuro-Lib)
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); // clk/64
sei(); // Interrupts erlauben
for(x=0; x<12; x++)
for(y=0; y<10; y++)
set(x, y, (x/3)%colors+1); // Helligkeitsstufen anzeigen
_delay_ms(1000);
cls();
z=0;
while(1)
{
for(x=0; x<12; x++)
for(y=0; y<10; y++)
set(x, y, ((x+y+(z%12))/3)%colors+1);
_delay_ms(50);
z++;
}
return (0);
}
void cls(void)
{
uint8_t x, y;
for(x=0; x<15; x++)
for(y=0; y<colors; y++)bildspeicher[y][x] = 0;
}
void set(uint8_t x, uint8_t y, uint8_t c)
{
uint8_t ebene;
y = 9-y; // Koordinatennullpunkt unten links
if(y < 8) // y 9 bis 2
for(ebene=0; ebene<colors; ebene++)
if(c>ebene) bildspeicher[ebene][x] |= (1 << y);
else bildspeicher[ebene][x] &= ~(1 << y);
else // y 1 und 0
for(ebene=0; ebene<colors; ebene++)
if(c>ebene) bildspeicher[ebene][12+(x>>2)] |= (1<<((x%4)*2+(y&1)));
else bildspeicher[ebene][12+(x>>2)] &= ~(1<<((x%4)*2+(y&1)));
}
uint16_t readADC(uint8_t channel)
{
ADMUX = (1 << REFS0) | (channel & 7);// AVCC reference with external capacitor
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
return(ADC);
}
SIGNAL (SIG_OUTPUT_COMPARE2)
{
OCR2 = (24<<ebene); // hihi
PORTB &= ~0x03; // Die Pins der Displaymatrix werden auf Low gesetzt
PORTC &= ~0x0f;
PORTD &= ~0xf0;
}
SIGNAL (SIG_OVERFLOW2)
{
uint8_t ledval, portb;
// Spalten
if(col) PORTB |= (1<<4); /* Danach Einsen hinterherschicken (PB4 = 1) */
else PORTB &= ~(1<<4); /* Bei der ersten Spalte eine 0 ausgeben (PB4 = 0) */
PORTB |= (1 << 3); /* PB3 = 1 (cl) */
PORTB &= ~(1 << 3); /* PB3 = 0 (!cl) */
PORTB |= (1 << 2); /* PB2 = 1 (str) */
PORTB &= ~(1 << 2); /* PB2 = 0 (!str) */
// Zeilen
ledval = bildspeicher[ebene][12+(col>>2)]; // y 1 und 0
portb = (ledval >> (col%4)*2) & 0x03;
ledval = bildspeicher[ebene][col]; // y 9 bis 2
PORTC |= ledval & 0x0f;
PORTD |= ledval & 0xf0;
PORTB |= portb;
col++;
if(col>11)
{
col=0;
ebene++;
if(ebene == colors) ebene=0;
}
}
Gruß
mic
Ein Vorkucker:
Bild hier Bild hier Bild hier
http://www.youtube.com/watch?v=z18KkJU_0Ic
http://www.youtube.com/watch?v=IKszXFViHR8
http://www.youtube.com/watch?v=ngim6DzIcGQ
Die 0,00012 Megapixelkamera:
https://www.roboternetz.de/phpBB2/vi...=531996#531996
Lesezeichen