ATtiny26 controlling 12 leds with 4 IO-lines with charlieplexing
Source code for blinking leds
/* cycle 12 leds with attiny2313 Tomi Leppikangas 25.5.2010 */ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <avr/pgmspace.h> typedef struct { uint8_t ddr; uint8_t bits; } leds_t; /* bit values for 12 leds */ const leds_t led_values [] PROGMEM = { // 3210 3210 { 0b00001100, 0b00000100 }, // 1 { 0b00000110, 0b00000010 }, // 2 { 0b00000011, 0b00000001 }, // 3 { 0b00000011, 0b00000010 }, // 4 { 0b00000110, 0b00000100 }, // 5 { 0b00001100, 0b00001000 }, // 6 { 0b00001010, 0b00001000 }, // 7 { 0b00001010, 0b00000010 }, // 8 { 0b00001001, 0b00000001 }, // 9 { 0b00001001, 0b00001000 }, // 10 { 0b00000101, 0b00000100 }, // 11 { 0b00000101, 0b00000001 }, // 12 }; volatile uint8_t current = 0; // current led volatile uint8_t old[3] = {0}; // old leds /* timer/counter0 compare interrupt */ ISR(TIMER0_COMPA_vect) { static uint8_t count = 0; if(count <20) { DDRB = pgm_read_byte(&led_values[current].ddr); PORTB = pgm_read_byte(&led_values[current].bits); } else if(count < 30) { DDRB = pgm_read_byte(&led_values[old[0]].ddr); PORTB = pgm_read_byte(&led_values[old[0]].bits); } else if(count < 35) { DDRB = pgm_read_byte(&led_values[old[1]].ddr); PORTB = pgm_read_byte(&led_values[old[1]].bits); } else { DDRB = pgm_read_byte(&led_values[old[2]].ddr); PORTB = pgm_read_byte(&led_values[old[2]].bits); } count ++; if(count == 36) count = 0; } /* timer/counter1 compare interrupt */ ISR(TIMER1_COMPA_vect) { static int8_t direction = 1; old[2] = old[1]; // remember old leds old[1] = old[0]; old[0] = current; current = current + direction; if(current == 11) direction = -1; else if (current == 0) direction = 1; } int main(void) { // init timer 0 TCCR0A |= (1<<WGM01); // CTC TCCR0B |= (1<<CS02 | 1<<CS00); // scale 1024 TIMSK |= (1<<OCIE0A); // enable output compare int a OCR0A = 1; // init timer 1 t TCCR1A &= ~(1<<WGM11 | 1<<WGM10); // CTC TCCR1B &= ~(1<<WGM13); TCCR1B |= (1<<WGM12 | 1<<CS12 ); // CTC + scale 256 TIMSK |= (1<<OCIE1A); // enable output compare int a OCR1A = F_CPU/256/20; //OCR1AL = 1000; DDRB |= (1 << PB0); // port B0 out DDRB |= (1 << PB1); // port B1 out PORTB |= (1 << PB0); // BO = 1 set_sleep_mode(SLEEP_MODE_IDLE); sleep_enable(); sei(); while(1) { sleep_cpu(); } return 0; }Tomi Leppikangas 27.5.2010 [home]