; 16/01/2012 ; Correctif adressage mode LCD 2x8 en 1x16 => OK ; affichage espace au lieu de 0 inutiles ; checksum=3AAB ; rev 11 sept 2004 test BAD ; pB avec include tempo4M.sub.. rajout chemin ; Pb affichage ; Version originale: ; Program : "FREQLCD.ASM" ; Date : 6/11/98 Last update : 08/05/99 ; Description : Fréquencemêtre 50 MHz ; Authors : Loic LEFEBVRE ; Tests : ; affichage LCD mode 4 bits ;_________________directives____________________________________ title "Fréquencemêtre 50 MHz V1.1" processor 16F84 include p16f84.inc __config _PWRTE_ON & _WDT_OFF & _XT_OSC ; 3FF1 radix DEC errorlevel -302 include macros.lib ;___________________________________Constants_______________________________ RAM equ h'0C' ; pour 16F84 mais 0x20 pour 16F628, 16F88 YES equ 1 NO equ 0 ;______________________________Port configuration___________________________ ; ;PORTA ;----- ; 5 = R/W 'Afficheur LCD) au 0V ; A_0 17 (Out) 6 = E (afficheur LCD 1x16) ; A_1 18 (Out) 4 = RS (afficheur LCD 1x16) ; A_2 1 (Out) = Power control ; A_3 2 (Out) = signal pour debordement Prescaler ; A_4 3 (In) = Signal in ; xxx43210 CONFIGA equ B'00010000' ;Port B ;------ ; B_0 (In) = ; B_1 (In) = ; B_2 (In) = ; B_3 (In) = ; B_4 (Out) = | ; B_5 (Out) = | Bus de donnée (en sortie lors du reset) ; B_6 (Out) = | ; B_7 (Out) = | ; 76543210 CONFIGB equ B'00001111' PULLUP equ NO ;____________________________ registers configuration_______________________ ;OPTION ;====== ;RBPU/ : 0 Enable pull-ups resistors in port B ;INTEDG : x Interrupt edge select bit ;TOCS : 1 TMRO increment source on RA4/TOCKI pin ;TOSE : 0 TMR0 increment on rising RA4/TOCKI pin ;PSA : 0 Prescaler assignment bit (to TMR0) ;PS2 : 1 | ;PS1 : 1 |Ratio of 1/256 ;PS0 : 1 | CONFOPT equ B'00100111' ;INTERRUPTION ;============ ;GIE :0 Global interrupt enable bit ;EEIE :0 EE write complete interrupt enable bit ;T0IE :0 TMR0 overflow interrupt enable bit ;INTE :0 RB0/INT interrupt enable bit ;RBIE :0 RB port change interrupt enable bit ;T0IF :0 TMR0 overflow interrupt flag bit ;INTF :0 RB0/INT interrupt flag bit ;RBIF :0 RB port change interrupt flag bit CONFINT equ B'00000000' ;_________________________________Some Define_______________________________ #define E PORTA,0 #define RS PORTA,1 #define DATA_PORT PORTB ; Seulement de RB7 … RB4 #define DATA_DIR TRISB LCD_DATA EQU PORTB ; LCD: Port ou est branche le bus de donnee ( bits 4 a 7 ) LCD_DATA_TRIS EQU TRISB ; LCD: Port ou est branche le bus de donnee ( bits 4 a 7 ) LCD_CTRL EQU PORTA ; LCD: Port ou est branche le bus de commande LCD_CTRL_TRIS EQU TRISA ; LCD: Port ou est branche le bus de commande #define POWER PORTA,2 ;__________________________________Variables________________________________ cblock RAM Temp Temp0 TimeOut LCDtmp SaveW Result : 4 ; MSB first Count Char Thousand : 2 ; MSB first BCD0 BCD1 BCD2 BCD3 N Temp1 Temp2 Temp3 Temp4 Drapeaux ; 8 bits flags Dummy endc ;__________________________________vectors__________________________________ Reset START IntReq Intserv EEPROM EQU 0x2100 #define bank0 bcf STATUS,RP0 #define bank1 Bsf STATUS,RP0 ;___________________________________macros__________________________________ ;(2) IncPre macro ; Increment prescaler bsf PORTA,3 bcf PORTA,3 endm ;(12) Init macro clrf PORTA clrf PORTB Bank1 Movlf CONFIGA,TRISA ; Init ports A & B Movlf CONFIGB,TRISB Movlf CONFOPT,OPTION_REG ; Init config registers Movlf CONFINT,INTCON Bank0 bsf POWER ; Power On endm ;(6) InitMeasure macro Movlf B'00000011',Thousand ; Change: Thousand=0x3E7=(999)10 Movlf B'11100111',Thousand+1 clrf TMR0 ; Prescaler and tmr0 reset clrf Result+1 clrf Result endm ;(3) Ra3_out macro ; Ra3 is an output Bank1 bcf TRISA,3 Bank0 endm ;(3) Ra3_in macro ; Ra3 is an input Bank1 bsf TRISA,3 Bank0 endm ;(7/+1 if jump) TJZ16 macro file16,address ; If file16 = 0 jump to address Test file16 JZ TJZ16_MSB_ZERO nop nop goto TJZ16_END TJZ16_MSB_ZERO Test file16 +1 JZ address TJZ16_END endm ClearDisp macro movlw b'00000001' call SEND_CMD call T1mS ; Effacer l'ecran prend plus de 1mS endm DataOk macro ; Validation des données bsf E bcf E endm DDRam macro address movlw 0x80 + address call SEND_CMD endm Disp macro charvalue movlw charvalue call SEND_CHAR endm RSCmd macro ; Les données sont des commandes (RS=0) bcf RS endm RSChar macro ; Les données sont des caractéres (RS=1) bsf RS endm ShiftL macro ; Décalage vers la gauche de l'affichage movlw b'00011000' call SEND_CMD endm ;________________________________Subroutines________________________________ ;Tempo subroutines: ; SUBROUTINES ; Delays 1mS, 10mS, 100mS and 1S T1mS movwf SaveW movlw .248 movwf Temp1 Loop1mS nop decfsz Temp1,f goto Loop1mS movf SaveW,w return ;--------------------------- T10mS movwf SaveW movlw .10 movwf Temp2 Loop10mS call T1mS decfsz Temp2,f goto Loop10mS movf SaveW,w return ;---------------------------- T100mS movwf SaveW movlw .100 movwf Temp3 Loop100mS call T1mS decfsz Temp3,f goto Loop100mS movf SaveW,w return ;---------------------------- T1S movwf SaveW movlw .100 movwf Temp4 Loop1S call T10mS decfsz Temp4,f goto Loop1S movf SaveW,w return T975us Movlf .243 ,Temp0 ;WARNING only if Xtal= 4MHz Loop975us nop decfsz Temp0,f goto Loop975us return ;-------------------------------------------------- ;Name : Readprescal ;Function: Read the prescaler and store the result. ;Input : tmr0 and prescaler ;Output : Result +2 (tmr0) and Result +3 (prescaler) ;Call : None ;Register: Count Readprescal Movlf 255,Count Movff TMR0,Result+2 INCREMENT IncPre incf Count,f CJE TMR0,Result+2,INCREMENT movf Count,w sublw 255 movwf Result+3 return ;--------------------------------------------------------------------------- ; Bin To BCD conversion ( 32 bit word -> 8 digits ) ; Bin in Result, Result+1, Result+2, Result+3 ; BCD in BCD3, BCD2, BCD1, BCD0 Bin2BCD clrc Movlf .32,N ; Init Loop counter clrf BCD3 ; Init result clrf BCD2 clrf BCD1 clrf BCD0 LoopBB ; For N = 1 To 32 rlf Result+3,f ; Shift bin value (LSB first) rlf Result+2,f rlf Result+1,f rlf Result,f rlf BCD3,f ; Shift BCD value (LSD first) rlf BCD2,f rlf BCD1,f rlf BCD0,f decfsz N,f goto DecAdj ; Decimal adjust return DecAdj Movlf BCD3,FSR ; Init pointer call BCDAdj ; BCD adjust Movlf BCD2,FSR ; Init pointer call BCDAdj ; BCD adjust Movlf BCD1,FSR ; Init pointer call BCDAdj ; BCD adjust Movlf BCD0,FSR ; Init pointer call BCDAdj ; BCD adjust goto LoopBB BCDAdj movlw 3 addwf INDF,w movwf Temp btfsc Temp,3 ; Test if result > 7 movwf INDF movlw 30H addwf INDF,w movwf Temp btfsc Temp,7 ; Test if result > 7 movwf INDF ; Save as MSD return ;-------------------------------------------------------------------------- ; Display Frequency stored in BCD3, BCD2, BCD1 and BCD0 (LSD) ;OK DispFreq bsf Drapeaux,0 ; remplace zero par blanc DDRam 2 swapf BCD0,W ; Mhz andlw 0FH call DispHex movf BCD0,W andlw 0FH call DispHex Disp ' ' swapf BCD1,W ; Khz andlw 0FH call DispHex movf BCD1,W andlw 0FH call DispHex swapf BCD2,W andlw 0FH call DispHex Disp ' ' movf BCD2,W andlw 0FH call DispHex swapf BCD3,W andlw 0FH call DispHex movf BCD3,W andlw 0FH call DispHex Disp ' ' Disp 'H' Disp 'z' bcf Drapeaux,0 return ;--------------------------------------------------------------------------- ; Display hex digit ; input : w = hex ; OK DispHex ;test if zero ; movwf Dummy xorlw 0x00 btfsc STATUS,Z goto DispHex1 bcf Drapeaux,0 goto DispHex2 DispHex1 btfss Drapeaux,0 goto DispHex2 movlw ' ' call SEND_CHAR return DispHex2 addlw -0AH SkipNC addlw 7 addlw 3AH call SEND_CHAR return ;-------------------------------------------------------------------------- ; Description: Initialisation de l'afficheur LCD ; Entrée: Aucune ; Sortie: Aucune LCD_Init bcf E nop bcf RS nop call T10mS movlw 0x0f andwf LCD_DATA,F movlw 0x030 ; Commande pour interface 4 bits iorwf LCD_DATA,F bank1 movlw 0x0F andwf LCD_DATA_TRIS,W movwf LCD_DATA_TRIS ; Port en sortie bank0 bsf E nop bcf E call T10mS bsf E nop bcf E call T10mS bsf E nop bcf E call T100mS ; tempo 100ms , remplace l'attente Wait_Busy de l'afficheur movlw 0x0f andwf LCD_DATA,F movlw 0x020 ; Commande pour interface 4 bits iorwf LCD_DATA,F bsf E nop bcf E movlw 0x028 ; Envoi de la commande Fonction 4-bit , Font, Nombre de lignes call LCD_Cde movlw 0x008 ; display off call LCD_Cde movlw 0x00C ; display on (0x00C sans curseur, 0x00E avec , 0x00F clign. ) call LCD_Cde movlw 0x006 LCD_Cde movwf LCDtmp call T100mS ; tempo 100ms , remplace l'attente Wait_Busy de l'afficheur movlw 0x0f andwf LCD_DATA,F movf LCDtmp,w andlw 0xF0 iorwf LCD_DATA,F nop bcf RS nop bsf E nop bcf E movlw 0x0f andwf LCD_DATA,F swapf LCDtmp,W andlw 0xF0 iorwf LCD_DATA,F bsf E nop bcf E return ;--------------------------------------------------- ; Description: Transmet un caractére vers l'afficheur ; Entrée: Caractere dans le registre W ; Sortie: Aucune SEND_CHAR call T1mS ; Attendre que l'afficheur soit pret RSChar ; Afficheur en mode caractere movwf Char ; Sauvegarde du caractére Andlf 0x0F,DATA_PORT ; Masquage: Reset du poids fort de DP movf Char,W ; On restaure le caractére dans W andlw 0xF0 ; On isole le poids fort du registre W iorwf DATA_PORT,F; On positionne le poids fort de DATA_PORT DataOk ; On bascule le verrou du LCD swapf Char,F ; On échange les poids fort et faible Andlf 0x0F,DATA_PORT ; Masquage: Reset du poids fort de DP movf Char,W andlw 0xF0 ; On isole le poids fort du registre W iorwf DATA_PORT,F; On positionne le poids fort de DATA_PORT DataOk ; On bascule le verrou du LCD retlw 0 ; Retour avec W=0 ;--------------------------------------------------- ; Description: Transmet une commande vers l'afficheur ; Entrée: Commande dans le registre W ; Sortie: Aucune SEND_CMD call T1mS ; Attendre que l'afficheur soit prˆt RSCmd ; Afficheur en mode commande movwf Char ; Sauvegarde de la commande Andlf 0x0F,DATA_PORT ; Masquage: Reset du poids fort de DP movf Char,W ; On restaure la commande dans W andlw 0xF0 ; On isole le poids fort du registre W iorwf DATA_PORT,F; On positionne le poids fort de DATA_PORT DataOk ; On bascule le verrou du LCD swapf Char,F ; On échange les poids fort et faible Andlf 0x0F,DATA_PORT ; Masquage: Reset du poids fort de DP movf Char,W andlw 0xF0 ; On isole le poids fort du registre W iorwf DATA_PORT,F; On positionne le poids fort de DATA_PORT DataOk ; On bascule le verrou du LCD retlw 0 ; Retour avec W=0 ;--------------------------------------------------------------------------- Intserv retfie ;____________________________________main___________________________________ START Init call LCD_Init ;INIT_LCD movlw b'00001100' ; Mise en marche de l'affichage call SEND_CMD movlw b'00101000' ; Function set: 2 lignes call SEND_CMD Movlf 226,TimeOut ClearDisp Disp ' ' Disp 'F' Disp 'R' Disp 'E' Disp 'Q' Disp '3' Disp '2' Disp '-' Disp 'L' Disp 'L' Disp '-' Disp '2' Disp '0' Disp '1' Disp '2' Disp ' ' call T1S call T1S call T1S ClearDisp call T100mS Disp ' ' Disp ' ' Disp '1' Disp '6' Disp 'F' Disp '8' Disp '4' Disp ' ' Disp 'Q' Disp '=' Disp '4' Disp 'M' Disp 'H' Disp 'z' Disp ' ' Disp ' ' Disp ' ' call T1S call T1S call T1S ClearDisp call T100mS MEASURE InitMeasure Ra3_in ; Start counter call T975us nop ; Adjust sequence nop nop nop nop nop nop nop nop nop nop nop GATE TJZ16 Thousand,STOP ; End of loop ? Test msb and lsb WAIT call T975us Dec16 Thousand ; Dec loop btfss INTCON,T0IF ; Jump at OVERFLOW_TMR0 if tmr0 overflow goto NO_OVERFLOW_TMR0 OVERFLOW_TMR0 bcf INTCON,T0IF ; Clear the Overflow flag incf Result+1,f JZ INC_RESULT ; when carry goto INC_RESULT nop nop goto GATE INC_RESULT ; Increment Result when result+1 incf Result,f ; overflow goto GATE NO_OVERFLOW_TMR0 nop ; Same time for OVERFLOW nop ; and NO_OVERFLOW nop nop nop goto GATE STOP Ra3_out ; Stop counter READ call Readprescal call Bin2BCD ; Bin to BCD conversion call DispFreq ; Send result to display TEST Test BCD0 SkipNZ Test BCD1 SkipNZ Test BCD2 SkipNZ Test BCD3 SkipNZ goto TIME_CONTROL clrf TimeOut goto MEASURE ; New measure TIME_CONTROL incf TimeOut,F JZ MESS_TIME_OUT goto MEASURE MESS_TIME_OUT ClearDisp Disp ' ' Disp 'A' Disp 'R' Disp 'R' Disp 'E' Disp 'T' Disp ' ' Disp 'A' Disp 'U' Disp 'T' Disp 'O' Disp ' ' Disp ' ' call T1S call T1S call T1S call T1S call T1S bcf POWER ; Power off LOOP_STOP goto LOOP_STOP ORG 0x2100 ; "1234567890123456" ; message taille modulo 16 EE0 DT "Freq32_LL_2012 " EE1 DT "PIC16F84 Q=4Mhz ",0 finEprom EQU $ end