1 | ;ausgangsspannungsregelung nach stepdown
|
2 | ;pwm an atmega16 für 2 khz
|
3 | ;bei 4mhz taktfrequenz
|
4 | ;mit timer0 im fast pwm mode, 8 bit aufloesung
|
5 | ;pwm-signal liegt auf pb3 oc0
|
6 | ;adc takt mittels rcall
|
7 | ;rs232 ausgabe+bcd wandlung mittels rcall
|
8 | ;werner/16.2.12
|
9 | .include "m16def.inc"
|
10 |
|
11 | .def v_panel = r14 ;Messwert PV-Spannung PA0
|
12 | .def v_akku = r12 ;Messwert Akku-Spannung PA1
|
13 | .def i_panel = r10 ;Messwert PV-Strom PA2
|
14 | .def temp1 = r16 ;temporäre Variable
|
15 | .def temp2 = r17 ;temporäre Variable
|
16 | ;.def wait2 = r18 ;Zähler
|
17 | .def v_akkupwm = r19 ;ermittellter Vorladewert ocr0
|
18 | .def v_store = r20 ;gespeicherte Wunschspannung am PWM-Ausgang
|
19 |
|
20 |
|
21 |
|
22 | .org 0x000
|
23 | rjmp RESET ;External Pin, Power-on Reset, Brown-out
|
24 | .org INT0addr
|
25 | reti ;External Interrupt Request 0
|
26 | .org INT1
|
27 | reti ;External Interrupt Request 1
|
28 | .org OC2addr
|
29 | reti ;Timer/Counter2 Compare Match
|
30 | .org OVF2addr
|
31 | reti ;Timer/Counter2 Overflow
|
32 | .org ICP1addr
|
33 | reti ;Timer/Counter1 Capture Event
|
34 | .org OC1Aaddr
|
35 | reti ;Timer/Counter1 Compare Match A
|
36 | .org OC1Baddr
|
37 | reti ;Timer/Counter1 Compare Match B
|
38 | .org OVF1addr
|
39 | reti ;TIMER1 OVF ;Timer/Counter1 Overflow
|
40 | .org OVF0addr
|
41 | reti ;Timer/Counter0 Overflow
|
42 | .org SPIaddr
|
43 | reti ;Serial Transfer Complete
|
44 | .org URXCaddr
|
45 | reti ;USART, Rx Complete
|
46 | .org UDREaddr
|
47 | reti ;USART Data Register Empty
|
48 | .org UTXCaddr
|
49 | reti ;USART, Tx Complete
|
50 | .org ADCCaddr
|
51 | reti ;ADC Conversion Complete
|
52 | .org ERDYaddr
|
53 | reti ;EEPROM Ready
|
54 | .org ACIaddr
|
55 | reti ;Analog Comparator
|
56 | .org TWIaddr
|
57 | reti ;Two-wire Serial Interface
|
58 | .org INT2addr
|
59 | reti ;External Interrupt Request 2
|
60 | .org OC0addr
|
61 | reti ;Timer/Counter0 Compare Match
|
62 | .org SPMRaddr
|
63 | reti ;Store Program Memory Ready
|
64 |
|
65 | .org 0x30 ;programm ab flashadresse 30h speichern
|
66 |
|
67 | ;=============== stackpointer ini ===========================
|
68 | reset:
|
69 |
|
70 | ldi temp1, high (RAMEND)
|
71 | out SPH, temp1 ;SPH am Ende phys. SRAM
|
72 | ldi temp1, low (RAMEND)
|
73 | out SPL, temp1 ;SPL am Ende phys. SRAM
|
74 | ldi temp1,0b11111000
|
75 | out DDRA, temp1 ;pa0-2 analoge eingaenge
|
76 | ldi temp1,0b11111111
|
77 | out DDRD, temp1 ;pd2-7 ausgabe
|
78 | ldi temp1, 0b11111111
|
79 | out DDRC, temp1 ;pc0-7 ausgabe
|
80 | ldi temp1, 0b00001111
|
81 | out DDRb, temp1 ;pb0-3 ausgabe
|
82 |
|
83 |
|
84 | ldi v_store,132 ;max.ladespannung rechner.139
|
85 | ;rcall timer1ini ;TIMER 1 initialisieren
|
86 | rcall timer0ini ;Timer 0 initialisieren
|
87 | rcall adini ;A-D Wandler AD0 initialisieren
|
88 | rcall rs232ini ;RS232 initialisieren
|
89 |
|
90 | sei ;Interrupts global aktivieren?????????
|
91 | ;============== hauptprogramm ====================================
|
92 | main:
|
93 | rcall adwand
|
94 | rcall auswahl
|
95 | rcall bin2bcd
|
96 | rcall rs232aus
|
97 | rcall warte
|
98 |
|
99 | jmp main
|
100 | ;============== auswahl+pwm ausgabe ====================================
|
101 | auswahl:
|
102 | cp v_store, v_akku ; vergleiche messwert mit sollwert
|
103 | breq doReturn ; gleich? dann gibts nichts zu tun
|
104 | brsh up ; zu groß?
|
105 | ; -> nicht zu groß, also muss es zu klein sein
|
106 | down:
|
107 | dec v_akkupwm ; pwm bischen verringern
|
108 | jmp sichern
|
109 |
|
110 | up:
|
111 | inc v_akkupwm ; pwm bischen vergrößern
|
112 |
|
113 | sichern:
|
114 | out ocr0, v_akkupwm ; und externe PWM setzen
|
115 | doReturn:
|
116 | ret
|
117 | ;======================== timer0ini =====================
|
118 | timer0ini:
|
119 |
|
120 | in temp1, tccr0
|
121 | ori temp1, 0b01101010 ;tccr0, fast pwm, prescaler 8, lösche oc0 bei gleichstand
|
122 | out tccr0, temp1
|
123 | in temp1, timsk
|
124 | ori temp1, 0b00000000
|
125 | out timsk, temp1 ;ohne irq
|
126 |
|
127 | ret
|
128 | ;====================== ad-wandler ini =================
|
129 | adini:
|
130 |
|
131 | ldi temp1,(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)
|
132 | out ADCSRA,temp1 ;adcen,
|
133 | ldi temp1,(1<<REFS0)|(1<<ADLAR) ;AVcc,linksbuendig,pa0
|
134 | out ADMUX,temp1
|
135 | ret
|
136 | ;======================== adwandlung pa0 ==================
|
137 | adwand:
|
138 | ;pa0
|
139 |
|
140 |
|
141 | sbi ADCSRA,ADSC ;Wandlung pa0 starten
|
142 | fertig:
|
143 | sbic ADCSRA,ADSC ;warten bis wandlung
|
144 | rjmp fertig ;beendet
|
145 |
|
146 | in v_akku, ADCH ;highbyte auslesen
|
147 |
|
148 | ret
|
149 | ;================== warte 5ms ===================
|
150 | warte:
|
151 |
|
152 |
|
153 | ldi temp1, $21
|
154 | WGLOOP0: ldi temp2, $C9
|
155 | WGLOOP1: dec temp2 ; 5ms Pause (bei 4 MHz)
|
156 | brne WGLOOP1
|
157 | dec temp1
|
158 | brne WGLOOP0
|
159 | ret
|
160 |
|
161 | ;====================== timer1ini ======================
|
162 | timer1ini:
|
163 |
|
164 | ldi temp1,(1<<CS11) ;Betriebsart Mode 0 (PB3 normal)
|
165 | ;4Mhz/1 Wave Form Generator Mode 0 (Normal)
|
166 | out TCCR1B, temp1 ;Prescaler 256 um bei TCNT1H + TCNT1L = 0
|
167 | in temp1, timsk ;auf ca. 239msek zu kommen
|
168 | ori temp1, (1<<TOIE1) ;Timer1 Overflow Interrupt aktiviert
|
169 | out TIMSK, temp1
|
170 | sei ;Enble all Interrupt
|
171 | ldi temp1, 0b00000000 ;Lade High Byte des 16 bit Zählers
|
172 | out TCNT1H, temp1 ;in TCNT1H
|
173 | ldi temp1, 0b00000000 ;Lade High Byte des 16 bit Zählers
|
174 | out TCNT1L, temp1 ;in TCNT1L
|
175 |
|
176 | ret
|
177 |
|
178 | ;======================= rs232ini =========================
|
179 | rs232ini:
|
180 | LDI temp1, 0 ;Festlegen der Flanke wann gesendet
|
181 | OUT UBRRH, temp1 ;und gelesen wird
|
182 | LDI temp1, 26
|
183 | OUT UBRRL, temp1 ;sende bei 4 MHz mit 9600 Baud
|
184 | LDI temp1, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE) ;aktiviere tx+rx irq
|
185 | OUT UCSRB, temp1
|
186 | LDI temp1,(1<<URSEL)|(0<<USBS)|(3<<UCSZ0) ; 1 Stopbits, 8 Datenbits
|
187 | OUT UCSRC,temp1 ;(fuer 2 Stoppbits USBS=1)
|
188 | ret
|
189 |
|
190 |
|
191 |
|
192 | ;============== rs232 ausgabe===========================
|
193 | rs232aus:
|
194 |
|
195 | rs232a: SBIS UCSRA, UDRE ;Ausgabe Messwert an RS 232
|
196 | RJMP rs232a
|
197 | OUT UDR, R1
|
198 |
|
199 | rs232b: SBIS UCSRA, UDRE
|
200 | RJMP rs232b
|
201 | OUT UDR, R2
|
202 |
|
203 | rs232c: SBIS UCSRA, UDRE
|
204 | RJMP rs232c
|
205 | LDI R23, ','
|
206 | OUT UDR, R23
|
207 |
|
208 | rs232d: SBIS UCSRA, UDRE
|
209 | RJMP rs232d
|
210 | OUT UDR, R3
|
211 |
|
212 | rs232e: SBIS UCSRA, UDRE
|
213 | RJMP rs232e
|
214 | LDI R23, ' '
|
215 | OUT UDR, R23
|
216 |
|
217 | rs232f: SBIS UCSRA, UDRE
|
218 | RJMP rs232f
|
219 | LDI R23, 'V'
|
220 | OUT UDR, R23
|
221 |
|
222 | rs232g: SBIS UCSRA, UDRE
|
223 | RJMP rs232g
|
224 | LDI R23, ' '
|
225 | OUT UDR, R23
|
226 |
|
227 | rs232h: SBIS UCSRA, UDRE
|
228 | RJMP rs232h
|
229 | LDI R23, 13
|
230 | OUT UDR, R23
|
231 | ret
|
232 | ;===================== binaer2bcd-wandlung ======================
|
233 | bin2bcd:
|
234 |
|
235 | CLI
|
236 | LDI R21, 0 ;Zähler für Durchläufe auf 0
|
237 | MOV R22 , R14 ;Lade 253dez in R22
|
238 |
|
239 | hundertera:
|
240 | MOV R0,R22 ;Rette Originalwert in R0
|
241 | CPI R22, 100 ;Prüfe ob hunderter Stelle = 0
|
242 | BRSH hunderterb
|
243 | MOV R1, R21 ;schreibe erste Stelle 0
|
244 | jmp zehnera
|
245 |
|
246 | hunderterb:
|
247 | MOV R22,R0 ;Rette Originalwert in R22
|
248 |
|
249 | hunderterc:
|
250 | MOV R1, R21
|
251 | SUBI R22, 100 ;ziehe 100 ab
|
252 | BRLO zehnera ;nicht mehr teilbar und raus
|
253 | ;(oder = prüfe Carry)
|
254 | INC R21 ;Erhähe Teilbar durch Zähler
|
255 | MOV R0,R22 ;Rette Originalwert in R0
|
256 | jmp hunderterc
|
257 |
|
258 | zehnera:
|
259 | LDI R21,0 ;Teilerzähler erneut auf 0
|
260 | MOV R22,R0 ;Stelle Originalwert aus R0 her
|
261 | CPI R22, 10 ;Prüfe ob zehner Stelle = 0
|
262 | BRSH zehnerb
|
263 | MOV R2, R21 ;schreibe mittlere Stelle 0
|
264 | jmp einera
|
265 | zehnerb:
|
266 | MOV R22,R0 ;Rette Originalwert in R0
|
267 | zehnerc:
|
268 | MOV R2, R21 ;mittlerer Wert in R2
|
269 | SUBI R22, 10 ;ziehe 10 ab
|
270 | BRLO einera ;nicht mehr teilbar und raus
|
271 | ;(oder = prüfe Carry)
|
272 | INC R21 ;Erhähe Teilbar durch Zähler
|
273 | MOV R0,R22 ;Rette Originalwert in R0
|
274 | jmp zehnerc
|
275 |
|
276 | einera:
|
277 | LDI R21,0 ;Teilerzähler erneut auf 0
|
278 | MOV R22,R0 ;Stelle Originalwert aus R0 her
|
279 | CPI R22, 0 ;Prüfe ob einer Stelle = 0
|
280 | BRNE einerb
|
281 | MOV R3, R21 ;schreibe vordeste Stelle 0
|
282 | jmp fertig
|
283 |
|
284 | einerb:
|
285 | MOV R3,R0 ;Hole Originalwert aus R0
|
286 |
|
287 | jmp fertigasc
|
288 |
|
289 |
|
290 |
|
291 |
|
292 | ;==================bcd2ascii=========================
|
293 |
|
294 | fertigasc:
|
295 | LDI R22, '0' ;Lade Register 16 mit ASCII NULL
|
296 | ADD R1, R22 ; ASCII MSB Stelle
|
297 | ADD R2, R22 ;mittlere ASCII Stelle
|
298 | ADD R3, R22 ; ASCII LSB Stelle
|
299 |
|
300 | RET
|