|
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
;
|