AT89C4051

LED Lauflicht mit dem AT90S1200

Endlich war Zeit, meine Testschaltung auch mal aufzubauen.

Diese eignet sich gut für Lötübungen. Die Bauteile sind als 0805 angelegt. Ich habe bis auf die LEDs und den µC alle übrigen Teile (Widerstände, Kondensatoren) von alten Festplattenelektroniken mit einer Heißluftstation entnommen, was eben da war. Deshalb wurde nicht durchgängig mit 0805 bestückt und als Vorwiderstand 1k (102) bzw. sogar 10k (103) benutzt. 😉 Die LED sind trotzdem noch erkennbar an. Auf die LED angepasste Widerstände wären hier natürlich deutlich besser.

Die ursprüngliche Intention war der erste Versuch, mittels eagle und professionellem Hersteller Platinen zu entwerfen. Bisher wurde immer auf Lochraster gebastelt. Es ist also ein Erstlingswerk, ich bin mir bereits vieler Fehler bewußt. (z.B. für die Handlötung zu kleine Lötpads am IC, ging trotzdem erstaunlich gut; 15 LEDs wären möglich statt 11; keine Beschriftung der Lagen; ungeduldige 😉 Entflechtung; ungünstige Platzierung der Bauteilbeschriftungen usw.) Ungeachtet dessen funktionieren die Platinen zuverlässig und sind fehlerfrei. Gelötet wurde mit einem Weller WECP-20 mit meißelförmiger 2mm-Spitze mit verbleitem 0,5mm-Lötzinn. Als µC geeignet sind ATtiny2313(A), ATTiny4313, AT90S1200(A), AT90S2313(A) und auch AT89C2051/4051 (bei geänderter RESET-Beschaltung) Der ISP-Programmieradapter ist nur für die AVR nutzbar, die 8051-er müssen vorher programmiert werden. Die LEDs stammen aus dem SMD-LED-Sortiment von Pollin bzw. die 0603-Bauform von Reichelt. (z.B. Bestellnummer: LY L29K)

Das Programm wurde recht schnell „zusammengeworfen“, da es nur zum schnellen Test dienen soll:

.include "1200def.inc"				; Das Programm ist für den AT90S1200 geschrieben, 
						; für den ATTiny2313 oder andere sind Änderungen erforderlich!!

.equ XTAL = 3187200

.def i = r21					; diverse Zwischenvariablen
.def Change = r22
.def Change_D = r23
.def Change_B = r24
.def temp = r25
.def DelCount_1 = r26				; bestimmt die Dauer der äußeren Warteschleife
.def DelCount_2 = r27				; mittlere Warteschleife
.def DelCount_3 = r28				; innere Warteschleife

 
.org 0x0000
        	        rjmp   	main            ; Programmstart
			rjmp 	EXT_INT0 	; IRQ0 Handler
			rjmp 	TIM0_OVF 	; Timer0 Overflow Handler
			rjmp 	ANA_COMP 	; Analog Comparator Handler			
 
EXT_INT0: 
TIM0_OVF: 
ANA_COMP: 
			reti			; fehlgeleitete Interrupts abfangen (sollte eigentlich nicht vorkommen)


main:
			ldi   	temp, 0xFF      ; Port B und D auf Ausgang
      		        out  	DDRB, temp
			out  	DDRD, temp

main2:		        ldi 	Change, 0x00		; Variablen initialisieren
			ldi 	Change_B, 0x00
			ldi 	Change_D, 0x03


// hier geht es los mit der Animation

// Effekt 1: versetztes Wechselblinken über alle LEDs

			ldi	i, 0x06			; 6-mal sollst Du es tun
main1:		        ldi temp, 0xAA				
			out PORTB, temp
			ldi	temp, 0x55
			out	PORTD, temp
			ldi	DelCount_1, 0x05		; 5 Warterunden
			rcall	wait

			ldi temp, 0x55
			out PORTB, temp
			ldi	temp, 0xAA
			out	PORTD, temp		
			ldi	DelCount_1, 0x05		; 5 Warterunden
			rcall 	wait

			dec	i
			cpse 	Change, i			; Schleife zu Ende?
			rjmp 	main1

// Effekt 2: LED-Kette geht schrittweise an

			ldi	temp, 0xFF
			out PORTB, temp
			ldi	temp, 0x30
schieben1:	        lsl	temp					; zuerst PORTD anschalten
			out	PORTD, temp
			ldi	DelCount_1, 0x05		; 5 Waitrunden
			rcall 	wait
			dec Change_D
			cpse Change, Change_D
			rjmp schieben1


			ldi	temp, 0xFF
schieben:	        lsl	temp					; jetzt ist PORTB dran
			out	PORTB, temp
			ldi	DelCount_1, 0x05		; 5 Waitrunden	
			rcall 	wait
			cpse	temp, Change_B
			rjmp	schieben

// Effekt 3: LEDs sind an, dunkler Punkt wandert durch die Kette

			ldi	Change_B, 0x78
			ldi 	i, 0x80
			mov	temp, i
wandern:		out	PORTB, temp			; erst PORTB
			lsr	temp
			dec	i
			ldi	DelCount_1, 0x05		; 5 Runden durch die Waitschleife
			rcall 	wait
			cpse	Change_B, i
			rjmp	wandern

			ldi	Change_D, 0x04
			ldi 	i, 0x40
			ldi	temp, 0x00
			out 	PORTB, temp
			mov	temp, i
wandern2:	        out	PORTD, temp				; dann PORTD
			lsr	temp
			dec	Change_D
			ldi	DelCount_1, 0x05		; 5 Runden durch die Waitschleife
			rcall 	wait
			cpse	Change, Change_D
			rjmp	wandern2




// Ein dunkler Punkt wird durchgeschoben

			ldi	i, 0x08
			ldi 	temp, 0x80
Shift:		        out 	PORTB, temp
			ror	temp
			dec i
			ldi	DelCount_1, 0x05		; 5 Runden durch die Warteschleife
			rcall	wait
			cpse	Change, i
			rjmp	Shift

			ldi	i, 0x04
			ldi	temp, 0x00
			out 	PORTB, temp
			out	PORTD, temp
			ldi 	temp, 0x40
Shift1:		        out 	PORTD, temp
			ror	temp
			dec 	i
			ldi	DelCount_1, 0x05		; 5 Runden durch die Warteschleife
			rcall	wait
			cpse	Change, i
			rjmp	Shift1

			rjmp 	main2			; Animationsprogramm beginnt von vorn



; subroutine wait, keine Ahnung, wie lang die ist, zu faul zum Rechnen, daher reines Bauchgefühl, 
; DelCount_1 muss vom Aufrufer gefüllt werden

wait:
	
delay2:		        ldi 	DelCount_2, 0xFF
delay1:		        ldi	DelCount_3, 0xFF
delay: 		        dec	DelCount_3
			cpse	Change, DelCount_3
       		        rjmp	delay     

			dec	DelCount_2
			cpse	Change, DelCount_2
			rjmp	delay1

			dec	DelCount_1
			cpse	Change, DelCount_1
			rjmp	delay2
			ret