; ; rev PF dec 2007 ;Executing: "C:\Mplab8\MPASM Suite\MPASMWIN.exe" /q /p16F876 "nokia07.asm" /l"nokia07.lst" ;/e"nokia07.err" /x"C:\MPLAB8\MESPRO~1\nokia07.xrf" /aINHX8M;Loaded ;C:\Mplab8\Mesprojets\_Nokia\nokia07.cod.;"C:\MPLAB722\MPASM Suite\MPASMWIN.EXE" #include <../P16F876.inc> list p=PIC16F876,c=132,n=60,st=ON,mm=ON,t=ON,x=ON,r=hex __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF &_BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC ERRORLEVEL -302 ;======================================================== ; series Nokia 7110 96 x 65 2 (b/w) * ser.5 P backlight built-in Nokia 7110 ; car 5 lignes 1/2 de 16 car ; voir lcd_controller_pcd8544.pdf ;I2_cours.pdf Overview and Use of the PICmicro MSSP I2C Interface ; Hardware ;Pin 16F876 Nokia 3310 Pin ;11 PortC 0 SCE 4.7K 5 ;12 PortC 1 D/C 4.7K 4 data ou Commande ;13 PortC 2 Reset 4.7K 8 ;14 PortC 3 SCL 4.7K 2 ;15 PortC 4 SDA 4.7K 3 ; Power 1 +3V ; Gnd 6 0V ; Vc 7 capa 1uF ;- ; pin17=RC6=Tx ------vert ---------- 3 de DS275 --- RS232 --> Ecran ; pin18=RC7=Rx ------blznc/vert ---- 1 de DS275 --- RS232 <-- Clavier ;====================================================== cblock 0x21 PDel0 PDel1 PDel2 BUFFER OUTER ;delay variable mS BoucleExt BoucleInt caractere offset_caractr pointeur_msg ;mensage (max. 255 caracteres) rotulo ;indique la position PCL dans le message Progression DATAL DATAH count1 count2 count3 receive Cpt1 ACCaLO ;Variables de calcul ACCaHI ACCbLO ACCbHI ACCcLO ACCcHI ACCdLO ACCdHI temp Flags Drapeaux ; Drapeaux de 8 bits a usage multiple ;7 signe 1= RETENUE si negatif ;6 elligible =1 ;5 si=1 => affichage 00000 a 999999 sinon si =0 affichage XXX.XX ;4 si=1 => ;3 si=1 => ;2 si=1 => ;1 si=1 => affichage LCD sinon sur RS232 ;0 endc LastBank0 EQU Drapeaux IF ( LastBank0 >= 0x70 ) ERROR "Attention debordement zone RAM bank0" ENDIF CBLOCK 0x71 ;Attention 0x70 used by ICD ; 0x71 ... 0x7B used by bootloader w_temp : 1 ; Sauvegarde registre W status_temp : 1 ; sauvegarde registre STATUS FSR_temp : 1 ; sauvegarde FSR (si indirect en interrupt) PCLATH_temp : 1 time:1 bufinptr : 1 ; pointeur sur caractcre courant buffer entrée bufoutptr : 1 ; pointeur sur caractcre courant buffer sortie flags : 1 ; 8 flags divers ; b0 : parite calculee ; b1 : erreur de parite ; b2 : erreur de frame ; b3 : erreur overflow local1 : 1 ; variable locale pour interruptions ENDC LastCDA equ PCLATH_temp IF ( LastCDA > 0x7F ) ERROR "Attention debordement zone RAM Bootloader en bank0" ENDIF ;*********************** ; VARIABLES BANQUE 1 ;*********************** ; Zone de 80 bytes cblock 0xA0 ; en bank1 Cpt10 ; Bcd Mcount btmp btmp1 dixmil mille cent dix un ; variables 16 bits SommeTamb :1 Tamb_F :2 ; Tamb STamb_F :2 valx :2 val1 :2 val2 :2 val3 :2 reste :2 result :2 Nb_1 ; compteur bit pour Max186 endc ;*********************** ; VARIABLES BANQUE 2 ;*********************** ; Zone de 80 bytes CBLOCK 0x110 ; Début de la zone (0x110 à 0x16F) bufin : D'80' ; zone de stockage des données saisies addwrite ENDC ; Fin de la zone ;*********************** ; VARIABLES BANQUE 3 ;*********************** ; Zone de 80 bytes ; ---------------- CBLOCK 0x190 ; D'but de la zone (0x190 à 0x1EF) bufout : D'80' ; message à envoyer ENDC ;==== Parametrage pour RS232 ==== #define FOSC D'8000000' ; <<< frequence du quartz[Hz], max. 20 MHz #define BAUD D'9600' ; <<< vitesse du port serie [bit/sec] #define BAUD_ERROR D'4'; <<< erreur de vitesse [%] ;===== verification ============= IF ((FOSC/(D'16' * BAUD))-1) < D'256' #define DIVIDER (FOSC/(D'16' * BAUD))-1 #define HIGH_SPEED 1 ELSE #define DIVIDER (FOSC/(D'64' * BAUD))-1 #define HIGH_SPEED 0 ENDIF BAUD_REAL EQU FOSC/((D'64'-(HIGH_SPEED*D'48'))*(DIVIDER+1)) IF BAUD_REAL > BAUD IF (((BAUD_REAL - BAUD)*D'100')/BAUD) > BAUD_ERROR ERROR "mauvaise vitesse de la liaison serie" ENDIF ELSE IF (((BAUD - BAUD_REAL)*D'100')/BAUD) > BAUD_ERROR ERROR "mauvaise vitesse de la liaison serie" ENDIF ENDIF ;-- F(Quartz) ------------ IF FOSC > D'10240000' #define T1PS 8 #define T1SU 0x31 ELSE IF FOSC > D'5120000' #define T1PS 4 #define T1SU 0x21 ELSE IF FOSC > D'2560000' #define T1PS 2 #define T1SU 0x11 ELSE #define T1PS 1 #define T1SU 0x01 ENDIF ENDIF ENDIF TIMER EQU (D'65538'-(FOSC/(D'10'*4*T1PS))); valeur de reprise pour TIMER1 (0.1s int) ;========================= #define RETENUE Drapeaux,7 #define ELLIGIBLE Drapeaux,6 #define SCE PORTC,0 #define DC PORTC,1 #define RST PORTC,2 #define LEDrouge PORTB,0 #define Devermine ;-------------------- ORG 0x0000 nop ; pour ICSP nop ; pour ICSP nop ; pour ICSP goto Init ;------------------ Init bank0 clrf PORTA clrf PORTB clrf PORTC bank1 movlw b'00000110' ;06 movwf ADCON1 movlw b'00000000' movwf TRISB movlw b'00000000' movwf TRISA movlw b'00011000'; SCL SDA en entrees movwf TRISC clrf val1 clrf val1+1 bank0 bsf SCE ;/SCE a 1 bsf DC ;D/C a 1 bsf RST ;/RESET a 1 bcf LEDrouge call delay_1s movlw 0x90 ; SPEN = 1, CREN = 1 movwf RCSTA ;configures RC7/RX/DT and RC6/TX/CK pins as serial port bank1 IF HIGH_SPEED == 1 ; USART SYNC=0; SPEN=1; CREN=1; SREN=0; bsf TXSTA,BRGH ; TX9=0; RX9=0; TXEN=1; ELSE bcf TXSTA,BRGH ENDIF bsf TXSTA,TXEN movlw DIVIDER ; generateur de baud rate movwf SPBRG bank0 bcf Drapeaux,1 ; sortie sur RS232 call delay_1s CALL Rs_CrLf ; purge RS232 movlw 0 call Msg_Eeprom call delay_1s movlw EE1-EE0 call Msg_Eeprom call delay_1s Bsf Drapeaux,1 ; sortie sur LCD call INIT_LCD call CLR_LCD bcf LEDrouge call delay_1s call CLR_LCD call normal_video movlw 0 call Affiche_Msg CALL Rs_CrLf movlw .32 ;clignote xorwf PORTA,f ;LEDrouge bsf LEDrouge call delay_1s call delay_1s call CLR_LCD call Invert_video movlw EE1-EE0 call Affiche_Msg CALL Rs_CrLf bcf LEDrouge call delay_1s call delay_1s call normal_video Bsf Drapeaux,1 ; sortie sur LCD bsf LEDrouge Bsf Drapeaux,1 ; sortie sur LCD call CLR_LCD call normal_video movlw EE2-EE0 call Affiche_Msg call delay_1s Suite Bsf Drapeaux,1 ; sortie sur LCD ; en points ................ movlw .3 ;Y address in Lines iorlw b'01000000' ;bit de commande call TX_SPI_C movlw .6 ;X address in pixel iorlw b'10000000' ;bit de commande call TX_SPI_C bank1 incf val1+1,f BTFSC STATUS,Z ; si debordement MSB incf val1,f bank0 bcf Drapeaux,5 ; mode XXXXX bcf RETENUE call bcd_temp ; remplit le buffer d'affichage ASCII ; en degres ............ movlw .2 ;Y address in Lines iorlw b'01000000' ;bit de commande call TX_SPI_C movlw .12 ;X address in pixel iorlw b'10000000' ;bit de commande call TX_SPI_C bank1 incf val1+1,f BTFSC STATUS,Z ; si debordement MSB incf val1,f bank0 bsf Drapeaux,5 ; mode XXXXX bcf RETENUE call bcd_temp ; remplit le buffer d'affichage ASCII bcf LEDrouge Bcf Drapeaux,1 ; sortie sur RS232 bcf RETENUE call bcd_temp CALL Rs_CrLf call delay_1s goto Suite ;boucle infinie Affiche_Msg bank0 movwf Cpt1 Aff_Msg1 movf Cpt1,w call Read_EE movwf caractere incf Cpt1,f ANDLW 0x0FF BTFSC STATUS, Z Return movf caractere ,w call Output_Char goto Aff_Msg1 return Output_Char bank0 movwf caractere btfsc Drapeaux,1 call Affiche_Char btfss Drapeaux,1 call Rs_Putchar return ;------ print char 6x8 pixels ---- Affiche_Char clrf offset_caractr call Search_In_ascii_Table ; col 1 du caractere call TX_SPI_D ; incf offset_caractr,F call Search_In_ascii_Table ;col 2 du caractere call TX_SPI_D incf offset_caractr,F call Search_In_ascii_Table ;col 3 du caractere call TX_SPI_D incf offset_caractr,F call Search_In_ascii_Table ;col 4 du caractere call TX_SPI_D incf offset_caractr,F call Search_In_ascii_Table ;col 5 du caractere call TX_SPI_D incf offset_caractr,F call Search_In_ascii_Table ;col 6 du caractere call TX_SPI_D incf offset_caractr,F return ;Routines de control du LCD NOKIA 3310 en mode SPI ; INIT_LCD call CFG_SPI ;configuration mode SPI movlw d'30' call delay call RST_LCD ;reset LCD movlw d'10' call delay call SET_LCD ;initialisation LCD movlw d'10' call delay call CLR_LCD ;Raz ecran movlw d'10' call delay return ;Configuration du port serie SPI CFG_SPI ;voir AN735 ;set I2C rate =((FOSC/Bitrate)/4)-1; ;8000000/1000000=80 80/4=20 20-1=19 movlw .19 ; setup value banksel SSPADD ; select SFR bank movwf SSPADD ; baud rate = 100KHz @ 8MHz movlw b'00000000' movwf SSPSTAT bank0 ; Registre de configuration SSPCON ; SSPEN <5> Enable=1 ; SSPM3:SSPM0 Hardware master mode=1000 ; I2C master mode, clock = FOSC / (4 * (SSPADD+1) ) movlw b'00101000' movwf SSPCON return ; Generation d'un Reset pour initialiser le LCD3310 RST_LCD bcf RST ; reset au niveau bas call delay_1ms ;retard bsf RST ; reset niveau haut return ;=============== ;Inicialisation du LCD SET_LCD ;Function SET: 00100_PD_V_H ; PD=0=>chip active ; V =0 =>Addressage Horizontal ; H =1 => extended instructions set movlw b'00100001' call TX_SPI_C ;Set VOP : 1_VOP6..VO0 ;VLCD = a + (VOP6 to VOP0)* b [V]. ; a = 3.06 and b = 0.06 soit 3,00 à 10,68V à T°Amb ; movlw b'11001011' ;3.06+75*0.06=8.1 movlw b'10010000' ;3.06+162*0.06=4.02 call TX_SPI_C ; compensation temperature TC0 TC1 movlw b'00000101' ; TC0=1 TC1=0 call TX_SPI_C ;bias System : 000010_BS2_BS1_BS0 movlw b'00010011' ;bias System 1:48 -> n=4 call TX_SPI_C ;Function SET: 00100_PD_V_H ; PD=0=>chip active ; V =0 =>Addressage Horizontal ; H =0 => normal instructions set movlw b'00100000' ;chip activo, H=0 call TX_SPI_C ; ???? ; movlw b'00001001' ;mode [Pantalla negra] ; call TX_SPI_C ;Display mode control set : 00001_D_0_E ; D=1 ; E=0 call delay_1ms movlw b'00001100' ;mode [Normal mode] call TX_SPI_C return ;================================= ;RAZ memoire RAM LCD CLR_LCD movlw b'00001000' ; mode Display Blank call TX_SPI_C ; envoi Commande movlw d'2' ;8 movwf BoucleExt Bint movlw d'252' ;96 =768 movwf BoucleInt Bint1 movlw b'00000000' call TX_SPI_D ;envoi Data decfsz BoucleInt,f ;soit 252 cycles goto Bint1 decfsz BoucleExt,f ; 2 x 252 = 504 cycles goto Bint movlw .0 ;Y address call Y_address movlw .0 ;X address call X_address return ;position X contenue dans W X_address iorlw b'10000000' ;bit de commande call TX_SPI_C return ;position Y contenue dans W Y_address iorlw b'01000000' ;bit de commande call TX_SPI_C return ;video inverse Invert_video movlw b'00001101' ;mode [Inverse video mode] call TX_SPI_C return ;video normal normal_video movlw b'00001100' ;mode [normal mode] call TX_SPI_C return ;Transmision de Cde TX_SPI_C bcf DC ;Mode COMMANDE nop ;Transmision de donnees TX_SPI_D bcf SCE ;enable display! movwf SSPBUF ;Transmission sur port SPI espera btfss PIR1,SSPIF ; goto espera bcf PIR1,SSPIF nop bsf SCE ;display OFF nop nop bsf DC ;Mode DATA (par defaut) nop return ;=================== Rs_CrLf bank0 movlw .13 call Rs_Putchar movlw .10 call Rs_Putchar return ;--------------- Rs_Putchar bank0 clrwdt Rs_P1 btfss PIR1,TXIF ; while(!TXIF) goto Rs_P1 movwf TXREG ; TXREG = octet return ;--------------- Msg_Eeprom bank0 movwf Cpt1 Msg_eep1 movf Cpt1,w call Read_EE movwf caractere incf Cpt1,f ANDLW 0x0FF BTFSC STATUS, Z Return movf caractere,w btfss Drapeaux,1 call Rs_Putchar btfsc Drapeaux,1 call Affiche_Char goto Msg_eep1 return ;------- ; subroutine to read EEPROM memory ;(adresse & r‚sultat en w) Read_EE ; 16F876 bank2 MOVWF EEADR ;Data Memory Address to read bank3 BCF EECON1, EEPGD ;Point to DATA memory BSF EECON1, RD ;EEPROM Read bank2 MOVF EEDATA, W ;W = EEDATA bank0 return ;------------ Rs_Getchar clrwdt movf time,w btfsc STATUS,Z ; regarder si time==0 goto getchar3 btfss PIR1,TMR1IF ; regarder si le TIMER1 a débordé goto getchar3 ; pas de debordement bcf T1CON,TMR1ON ; timeout 0.1 sec decfsz time,f ; time-- goto getchar2 retlw 0 ; if time==0 then return getchar2 bcf PIR1,TMR1IF movlw high TIMER movwf TMR1H ; preset TIMER1 for 0.1s timeout bsf T1CON,TMR1ON getchar3 btfss PIR1,RCIF ; while(!RCIF) goto Rs_Getchar movf RCREG,w ; RCREG return ;==================================== ; rev pour horloge 8MHZ cycle=250nS ; count1 ;delay routines ; count2 ;delay routines ; count3 ;delay routines ;delay delay_RS ;delay1 ; 5(count3-1)+1282(count2-1)+327684(count1-1)+6 ;delay_25us delay_100us delay_200us ;delay_1ms delay_10ms delay_100ms delay_500ms ;delay_1sec delay_10sec delay_25us movlw 0x01 movwf count1 movlw 0x01 movwf count2 movlw .10 movwf count3 goto delay1 delay_1ms movlw 0x01 movwf count1 movlw .4 movwf count2 movlw .231 movwf count3 goto delay1 delay_100ms movlw .2 movwf count1 movlw .135 movwf count2 movlw .105 movwf count3 goto delay1 delay_1s movlw .16 movwf count1 movlw .67 movwf count2 movlw .25 movwf count3 goto delay1 delay1 decfsz count3,f ;2 + 5*(count3-1) + goto $-1 ;2 + (5*255 +2+5) * (count2-1) + decfsz count2,f ;2 + (5*255*256 +2 + 5*255 +2+5) *(count1-1) goto $-3 ; = decfsz count1,f ;5(count3-1)+1282(count2-1)+327684(count1-1)+6 goto $-5 ; return ; delay movwf OUTER out_loop call delay_1ms decfsz OUTER,F goto out_loop return ;========================================= ; conv mot 16bits --> en XX.XXøC 25.42øC bcd_temp bank1 movf val1,W movwf valx movf val1+1,W movwf valx+1 swapf valx,W iorlw 0xf0 movwf mille addwf mille,F addlw 0xE2 ; 226 movwf cent addlw 0x32 ;50 movwf un movf valx,W andlw 0x0F addwf cent,F addwf cent,F addwf un,F addlw 0xE9 ;233 movwf dix addwf dix,F addwf dix,F swapf valx+1,W ;<- modif 20mars03 was val1 andlw 0x0F addwf dix,F addwf un,F rlf dix,F rlf un,F comf un,F rlf un,F movf valx+1,W andlw 0x0F addwf un,F rlf mille,F movlw 0x07 movwf dixmil movlw 0x0A Lb1: addwf un,F decf dix,F btfss STATUS,C goto Lb1 Lb2: addwf dix,F decf cent,F btfss STATUS,C goto Lb2 Lb3: addwf cent,F decf mille,F btfss STATUS,C goto Lb3 Lb4: addwf mille,F decf dixmil,F btfss STATUS,C goto Lb4 bank0 btfss Drapeaux,5 ; 1 => affichage 00000 … 999999 goto Bcd5ascii ; 0 => affichage + ou - XXX.XX movlw ' ' btfsc RETENUE movlw '-' call Output_Char bank1 movf mille,w btfss STATUS,Z ; si digit=0 remplace par Blanc goto Lb5 bank0 movlw ' ' call Output_Char goto Lb6 Lb5 bank0 addlw '0' call Output_Char Lb6 bank1 movf cent,w addlw '0' call Output_Char movlw '.' call Output_Char bank1 movf dix,w addlw '0' call Output_Char bank1 movf un,w addlw '0' call Output_Char return ;--------------- Bcd5ascii bank1 ; movf dixmil,w ; addlw '0' ; call Output_Char ; bank1 movf mille,w addlw '0' call Output_Char Bcd3ascii bank1 movf cent,w addlw '0' call Output_Char bank1 movf dix,w addlw '0' call Output_Char bank1 movf un,w addlw '0' call Output_Char movlw ' ' call Output_Char return ;======================= org 0x3FF ;position de la table en memoire Flash de programe ;RECHERCHE DANS TABLE DE CARACTERES ASCII Search_In_ascii_Table movf caractere,W movwf ACCaLO ;valeur ascii comme premier operande de la multiplication movlw .0 ; A Raz Resultat HI movwf ACCaHI movwf ACCbHI ;B Raz resultat HI movlw .6 movwf ACCbLO ;second operande de la multiplication call D_mpyS ; multiplication valeur ascii par 6 ;------------------------------------ movlw .4 ;position de la table ascii en page 4 movwf PCLATH ; initailise compteur de page movlw init_table ; Charge la position relative de la table movwf Progression movf ACCcHI,W ; resultat HI multipilcation -> W addwf PCLATH,F ; charge PAGE movf ACCcLO,W ; Resulta LO de la multiplication addwf offset_caractr,W; rajoute position de la colonne dan sle caractere btfsc STATUS,C ; test si depassement incf PCLATH,F ;si oui incremente PCLATH addwf Progression,F btfsc STATUS,C ;test si depassement incf PCLATH,F ;si oui incremente PCLATH ;matrice 6x8 pour caractere 5x7 , continet donc l'inter espace caractere ; 96 pixels -> 16 car de 6 pixels de large init_table addwf PCL,F ; #include <../police_6x7.txt> ;*******************************************************************; ; Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCb,ACCc ( 32 bits ) ; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ) ; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ) ; (c) CALL D_mpy ; (d) The 32 bit result is in location ( ACCbHI,ACCbLO,ACCcHI,ACCcLO ) ;*******************************************************************; ; ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word ; in ACCb ( ACCbHI,ACCbLO ) and low word in ACCc ( ACCcHI,ACCcLO ). D_mpyS ;results in ACCb(16 msb's) and ACCc(16 lsb's) call setupmult bcf STATUS,C mloop rrf ACCdHI,F ;rotate d right rrf ACCdLO,F btfss STATUS,C ;need to add? goto No_add movf ACCaLO,W ; Addition ( ACCb + ACCa -> ACCb ) addwf ACCbLO,F ;add lsb btfsc STATUS,C ;add in carry incf ACCbHI,F movf ACCaHI,W addwf ACCbHI,F ;add msb No_add rrf ACCbHI,F rrf ACCbLO,F rrf ACCcHI,F rrf ACCcLO,F decfsz temp,F ;loop until all bits checked goto mloop goto end1 ; Double Precision Addition ( ACCb + ACCa -> ACCb ) ; D_add bcf Flags,C ;Clear temp Carry bit movf ACCaLO,W ; Addition ( ACCb + ACCa -> ACCb ) addwf ACCbLO,F ;add lsb btfsc STATUS,C ;add in carry incf ACCbHI,F btfsc STATUS,C bsf Flags,C movf ACCaHI,W addwf ACCbHI,F ;add msb btfsc Flags,C bsf STATUS,C return ; setupmult movlw .16 ; for 16 shifts movwf temp movf ACCbHI,W ;move ACCb to ACCd movwf ACCdHI movf ACCbLO,W movwf ACCdLO clrf ACCbHI clrf ACCbLO return end1 return ORG 0x2100 ; 256 bytes of eeprom EEPROM EQU $ ;1234567890123456" EE0 DT "16F876 bootldr " DT "Q=8Mhz 9600bds" DT "Nokia11_ok_0712 " DT " 2007/12/26 " DT "Paulfjujofreefr ",0 EE1 DT "1234567890123456" DT " Ligne 2........" DT " Ligne 3......." DT " Ligne 4......" DT " Ligne 5.....",0 EE2 DT "25/10 10H23M32S" DT "Mesure de temper" DT " + 00.00 Degres " DT " 1023 points " DT "................",0 END