Inhaltsverzeichnis
PIC16(F/LF)XXX
Einige ASM Beispiele für PC12... und PIC16... befinden sich in http://www.rn-wissen.de/index.php/PIC_Assembler#Codeschnipsel .
UART Routine
Senden:
RS232send banksel TXREG ; Zur Bank von TXREG umschalten movwf TXREG ; Move w to TXREG banksel PIR1 ; Zur Bank von PIR1 umschalten Waittx btfss PIR1, TXIF ; Wenn bit in PIR1,TXIF HIGH übergehe den nästen Befehl goto Waittx ; Gehe zu WaitTX bcf PIR1, TXIF ; Interrupt Flag Löschen (Optionam muss nicht umbedinkt gemacht werden) return
Fehlerbehandlung:
uart_ferr ; Auf Frameerror testen btfsc RCSTA, FERR goto uart_err return uart_oerr ; Auf Overrunerror testen btfsc RCSTA, OERR goto uart_err return uart_err ; Fehlerbehandlung ; Fehlerbehanlungsroutine hier einfügen!!!!!!!!!!!!!!!!! ; z.b. Interupt beenden und RCREG nicht sichern bcf RCSTA, CREN ; Fehler Bits Löschen bsf RCSTA, CREN return ; Interupt beenden und zurück zur Main schleife
Entfangen per Interupt:
int ; Interupt STATUS und W sichern movwf wtemp ; W Sichern swapf STATUS, w ; Status Sichern movwf stemp ; Status Speichern btfss PIR1, RCIF ; Interupt vom USART wenn nicht goto intend ; Interupt beenden ; Interupt Code uart call uart_ferr ; Auf Frame Errors Testen <b>(siehe Fehlerbehandlung) </b> call uart_oerr ; Auf Overrunerrors Testen movf RCREG,w ; uart RX Reg sichern movwf rx intend ; Interupt beenden und STATUS + W zurückspielen bcf PIR1, RCIF ; Interuptflag Löschen swapf stemp, w ; Status restore movwf STATUS swapf wtemp, f ; W restore swapf wtemp, w retfie ; Interupt Beenden
DG-16080 Text-Mode
Senden:
movlw 0x00 movwf adrl ; LOW ADR movlw 0x00 movwf adrh ; High ADR call disp_send_char ; Adressregister setzen und vorbereiten zum Daten schreiben movlw B'01001000' ; H call disp_send_d movlw B'01100001' ; a call disp_send_d movlw B'01110101' ; u call disp_send_d
Display Anschlüsse:
#define RS PORTC, 0 ; Display Command(H)/DATA(L) #define RW PORTC, 2 ; Display Read(H)/Write(L) #define E PORTC, 3 ; Display Enable #define CS PORTC, 4 ; Display Chip Enable(L) #define WDATA PORTB ; Display Datenport (PORTB) #define YM PORTA, 3 ; Touch y- ADC #define YP PORTA, 2 ; Touch y+ PWR #define XP PORTA, 4 ; Touch x+ PWR #define XM PORTA, 1 ; Touch x- ADC
dg-16080.inc
disp_init ; Display Inialisieren bcf RW ; Startbedinungen herstellen nop bcf CS movlw 0x00 ; Mode Control REG call disp_send_c ; Send Command movlw b'00111000' ; DB5=ON/OFF, DB4=Master/Slave, DB3=Blink, DB2=Coursor, DB1/DB0=TEXT(00)/GRAFIG(10) call disp_send_d ; Send Data movlw 0x01 ; Character Pitch REG call disp_send_c ; Send Command movlw 0x75 ; 7x8px call disp_send_d ; Send Data movlw 0x02 ; Nummer oh Char REG call disp_send_c ; Send Command movlw D'26' ; Anzahl horit. Zeichen -1 call disp_send_d ; Send Data movlw 0x03 ; Display Duty REG call disp_send_c ; Send Command movlw 0x4F ; Display Duty call disp_send_d ; Send Data movlw 0x04 ; Cursor Position REG call disp_send_c ; Send Command movlw D'7' ; Curserstrich y-Pos -1 call disp_send_d ; Send Data return disp_send_c ; Send Command bsf RS movwf WDATA bsf E nop bcf E call delay_10_µs return disp_send_d ; Send DATA bcf RS movwf WDATA bsf E nop bcf E call delay_10_µs return disp_cls ; Display Löschen Textmode movlw 0x0A ; Low Reg call disp_send_c movlw 0x00 ; Low Adr call disp_send_d movlw 0x0B ; High Reg call disp_send_c movlw 0x00 ; High Adr call disp_send_d movlw 0x0C ; DATA REG call disp_send_c movlw D'65' movwf count disp_cls_loop movlw B'00100000' ; 65x5 call disp_send_d call disp_send_d call disp_send_d call disp_send_d call disp_send_d decfsz count,1 goto disp_cls_loop return disp_send_char ; Zeichen senden (ADRL,ADRH,Char) movlw 0x0A ; Low Reg call disp_send_c movf adrl,w ; Low Adr call disp_send_d movlw 0x0B ; High Reg call disp_send_c movf adrh,w ; High Adr call disp_send_d movlw 0x0C ; DATA REG call disp_send_c return
Touchscreen: Config für die ADCs VREF=VDD
banksel TRISA ; Zu Bank von TRISA umschalten movlw B'00001011' ; PortA I/O setzen (1=In, 0=Out) (Reinfolge RB7,RB6...) movwf TRISA ; PortA I/O setzen banksel ADCON1 ; Zur Bank von ADCON1 umschalten movlw B'10010100' ; Alle Analog VDD=VREF, Right jutyfy, fosc/8, AN0,1,3=AN, AN2,4-7=Dig. movwf ADCON1 ; Move w to ADCON1 banksel ADCON0 ; zu Bank von TRISA umschalten movlw B'01000001' ; Enable ADC movwf ADCON0 ; Move w to ADCON0
touch_read ; Y bcf YP bsf XP bcf ADCON0,5 ; ADC Auswehlen bcf ADCON0,4 bsf ADCON0,3 call adc_read ; Read ADC AD1 Daten banksel ADRESL movf ADRESL,w movwf ylow banksel ADRESH movf ADRESH,w movwf yhigh bcf YP bcf XP ; X bcf XP bsf YP bcf ADCON0,5 ; ADC Auswehlen bsf ADCON0,4 bsf ADCON0,3 call adc_read ; Read ADC AD3 Daten banksel ADRESL movf ADRESL,w movwf xlow banksel ADRESH movf ADRESH,w movwf xhigh bcf YP bcf XP return adc_read movlw D'30' ; Wait Acquisition Time 20MHz movwf count adc_read_loop decfsz count,F goto adc_read_loop bsf ADCON0,GO ; Setze ADCON0,GO, Int A/D Conversation adc_read_loop_1 ; Wen ADC bereit btfsc ADCON0,GO ; Ist ADCON0,GO = 0 dann ubergehe den nesten Befehl goto adc_read_loop_1 ; Warte bis ADC fertig return
--Theborg 12:00, 23. Jan 2010 (CET)
Schieberegister (z.b. CD4094)
; Datenleitungen Schiberegister alles Ausgänge #define CLK PORTB, 0 #define D PORTB, 1 #define STR PORTB, 2 #define OE PORTB, 3
cd4094_send banksel PORTB bcf OE bcf STR btfsc cdsend, 0 bsf D btfss cdsend, 0 bcf D bsf CLK bcf CLK btfsc cdsend, 1 bsf D btfss cdsend, 1 bcf D bsf CLK bcf CLK btfsc cdsend, 2 bsf D btfss cdsend, 2 bcf D bsf CLK bcf CLK btfsc cdsend, 3 bsf D btfss cdsend, 3 bcf D bsf CLK bcf CLK btfsc cdsend, 4 bsf D btfss cdsend, 4 bcf D bsf CLK bcf CLK btfsc cdsend, 5 bsf D btfss cdsend, 5 bcf D bsf CLK bcf CLK btfsc cdsend, 6 bsf D btfss cdsend, 6 bcf D bsf CLK bcf CLK btfsc cdsend, 7 bsf D btfss cdsend, 7 bcf D bsf CLK bcf CLK bsf STR bsf OE return
--Theborg 23:13, 15. Sep 2009 (CEST)
MAX7456 (S/W OSD)
Variabeln und I/0:
cblock 0x70 ; Variabeln ab 0x70 setzen alle Register max 16stk. SPI_DATA_WRITE ; Zu Sendene SPI Daten SPI_DATA_READ ; Gelesend SPI Daten m_char ; Maxim7456 und sda5708 Zeichen m_pos ; Maxim7456 Position endc ; Variabeln setzen beenden #define SPI_CS PORTC, 7; SPI Slave Select max7456
Config:
; PORTC banksel TRISC ; auf Bank 1 umschalten movlw B'10010000' ; PortC I/O setzen (1=In, 0=Out) (Reinfolge RC7,RC6...) movwf TRISC ; PortC I/O setzen banksel PORTC clrf PORTC ; PortC auf 0 setzen ; SPI banksel SSPSTAT movlw B'11000000' ; Mitlere Geschwindigkeit Output Time movwf SSPSTAT banksel SSPCON movlw B'00100001' ; MODE 1,1, SPI MASTER, 1/16 Tosc SSP ON movwf SSPCON banksel PORTC bsf SPI_CS ; SPI Slave Select aus (high) return
SPI Sende/Enfangs Rotinen:
SPI_Send banksel PORTC bcf SPI_CS ; Chip Select an (Low) nop nop nop banksel SSPBUF movf SPI_DATA_WRITE, W movwf SSPBUF banksel SSPSTAT SPI_Wait btfss SSPSTAT, BF ; Ist das Senden Komplet ? goto SPI_Wait ; Wen nicht gehe zu SPIWait nop nop nop banksel PORTC bsf SPI_CS ; Chip Select aus (High) return SPI_Read banksel PORTC bcf SPI_CS nop nop nop banksel SSPBUF movf SSPBUF, W movwf SPI_DATA_READ banksel PORTC nop nop nop banksel PORTC bsf SPI_CS return
Defines ASCII to MAX7456 Charset und Config und Schreibrotienen (Achtung es kann sein das die #define nicht mit mpasm Funktioniert mit gpasm wird groß und kleinschreibung unterschiden):
max7456_define ; Defines für den max7456 Zeichensatz #define m_sp 0x00 ; Space #define m_1 0x01 #define m_2 0x02 #define m_3 0x03 #define m_4 0x04 #define m_5 0x05 #define m_6 0x06 #define m_7 0x07 #define m_8 0x08 #define m_9 0x09 #define m_0 0x0A #define m_A 0x0B #define m_B 0x0C #define m_C 0x0D #define m_D 0x0E #define m_E 0x0F #define m_F 0x10 #define m_G 0x11 #define m_H 0x12 #define m_I 0x13 #define m_J 0x14 #define m_K 0x15 #define m_L 0x16 #define m_M 0x17 #define m_N 0x18 #define m_O 0x19 #define m_P 0x1A #define m_Q 0x1B #define m_R 0x1C #define m_S 0x1D #define m_T 0x1E #define m_U 0x1F #define m_V 0x20 #define m_W 0x21 #define m_X 0x22 #define m_Y 0x23 #define m_Z 0x24 #define m_a 0x25 #define m_b 0x26 #define m_c 0x27 #define m_d 0x28 #define m_e 0x29 #define m_f 0x2A #define m_g 0x2B #define m_h 0x2C #define m_i 0x2D #define m_j 0x2E #define m_k 0x2F #define m_l 0x30 #define m_m 0x31 #define m_n 0x32 #define m_o 0x33 #define m_p 0x34 #define m_q 0x35 #define m_r 0x36 #define m_s 0x37 #define m_t 0x38 #define m_u 0x39 #define m_v 0x3A #define m_w 0x3B #define m_x 0x3C #define m_y 0x3D #define m_z 0x3E #define m_KLa 0x3F ; ( #define m_KLz 0x40 ; ) #define m_. 0x41 #define m_? 0x42 #define m_sem 0x43 ; ; #define m_: 0x44 #define m_ko 0x45 ; , #define m_ag 0x46 ; Agostroff #define m_bs 0x47 ; Backslasch #define m_as 0x48 ; Anfürungsstriche #define m_minus 0x49 ; Minus #define m_ka 0x4A ; < #define m_ga 0x4B ; > #define m_at 0x4C ; @ oder at #define m_wait 0xfb ; Wartezeichen #define m_ls 0xf9 ; Lautsprecher #define m_lso 0xfa ; Tonsignal #define m_ff 0xff ; Ausgefültes feld return max7456_conf ; Max7456 Config movlw 0x00 ; VM0 Video Mode Register 0 (Write) movwf SPI_DATA_WRITE call SPI_Send movlw B'01001000' ; 0 , 1=PAL, 00=Auto Sync, 1=Enable OSD, 0=Enable OSD immer, 0=SW RST, 0=Enable Video Buffer movwf SPI_DATA_WRITE call SPI_Send movlw 0x01 ; VM1 Video Mode Register 1 movwf SPI_DATA_WRITE call SPI_Send movlw B'00000100' ; 0 = NA, 000=Background MODE Brightness 100%, 11=Blinking Time 160ms, 00=Blinking Duty Cycle BT:BT movwf SPI_DATA_WRITE call SPI_Send movlw 0x02 ; HOS Horizontal Offset Register movwf SPI_DATA_WRITE call SPI_Send movlw B'00101111' ; 00 = NA, 100000 = Horitzontal Offset movwf SPI_DATA_WRITE call SPI_Send movlw 0x03 ; VOS Vertical Offset Register movwf SPI_DATA_WRITE call SPI_Send movlw B'00010111' ; 000 = NA, 10000 = Vertical Offset movwf SPI_DATA_WRITE call SPI_Send return max7456_cls ; max7456 ausgabe Löschen movlw 0x00 ; VM0 Video Mode Register 0 (Write) movwf SPI_DATA_WRITE call SPI_Send movlw B'01001010' ; 0 , 1=PAL, 00=Auto Sync, 1=Enable OSD, 0=Enable OSD immer, 1=SW RST, 0=Enable Video Buffer movwf SPI_DATA_WRITE call SPI_Send call max7456_conf return max7456_add_high ; High adressbereich movlw 0x05 ; Ersten 256 zeichen Low = 0x00, Letzten 256 Zeichen High=0xff movwf SPI_DATA_WRITE call SPI_Send movlw 0xFF movwf SPI_DATA_WRITE call SPI_Send return max7456_add_low ; Low Adressbereich movlw 0x05 ; Ersten 256 zeichen Low = 000, Letzten 256 Zeichen High=225 movwf SPI_DATA_WRITE call SPI_Send movlw 0x00 movwf SPI_DATA_WRITE call SPI_Send return max7456_send_char movlw 0x06 ; Zeichen Position links nach rechts erste reihe 0-29, 30-...... movwf SPI_DATA_WRITE call SPI_Send movf m_pos, W movwf SPI_DATA_WRITE call SPI_Send movlw 0x07 ; Zeichen Sonderzeichen sihe Define in max7456.inc movwf SPI_DATA_WRITE call SPI_Send movf m_char, W movwf SPI_DATA_WRITE call SPI_Send return
Zeichen Senden:
movlw D'12' ; Position movwf m_pos movlw m_e ; Zeichen (hier das kleine e) oder direkt den wert des Zeichens im MAX7456 REG. movwf m_char call max7456_send_char; Schreiben
High/low Adressbereich (low = ersten 256 Zeichen, High die letzten 128 Zeichen);
call max7456_add_low ; Low Adressbereich ;call max7456_add_high; Low Adressbereich
--Theborg 23:13, 15. Sep 2009 (CEST)
PIC18(F/LF)xxxx
Programmspeicher (Flash) beschreiben und lesen
Weil das Programteil wurde mit PAD erstellt, ist fast nicht kommentiert. Zuerst wird der benötigter Flash-Bereich gelöscht und danach werden dort Daten aus RAM kopiert (gespeichert). Dazu wurden zwei Register "Tmp" und "Tmp1" benutzt, die im Program definiert werden müssen.
Store movff F2,FS2 movff F1,FS1 movff F0,FS0 clrf TBLPTRU ; erase flash memory (7BC0-7FFF) movlw 0x7B movwf TBLPTRH movlw 0xC0 movwf TBLPTRL movlw 0x11 movwf Tmp FlashEraseL bsf EECON1,EEPGD bcf EECON1,CFGS bsf EECON1,WREN bsf EECON1,FREE bcf INTCON,GIE movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1,WR bsf INTCON,GIE btfsc EECON1,WR bra $-2 movlw 0x40 addwf TBLPTRL btfsc _C incf TBLPTRH,1 decfsz Tmp,1 bra FlashEraseL lfsr FSR0,0x0020 ; write parameter 32 bytes (7BC0-7BDF) clrf TBLPTRU movlw 0x7B movwf TBLPTRH movlw 0xC0 movwf TBLPTRL tblrd*- movlw 4 movwf Tmp1 FlashProgPL movlw 8 movwf Tmp WriteFPL movff POSTINC0,TABLAT tblwt+* decfsz Tmp,1 bra WriteFPL bsf EECON1,EEPGD bcf EECON1,CFGS bsf EECON1,WREN bcf INTCON,GIE movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1,WR bcf PIR2,EEIF bsf INTCON,GIE decfsz Tmp1,1 bra FlashProgPL bcf EECON1,WREN WriteSMP lfsr FSR0,0x100 ; write samples 1024 bytes (7C00-7FFF) clrf TBLPTRU movlw 0x7C movwf TBLPTRH clrf TBLPTRL tblrd*- movlw 0x80 movwf Tmp1 FlashProgL movlw 8 movwf Tmp WriteFL movff POSTINC0,TABLAT tblwt+* decfsz Tmp,1 bra WriteFL bsf EECON1,EEPGD bcf EECON1,CFGS bsf EECON1,WREN bcf INTCON,GIE movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1,WR bcf PIR2,EEIF bsf INTCON,GIE decfsz Tmp1,1 bra FlashProgL bcf EECON1,WREN return
Um die Daten aus Flash zurück auf ursprüngliche Adressen im RAM zu übertragen, würde folgendes Programmfragment verwendet in dem Register "STmp" benutzt wurde, der auch im Programm definiert werden muss.
Restore lfsr FSR0,0x0020 ; restore parameter 32 bytes (7BC0-7BDF) clrf TBLPTRU movlw 0x7B movwf TBLPTRH movlw 0xC0 movwf TBLPTRL bsf EECON1,EEPGD bcf EECON1,CFGS FlashRAMP movlw 0x20 movwf STmp FlashRAMPL tblrd*+ movff TABLAT,POSTINC0 decfsz STmp,1 bra FlashRAMPL lfsr FSR0,0x100 ; restore samples 1024 bytes (7C00-7FFF) clrf TBLPTRU movlw 0x7C movwf TBLPTRH clrf TBLPTRL bsf EECON1,EEPGD bcf EECON1,CFGS call FlashRAM call FlashRAM call FlashRAM FlashRAM clrf STmp FlashRAML tblrd*+ movff TABLAT,POSTINC0 decfsz STmp,1 bra FlashRAML return
Hex Dec Wandlung
Weil das UP mit PAD erstellt wurde, ist es fast nicht kommentiert. Genaue Funktionsweise und Definitionen der Register sind im http://www.rn-wissen.de/index.php/PIC_Assembler#Hex_Dec_Wandlung beschrieben.
Übrigens, das UP wurde ursprünglich für PIC18... erstellt und danach auf PIC12.. und PIC16... umgeschrieben. Durchs Vergleichen sieht man den Unterschied zwischen den PIC Familien.
Hex_Dec call CClr ; Hex>A, D>Dec call DClr movlw 1 movwf C0 movlw 0x18 ; 24 bit Hex (6digits) > 32 bit Dec (8 digits) movwf HTmp Hex_DecL btfsc A0,0 call AddDC call CopyCB call AddCB call ARotRb decfsz HTmp,1 bra Hex_DecL return CClr lfsr FSR0,C4 movlw 5 bra RegClr DClr lfsr FSR0,D4 movlw 5 RegClr movwf ATmp RegClrL clrf POSTINC0 decfsz ATmp,1 bra RegClrL return CopyCB lfsr FSR0,C0 lfsr FSR1,B0 CopyReg movlw 5 movwf ATmp CopyRegL movff POSTDEC0,POSTDEC1 decfsz ATmp,1 bra CopyRegL return AddCB lfsr FSR0,B0 ; C+B>C lfsr FSR1,C0 bra AddReg AddDC lfsr FSR0,C0 ; D+C>D lfsr FSR1,D0 AddReg bcf _Ferr bcf _Fcrp movlw 5 movwf ATmp AddRegL bcf _Fcra movf INDF0,0 addwf INDF1,0 btfsc _C bsf _Fcra daw movwf INDF1 btfsc _C bsf _Fcra btfss _Fcrp bra AddRegN movlw 1 addwf INDF1,0 daw movwf INDF1 btfsc _C bsf _Fcra AddRegN bcf _Fcrp btfsc _Fcra bsf _Fcrp movf POSTDEC0,1 movf POSTDEC1,1 decfsz ATmp,1 bra AddRegL btfsc _Fcra bsf _Ferr return ARotRb lfsr FSR0,A2 RRotRb movlw 3 ; rotates A register 1 bit right movwf RTmp bcf _Fcrp btfsc A0,0 bsf _Fcrp RRotRbL bcf _Fcra btfsc INDF0,0 bsf _Fcra bcf _C btfsc _Fcrp bsf _C rrcf INDF0,1 bcf _Fcrp btfsc _Fcra bsf _Fcrp movf POSTINC0,1 decfsz RTmp,1 bra RRotRbL return