; PREPROCESSOR DEFINITIONS ;---------------------------------------------------------------------- #define LCD_RS 2 ; LCD RS #define LCD_E 3 ; LCD E (enable) #define LCD_DATA PORTD ; LCD-Port ;---------------------------------------------------------------------- ; Files Required: p16F887.inc ;---------------------------------------------------------------------- list p=16f887 ; list definiert den Controller #include ; Headerdatei mit Registernamen errorlevel -302 ; suppress message 302 from list file __CONFIG _CONFIG1, _LVP_OFF&_FCMEN_OFF&_IESO_OFF&_BOR_OFF&_CPD_OFF&_CP_OFF&_MCLRE_ON&_PWRTE_ON&_WDT_OFF&_INTRC_OSC_NOCLKOUT __CONFIG _CONFIG2, _WRT_OFF&_BOR21V ;---------------------------------------------------------------------- ; Configuration Word Register1: ; Low Voltage Programming -> LVP_OFF(disabled) ; Monitor Clock Fail-safe -> FCMEN_OFF(disabled) ; Internal External Switch Over Mode -> IESO_OFF(disabled) ; Brown Out Detect -> BOR_OFF(disabled) ; Data EE Read Protect -> CPD_OFF (disabled) ; Code Protect -> CP_OFF ; Master Clear Enable -> MCLRE_ON (enabled) ; Power Up Timer -> PWRTE_ON (enabled) ; Watchdog Timer -> WDT_OFF (disabled) ; Oscillator -> INTRC_OSC_NOCLKOUT (Internal RC No Clock) ; Configuration Word Register2: ; Flash Memory Write Protection off -> WRT_OFF (disabled) ; Brown-out Reset Voltage -> BORV21 (2,1 V) ;---------------------------------------------------------------------- ; VARIABLE DEFINITIONS ;---------------------------------------------------------------------- CBLOCK 0x20 ; Block beginnt bei 0x20 (RAM) max_count ; Maximalwert für enc_count enc_count ; Zählregister encoder enc_old ; old position enc_new ; new position program ; Programm Nr old_program ; Hilfsvariable mode_progr ; Merker mode 'program' -> 1 shift ; shadow PORTD w_temp ; w rethun in w_temp status_temp ; STATUS rethun in status_temp pclath_temp ; PCLATH rethun in pclath_temp mult_reg ; speichert Schrittzeit mult mult ; Schrittzeit mult mult_old ; Hilfsregister für Schrittzeit isr_count ; Zählregister isr_Routine data_byte ; Datenregister count ; Zählregister temp_01 ; temporäres Zählregister 01 temp_02 ; temporäres Zählregister 02 ten ; Display Schrittzeit Zehner hun ; Display Schrittzeit Hunderter wertstelle1 ; Wert vordere Stelle wertstelle2 ; Wert hintere Stelle ENDC ;---------------------------------------------------------------------- ; CONSTANT DEFINITIONS ;---------------------------------------------------------------------- ti_start equ d'178' ; Zeitbasis der Schrittzeit: ; (256-ti_start)*128µs = 10,0ms enc_switch equ d'4' ;---------------------------------------------------------------------- ; EEPROM INITIALIZATION ; The 16F887 has 256 bytes of non-volatile EEPROM, ; starting at address 0x2100, ending at address 0x21FF ;---------------------------------------------------------------------- ; ORG 0x2100 ; erste EEPROM-Adresse ; DE 0x00 ; Inhalt 0x00 ;---------------------------------------------------------------------- ORG 0x000 ; Anfangsadresse 0x000 ResetVector movlw high(main) movwf PCLATH goto main ORG 0x004 ; Interrupt-Einsprung-Adresse ;---------------------------------------------------------------------- ; Hauptprogramm: main ;---------------------------------------------------------------------- main BANKSEL OSCCON movlw b'01100000' ; 4 MHz einstellen ! ; -000---- IRCF Internal Oscillator Frequency Select bits ; 111(8 MHz) 101(2 MHz) 011(500 kHz) 001(125 kHz) ; 110(4 MHz) 100(1 MHz) 010(250 kHz) 000(31 kHz) movwf OSCCON BANKSEL PORTD clrf shift movlw d'50' movwf mult ; Multiplikator movwf mult_old call _init_io ; config I/O call _LCD_init_4bit ; 4-Bit-Modus call _LCD_clear_4bit movlw d'8' movwf count movlw d'100' ; display 2 seconds call _delay_2.5m decfsz count, f goto $-3 call _LCD_clear_4bit ; Anz. löschen movlw 0x01 call _LCD_pos call LCD_text_ZAHL1 movlw 0x41 ; 2. Zeile, 1. Stelle call _LCD_pos call LCD_text_ZAHL2 ;---------------------------------------------------------------------- mainloop mode_ZAHL1 movf mult, w movwf enc_count movlw d'99' movwf max_count call _read_encoder movwf mult end_mainloop_ZAHL1 call _bta ; byte to ascii movlw 0x0E call _LCD_pos movf hun, w call _write_4bit ; display 'hun' movlw 0x0F call _LCD_pos movf ten, w addlw '0' call _write_4bit ; display 'ten' mode_ABC end_mainloop_ABC call ABCDE movlw 0x4E call _LCD_pos movf wertstelle1, w call _write_4bit ; display 'wertstelle1' movlw 0x4F call _LCD_pos movf wertstelle2, w call _write_4bit; display 'wertstelle2' goto mainloop ;---------------------------------------------------------------------- ABCDE Zahl50 call zahl_2 call zahl_H6 return zahl_1 movlw 0x31 movwf wertstelle1 return zahl_2 movlw 0x32 movwf wertstelle1 return zahl_3 movlw 0x33 movwf wertstelle1 return zahl_4 movlw 0x34 movwf wertstelle1 return zahl_5 movlw 0x35 movwf wertstelle1 return zahl_6 movlw 0x36 movwf wertstelle1 return zahl_H0 movlw 0x30 movwf wertstelle2 return zahl_H1 movlw 0x31 movwf wertstelle2 return zahl_H2 movlw 0x32 movwf wertstelle2 return zahl_H3 movlw 0x33 movwf wertstelle2 return zahl_H4 movlw 0x34 movwf wertstelle2 return zahl_H5 movlw 0x35 movwf wertstelle2 return zahl_H6 movlw 0x36 movwf wertstelle2 return zahl_H7 movlw 0x37 movwf wertstelle2 return zahl_H8 movlw 0x38 movwf wertstelle2 return zahl_H9 movlw 0x39 movwf wertstelle2 return return ;---------------------------------------------------------------------- ;byte_to_ascii ;---------------------------------------------------------------------- _bta ?90..99 movlw d'90' subwf mult, w btfss STATUS, C ; Zahl zw. 50 und 59 ? goto ?80..89 ; nein movwf ten ; ja movlw '9' movwf hun goto end_bta ?80..89 movlw d'80' subwf mult, w btfss STATUS, C ; Zahl zw. 50 und 59 ? goto ?70..79 ; nein movwf ten ; ja movlw '8' movwf hun goto end_bta ?70..79 movlw d'70' subwf mult, w btfss STATUS, C ; Zahl zw. 50 und 59 ? goto ?60..69 ; nein movwf ten ; ja movlw '7' movwf hun goto end_bta ?60..69 movlw d'60' subwf mult, w btfss STATUS, C ; Zahl zw. 50 und 59 ? goto ?50..59 ; nein movwf ten ; ja movlw '6' movwf hun goto end_bta ?50..59 movlw d'50' subwf mult, w btfss STATUS, C ; Zahl zw. 50 und 59 ? goto ?40..49 ; nein movwf ten ; ja movlw '5' movwf hun goto end_bta ?40..49 clrc movlw d'40' subwf mult, w btfss STATUS, C ; Zahl zw. 40 und 49 ? goto ?30..39 ; nein movwf ten ; ja movlw '4' movwf hun goto end_bta ?30..39 clrc movlw d'30' subwf mult, w btfss STATUS, C ; Zahl zw. 30 und 39 ? goto ?20..29 ; nein movwf ten ; ja movlw '3' movwf hun goto end_bta ?20..29 clrc movlw d'20' subwf mult, w btfss STATUS, C ; Zahl zw. 20 und 29 ? goto ?10..19 ; nein movwf ten ; ja movlw '2' movwf hun goto end_bta ?10..19 clrc movlw d'10' subwf mult, w btfss STATUS, C ; Zahl<20 ? goto ?0..9 ; nein movwf ten ; ja movlw '1' movwf hun goto end_bta ?0..9 clrc movlw d'10' subwf mult, w btfsc STATUS, C ; Zahl<10, dann C=0 ? goto ?10..19 ; nein movf mult, w ; ja movwf ten ; movlw ' ' movwf hun end_bta return ;---------------------------------------------------------------------- ; Unterprogramm _read_encoder ; Kanal A (CHA) an RA2, Kanal B (CHB) an RA3 ; benötigte Variablen: enc_old, enc_new, max_count, enc_count ; in: PORTA (RA2, RA3) ; max_count (max. Zählerstand) ; enc_count (ab hier wird gezählt) ; out: w (neuer Zählerstand) ;---------------------------------------------------------------------- _read_encoder movf PORTA, w ; Port A -> w movwf enc_new ; w->enc_new rrf enc_new, f ; rotieren rrf enc_new, f movlw b'00000011' ; maskieren andwf enc_new, f movf enc_new, w xorwf enc_old, w btfsc STATUS, Z ; verstellt ? goto end_encoder ; nein, (Z=1) ;------------------------------------------------------------ ; nun prüfen in welche Richtung der Encoder ; verstellt ist ; rechts drehen: 1->3->2->0->1->3->2->0 ; links drehen: 2->3->1->0->2->3->1->0 ; Rastung bei CHA=CHB=1 und bei CHA=CHB=0 ;------------------------------------------------------------ old_1? movf enc_old, w ; ja sublw d'1' btfss STATUS, Z ; enc_old = 1 ? goto old_3? ; nein, 3 prüfen movf enc_new, w ; ja, sublw d'0' ; Folgezahl teshun btfss STATUS, Z ; enc_new = 0 ? goto right ; nein, rechts gedreht goto left ; ja, links gedreht ;------------------------------------------------------------ old_3? movf enc_old, w sublw d'3' btfss STATUS, Z ; enc_old = 3 ? goto old_2? ; nein, 2 prüfen movf enc_new, w ; ja, sublw d'1' ; Folgezahl teshun btfss STATUS, Z ; enc_new = 1 ? goto right ; nein, rechts gedreht goto left ; ja, links gedreht ;------------------------------------------------------------ old_2? movf enc_old, w sublw d'2' btfss STATUS, Z ; enc_old = 2 ? goto old_0? ; nein, 0 prüfen movf enc_new, w ; ja, sublw d'3' ; Folgezahl teshun btfss STATUS, Z ; enc_new = 3 ? goto right ; nein, rechts gedreht goto left ; ja, links gedreht ;------------------------------------------------------------ old_0? movf enc_old, w sublw d'0' btfss STATUS, Z ; enc_old = 0 ? goto end_encoder ; nein->end_encoder movf enc_new, w ; ja, sublw d'2' ; Folgezahl teshun btfss STATUS, Z ; enc_new = 2 ? goto right ; nein, rechts gedreht ;---------------------------------------------------------------------- left movlw 0x03 ; ja, nach links gedreht subwf enc_new, w btfsc STATUS, Z ; Rastlage CHA=CHB=1 ? goto decr_count ; ja, dann zu decr_count movlw 0x00 ; nein subwf enc_new, w ; btfss STATUS, Z ; Rastlage CHA=CHB=0 ? goto end_encoder ; nein, zu end_encoder decr_count decf enc_count, f ; ja, enc_count -1 movlw d'0' subwf enc_count, w btfss STATUS, Z ; enc_count = 0 ? goto end_encoder ; nein movlw 0x01 ; ja, enc_count = 1 movwf enc_count ; linke Endst. = 1 goto end_encoder ;---------------------------------------------------------------------- right movlw 0x03 subwf enc_new, w btfsc STATUS, Z ; Rastlage = 3 ? goto incr_count ; ja->enc_count movlw 0x00 subwf enc_new, w btfss STATUS, Z ; Rastlage = 0 ? goto end_encoder ; nein->end_enc. incr_count movf max_count, w ; ja subwf enc_count, w btfss STATUS, Z ; max erreicht ? incf enc_count, f ; nein-> +1 end_encoder movf enc_new, w ; ja movwf enc_old ; w->enc_old movf enc_count, w return ;---------------------------------------------------------------------- ; Unterprogramm: _delay_2.5m ; benötigte Zählregister: temp_01, temp_02 ; Grundverzögerung: 2.5 ms ; Multiplikator: Übergabe durch w-Register ;---------------------------------------------------------------------- _delay_2.5m movwf temp_02 ; w -> temp_02 wait_2 movlw d'250' ; 250 -> w movwf temp_01 ; w -> temp_01 wait_1 nop ; 1µs nop ; 1µs nop ; 1µs nop ; 1µs nop ; 1µs nop ; 1µs nop ; 1µs decfsz temp_01, f ; 1 µs goto wait_1 ; 2 µs decfsz temp_02, f ; 1 µs goto wait_2 ; 2 µs return ;---------------------------------------------------------------------- _delay_40u movlw d'10' movwf temp_01 ; w -> temp_1 nop ; 2 * nop decfsz temp_01, f ; 'normal' 1 state goto $-2 ; 2 states return ;---------------------------------------------------------------------- _init_io BANKSEL ANSEL ; -> Bank 3 clrf ANSEL ; Port A, Port E: Analog-Fkt. aus, digital I/O clrf ANSELH ; Port B: Analog-Fkt. aus, digital I/O BANKSEL TRISA ; -> Bank 1 movlw 0xff movwf TRISA ; RA0-RA7 Eingänge clrf TRISD ; RD0-RD7 Ausgänge BANKSEL PORTD ; Bank 0 clrf PORTD ; Port D löschen return ;---------------------------------------------------------------------- _LCD_init_4bit ; 4-bit-mode movlw d'8' call _delay_2.5m ; 20*2,5 ms bcf LCD_DATA, LCD_RS ; control in movlw b'00100000' ; Set->8 bit call _write_high_nibble call _delay_40u movlw b'00101000' ; Set->4 bit call _write_4bit ; 2 Z. 5x8 Dot movlw b'00001100' ; On/Off call _write_4bit ; Control movlw b'00000110' ; Entry Mode Set call _write_4bit ; bsf LCD_DATA, LCD_RS ; data in return ;---------------------------------------------------------------------- _LCD_clear_4bit bcf LCD_DATA, LCD_RS ; control in movlw 0x01 call _write_4bit bsf LCD_DATA, LCD_RS ; data_in movlw d'2' call _delay_2.5m return ;---------------------------------------------------------------------- _LCD_pos ; Übergabe -> w bcf LCD_DATA, LCD_RS ; control in addlw 0x80 call _write_4bit bsf LCD_DATA, LCD_RS ; data_in return ;---------------------------------------------------------------------- _write_high_nibble ; Übergabe -> w movwf data_byte ; w->data_byte movlw 0x0F ; andwf LCD_DATA, f ; LCD_DATA maskieren movf data_byte, w ; andlw 0xF0 ; data_byte maskieren iorwf LCD_DATA, f ; high-nibble bsf LCD_DATA, LCD_E nop bcf LCD_DATA, LCD_E call _delay_40u return ;---------------------------------------------------------------------- _write_4bit ; Übergabe -> w movwf data_byte call _write_high_nibble rlf data_byte, f rlf data_byte, f rlf data_byte, f rlf data_byte, f movf data_byte, w call _write_high_nibble return ;---------------------------------------------------------------------- END ; Programmende ;----------------------------------------------------------------------