From: <ha...@hu...> - 2007-03-13 17:52:12
|
2007/3/13, Matthias Trute <mt...@we...>: > Hans H=FCbner wrote: > > Also, on the home page under Bugs, "Using timer interrupt may cause > > strange effects." is mentioned. I would like to use a timer to > > refresh my multiplexed LED display, can you let me know what the > > "strange effects" are? > > If the frequency is too high (say 100Hz on a 16MHz controller) the > controller stops responding. And regardless of the frequency you are not > able to use the flash write operation i! and all words using it. I have > no idea why it happens... For fun, I have connected a four digit 7 segment display to my ATMEGA32 running at 16 Mhz. The display is multiplexed in two pairs, so I need to refresh fast enough to get a stable display. To do so, I use TIMER0 with the overflow interrupt mapped to vector three. I prescale the timer by 256, thus my interrupt handler is called at about 240 Hz. It just works. Also, I have observed no anomalies working in immediate mode while my display refresh was active, so I could still compile works. What a gas! Great stuff :) -Hans If anyone's interested: I had to patch devices/atmega32.asm: .org=09OVF0addr ; Overflow0 Interrupt Vector Address rjmp int3_isr \ Ansteuerung der vierstelligen 7-Segment-Anzeige \ Port A =3D> 1. und 3. Stelle \ Port B =3D> 2. und 4. Stelle \ Port C =3D> Bit 0: 1. und 2. Stelle ausw=E4hlen \ Bit 1: 3. und 4. Stelle ausw=E4hlen \ Bit 1 und 3 d=FCrfen nicht gleichzeitig auf 1 gesetzt werden! decimal \ Tabelle f=FCr die Umsetzung von Ziffern in Bits f=FCr die 7-Segment-Anzei= ge create 7seg-digit-map 63 invert , 6 invert , 91 invert , 79 invert , 102 invert , 109 invert , 125 invert , 7 invert , 127 invert , 111 invert , \ Umrechnen einer Ziffer in Bits f=FCr die 7-Segment-Anzeige : 7seg-digit ( n -- m ) 7seg-digit-map 1+ + i@ ; \ Variable f=FCr die aktuell angezeigten Display-Bits 0 variable display 3 allot \ Eine Zahl ins Display-Register schreiben : set-display ( n -- ) 4 0 do 10 /mod loop drop 7seg-digit display 3 + c! 7seg-digit display 2 + c! 7seg-digit display 1 + c! 7seg-digit display c! ; \ Initialisieren der Schnittstelle zum Display : init-display \ Erst mal die Bits so einstellen, da=DF alle LEDs aus sind 255 PORTA c! 255 PORTB c! 0 PORTC c! \ Jetzt die Datenrichtungsregister setzen, so da=DF die entsprechenden Bits alle \ als Ausgang konfiguriert sind. 255 DDRA c! 255 DDRB c! 7 DDRC c! ; \ Aktuell aktive Display-H=E4lfte 0 variable field \ Wechseln der Display-H=E4lfte und anzeigen der passenden Ziffern. Jedes \ Mal, wenn das Wort refresh-display aufgerufen wird, wird wird das Display \ umgeschaltet. Wenn man refresh-display schnell genug hintereinander aufr= uft, \ ergibt sich ein stehendes Bild. : refresh-display ( -- ) 0 PORTC c! field c@ dup if display c@ PORTA c! display 1 + c@ PORTB c! 2 PORTC c! else display 2 + c@ PORTA c! display 3 + c@ PORTB c! 1 PORTC c! then not field c! ; \ Demo f=FCr refresh-display : refresh-display-demo ( -- ) begin refresh-display 1ms key? until key drop ; \ Anzeige aller vier Ziffern im Hintergrund. Die Umschaltung erfolgt \ durch den Timer-Interrupt. : start-display ( -- ) init-display 0 set-display ['] refresh-display 3 intvector ! \ Timer clock =3D> sysclk / 256 4 TCCR0 c! \ Timer0 einschalten 1 TIMSK c! ; : count ( -- ) 10000 0 do i set-display 1ms loop ; |