; 12.11.2005 15:56:50 #cpu = 80C31 ; @15.600 MHz ajmp Initialisierung EXTI0: ; externer Interrupt 0 ajmp Externer Interrupt 0 ;definitionen für die fernbedienung einbinden #include 'rc_uni140.inc' #const start_addr=30h, end_addr=68h, max_nochange=17 #const ch_0_max=255, ch_1_max=255, ch_2_max=255, ch_3_max=255 #const ch_step=fh #exclude Byte 30h-68h #byte rc_ptr #byte rc_cnt, nochange_cnt, last_code, comp_val #byte tp1, tp2 #byte ch_0=71h, ch_1=72h, ch_2=73h, ch_3=74h, active_ch, max_active_ch #bit last_bit, have_code, match_end, led_toggle, rc_led=p3.3 #bit dir_0, dir_1, dir_2, dir_3 #byte prog_running, prog_state #byte ch_data_port=p1 #bit ch0_le=p3.4, ch1_le=p3.5, ch2_le=p3.6, ch3_le=p3.7 Initialisierung: ; Serieller Port mov SCON, # 40h ; Modus 1, asynchron, 8 Bit, Baudrate Timer 1 Überlauf mov TMOD, # 20h ; Timer 1 Autoreloadmodus mov TH1, # fch ; Reloadwert für Baudrate 158691,4 setb TR1 ; Timer 1 Start orl TMOD, # 01h ; Timer 0 als 16-Bit Timer. ; Die Überlauffrequenz des Timer 0 beträgt 19836,43 Hz, die Periodendauer 5,041231E-02 ms. mov TL0, # FFh mov TH0, # 3Fh ; Interrupts clr IT0 setb EA ; globale Interruptfreigabe mov last_code, #ffh setb rc_led mov prog_running, #0h setb p3.3 mov ch_0, #00h mov ch_1, #00h mov ch_2, #00h mov ch_3, #00h mov active_ch, #0h mov max_active_ch, #ch_0_max setb ch0_le setb ch1_le setb ch2_le setb ch3_le acall write_ch init_vars: clr have_code acall t0_go_long acall wait_for_t0 ;acall t0_go_long ;acall wait_for_t0 setb ex0 main: if bit have_code jmp eval end if mov a, prog_running if a=#1h acall prog1 elseif a=#2 acall prog2 end if jmp main eval: ;auf repeat code checken mov a, rc_cnt clr cy subb a, #rc_repeat_len ;code zu kurz if bit cy jmp init_vars end if ;vergleich mit repeat code tabelle mov dptr, #rc_repeat_tab mov r0, #start_addr mov r7, #rc_repeat_len inc r7 for r7 mov a, #0 movc a, @a+dptr mov comp_val, @r0 if a=comp_val inc r0 inc dptr else jmp check_rc_id end if next ;schleife ist durchgelaufen, also repeat code empfangen mov a, last_code if a=#ffh jmp init_vars else mov r7, last_code jmp code_found end if check_rc_id: ;auf fernbedienungs id checken mov a, rc_cnt clr cy subb a, #rc_id_len ;code zu kurz if bit cy jmp init_vars end if ;mit id tabelle vergleichen mov dptr, #rc_id_tab mov r0, #start_addr mov r7, #rc_id_len inc r7 for r7 mov a, #0 movc a, @a+dptr mov comp_val, @r0 if a=comp_val inc r0 inc dptr else jmp init_vars end if next ;schleife ist durchgelaufen, d.h. id ist gültig ;code ermitteln, dazu codetabelle durchgehen mov dptr, #code_tab mov r7, #known_codes for r7 clr match_end mov a, #start_addr add a, #code_pos mov r0, a for r6=#code_len mov a, #0 movc a, @a+dptr mov comp_val, @r0 if a=comp_val else setb match_end end if inc r0 inc dptr next ;es gab keinen fehler beim aktuellen code if not bit match_end jmp code_found end if next ;schleife ist durchgelaufen, dh kein code passte jmp init_vars code_found: ;codeauswertung mov last_code, r7 mov a, #known_codes clr cy subb a, r7 ;aktionen für den jeweiligen tastencode if a=#0 mov active_ch, #3h mov max_active_ch, #ch_3_max elseif a=#1 mov active_ch, #1h mov max_active_ch, #ch_1_max elseif a=#2 mov active_ch, #2h mov max_active_ch, #ch_2_max elseif a=#3 mov active_ch, #0h mov max_active_ch, #ch_0_max elseif a=#4 acall on_off elseif a=#5 acall dec_ch elseif a=#6 acall inc_ch elseif a=#7 acall dec_ch_step elseif a=#8 acall inc_ch_step elseif a=#9 mov a, prog_running if a=#1h mov prog_running, #0 else mov prog_running, #1 end if elseif a=#10 mov a, prog_running if a=#2h mov prog_running, #0 else mov prog_running, #2 acall prog2_init end if end if acall write_ch acall write_stats ;zurück auf anfang jmp init_vars Externer Interrupt 0: clr ex0 ; timer start acall t0_go ; receive buffer auf 0 mov r0, #start_addr mov rc_cnt, #0h mov nochange_cnt, #0h next_byte: ; rc led toggeln if bit led_toggle setb rc_led clr led_toggle else clr rc_led setb led_toggle end if ;schleife zum empfang eines bytes for r7=#8 mov a, @r0 clr cy rlc a clr p3.3 if not bit p3.2 then setb acc.0 end if mov @r0, a ;anzahl der hintereinander gleichen pegel zählen if bit acc.0 if bit last_bit inc nochange_cnt else mov nochange_cnt, #0h setb last_bit end if else if not bit last_bit inc nochange_cnt else mov nochange_cnt, #0h clr last_bit end if end if ;überschreitet die anzahl der hintereinander empfangen gleichen pegel ;eine grenze wird der signalempfang abgebrochen mov a, nochange_cnt if a=#max_nochange then jmp abort_rc end if setb p3.3 ;warten bis der timerabgelaufen ist acall wait_for_t0 ;timer neu starten acall t0_go next ;ein byte wurde komplett gesampelt inc rc_cnt inc r0 mov a, r0 ;überlauf des speichers verhindern if a=#end_addr jmp abort_rc end if ;nächstes byte sampeln jmp next_byte abort_rc: ;code empfange und zur kontrolle auf die ser. schnittstelle geben ;mov r0, #start_addr ;inc rc_cnt ;for r7=rc_cnt ; mov a, @r0 ; acall send_a ; inc r0 ;next ;dec rc_cnt setb rc_led setb have_code reti on_off: mov a, prog_running if a=#0h acall get_active_ch if a=#0h mov a, #ffh else mov a, #0h end if mov @r0, a else mov prog_running, #0h end if ret inc_ch: acall get_active_ch if a=max_active_ch else inc a end if mov @r0, a ret dec_ch: acall get_active_ch if a=#0h else dec a end if mov @r0, a ret inc_ch_step: acall get_active_ch clr cy subb a, max_active_ch dec a clr cy add a, #ch_step if bit cy mov a, max_active_ch end if mov @r0, a ret dec_ch_step: acall get_active_ch clr cy subb a, #ch_step if bit cy mov a, #0h end if mov @r0, a ret ;holt den wert des aktiven kanals nach a und dessen adresse nach r0 get_active_ch: mov a, #ch_0 add a, active_ch mov r0, a mov a, @r0 ret ;schreibt die kanalwerte zu den cplds write_ch: mov ch_data_port, ch_0 clr ch0_le setb ch0_le mov ch_data_port, ch_1 clr ch1_le setb ch1_le mov ch_data_port, ch_2 clr ch2_le setb ch2_le mov ch_data_port, ch_3 clr ch3_le setb ch3_le ret ;sendet ein byte in a an die serielle schnittstelle send_a: clr ti mov sbuf, a loop while not bit ti end loop ret ;startet timer0 mit der sampleperiode für die aktuelle fernbedienung t0_go: mov TL0, #sample_time_lo mov TH0, #sample_time_hi clr tf0 setb tr0 ret ;startet timer0 mit maximaler periodendauer t0_go_long: mov TL0, #0h mov TH0, #0h clr tf0 setb tr0 ret ;wartet auf einen overflow von timer0 wait_for_t0: loop while not bit tf0 end loop ret write_stats: mov a, r7 send_a mov a, ch_0 send_a mov a, ch_1 send_a mov a, ch_2 send_a mov a, ch_3 send_a ret prog1: mov a, #0 dec tp1 if a=tp1 mov tp1, #1h dec tp2 if a=tp2 mov tp2, #ffh acall prog1_action end if end if acall write_ch ret prog1_action: if bit dir_0 inc ch_0 mov a, #ffh if a=ch_0 cpl dir_0 jmp a1 else ret end if else dec ch_0 mov a, #1h if a=ch_0 cpl dir_0 jmp a1 else ret end if end if a1: if bit dir_1 inc ch_1 mov a, #ffh if a=ch_1 cpl dir_1 jmp a2 else ret end if else dec ch_1 mov a, #1h if a=ch_1 cpl dir_1 jmp a2 else ret end if end if a2: if bit dir_2 inc ch_2 mov a, #ffh if a=ch_2 cpl dir_2 jmp a3 else ret end if else dec ch_2 mov a, #1h if a=ch_2 cpl dir_2 jmp a3 else ret end if end if a3: if bit dir_3 inc ch_3 mov a, #ffh if a=ch_3 cpl dir_3 jmp a4 else ret end if else dec ch_3 mov a, #1h if a=ch_3 cpl dir_3 jmp a4 else ret end if end if a4: ret prog2_init: mov ch_0 ,#1 mov ch_1, #feh mov ch_2, #feh mov ch_3, #feh mov prog_state, #0 ret prog2: mov a, #0 dec tp1 if a=tp1 mov tp1, #1h dec tp2 if a=tp2 mov tp2, #ffh acall prog2_action end if end if acall write_ch ret prog2_action: mov a, prog_state if a=#0 inc ch_0 dec ch_1 mov a, ch_1 if a=#1 mov prog_state, #1 end if elseif a=#1 inc ch_1 dec ch_2 mov a, ch_2 if a=#1 mov prog_state, #2 end if elseif a=#2 inc ch_2 dec ch_3 mov a, ch_3 if a=#1 mov prog_state, #3 end if elseif a=#3 inc ch_3 dec ch_0 mov a, ch_0 if a=#1 mov prog_state, #0 end if end if ret