ci joint le programme a mettre dans le pic emeteur qui envoie une chaine de caractères toute les 3 secondes avec un caractère qui change a chaque fois
ci cela peut servir
Code : Tout sélectionner
;*****************************************************************************
; *
; NOM: emmission tx *
; Date: 26/02/2017 *
; Version: 1.1 *
; Circuit: Platine d'expérimentation *
; Auteur: pris des morceaux de partout et modifié par JM *
; *
;*****************************************************************************
; *
; Fichier requis: P16F877.inc *
; *
;*****************************************************************************
; *
; La liaison s'effectue au travers d'un MAX232 *
; 1 start-bit, 8 bits de donnée, 0 bit de parité paire, 1 stop-bit *
; Liaison en 9600 bauds (9615 bauds réels) *
; Utilisation du module USART *
; Le PIC travaille à 4 MHz *
;*****************************************************************************
LIST p=16F877 ; Définition de processeur
#include <p16F877.inc> ; fichier include
radix dec ; on travaille en décimal par défaut
__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC
;_CP_OFF Pas de protection
;_DEBUG_OFF RB6 et RB7 en utilisation normale
;_WRT_ENABLE_OFF Le programme ne peut pas écrire dans la flash
;_CPD_OFF Mémoire EEprom déprotégée
;_LVP_OFF RB3 en utilisation normale
; _BODEN_OFF Reset tension hors service
;_PWRTE_ON Démarrage temporisé
;_WDT_OFF Watchdog hors service
;_HS_OSC Oscillateur haute vitesse (4Mhz<F<20Mhz)
;*****************************************************************************
; ASSIGNATIONS SYSTEME *
;*****************************************************************************
; REGISTRE OPTION_REG (configuration)
; -----------------------------------
OPTIONVAL EQU B'10001111'
; RBPU b7 : 1= Résistance rappel +5V hors service
; PSA b3 : 1= Assignation prédiviseur sur Watchdog
; PS2/PS0 b2/b0 valeur du prédiviseur = 128
;*****************************************************************************
; ASSIGNATIONS PROGRAMME *
;*****************************************************************************
; (4000000/(9600*16))-1
; (4000000/153600)-1 = 25,0416 nous prendrons 25
BRGVAL EQU D'25' ; pour un débit de 9615 bauds en mode high-speed
;**********************************************************************
;
;***** Variable de temporisation
tempo50µ EQU 0x20 ; Variable tempo 50 µs
tempo10ms EQU 0x21 ; Variable tempo 10 ms
tempo1s EQU 0x22 ; Variable tempo 1s
;*****************************************************************************
; MACRO *
;*****************************************************************************
;*********************** MACROS ************************************************
Banque0 MACRO
BCF STATUS,RP0 ;Acces bank0
BCF STATUS,RP1
ENDM
Banque1 MACRO
BSF STATUS,RP0 ;Acces bank1
BCF STATUS,RP1
ENDM
Banque2 MACRO
BCF STATUS,RP0 ;acces bank2
BSF STATUS,RP1
ENDM
Banque3 MACRO
BSF STATUS,RP0 ;Acces bank4
BSF STATUS,RP1
ENDM
;*****************************************************************************
MESS macro a1,a2,a3,a4 ; inscrit le message dans bufout
BANKSEL bufout ; passer en banque 3
movlw "[" ; mettre crochet
movwf bufout ; dans bufout
movlw a1 ; charger argument 1
movwf bufout+1 ; dans bufout
movlw a2 ; charger argument 2
movwf bufout+2 ; dans bufout
movlw a3 ; charger argument 3
movwf bufout+3 ; dans bufout
movlw a4 ; charger argument 4
movwf bufout+4 ; dans bufout
movlw "]" ; mettre crochet
movwf bufout+5 ; dans bufout
movlw 0x0D ; charger carriage return
movwf bufout+6 ; dans bufout
movlw 0x0A ; charger line-feed
movwf bufout+7 ; dans bufout
BANKSEL 0 ; repasser banque 0
endm
;*****************************************************************************
; VARIABLES BANQUE 0 *
;*****************************************************************************
; Zone de 80 bytes
; ----------------
CBLOCK 0x20 ; Début de la zone (0x20 à 0x6F)
;***** Variable de temporisation
tempo50µ :1 ; Variable tempo 50 µs
tempo10ms :1 ; Variable tempo 10 ms
tempo1s :1 ; Variable tempo 1s
ptr1 : 1 ; pointeur temporaire 1
ptr2 : 1 ; pointeur temporaire 2
octemp : 1 ; sauvegarde temporaire
ENDC ; Fin de la zone
;*****************************************************************************
; VARIABLES ZONE COMMUNE *
;*****************************************************************************
; Zone de 16 bytes
; ----------------
CBLOCK 0x70 ; Début de la zone (0x70 à 0x7F)
w_temp : 1 ; Sauvegarde registre W
status_temp : 1 ; sauvegarde registre STATUS
FSR_temp : 1 ; sauvegarde FSR (si indirect en interrupt)
PCLATH_temp : 1 ; sauvegarde PCLATH (si prog>2K)
bufinptr : 1 ; pointeur sur caractère courant buffer entrée
bufoutptr : 1 ; pointeur sur caractère courant buffer sortie
flags : 1 ; flags divers
; b0 : parité calculée
; b1 : erreur de parité
; b2 : erreur de frame
; b3 : erreur overflow
local1 : 1 ; variable locale pour interruptions
ComptSu : 1
ENDC
#DEFINE PARITE flags,0 ; parité calculée
#DEFINE ER_PAR flags,1 ; erreur de parité
#DEFINE ER_FR flags,2 ; erreur de frame
#DEFINE ER_OV flags,3 ; erreur d'overflow
;*****************************************************************************
; VARIABLES BANQUE 2 *
;*****************************************************************************
; Zone de 96 bytes
; ----------------
CBLOCK 0x110 ; Début de la zone (0x110 à 0x16F)
bufin : D'96' ; zone de stockage des données entrées
ENDC ; Fin de la zone
;*****************************************************************************
; VARIABLES BANQUE 3 *
;*****************************************************************************
; Zone de 96 bytes
; ----------------
CBLOCK 0x190 ; Début de la zone (0x190 à 0x1EF)
bufout : D'96' ; message à envoyer
ENDC ; Fin de la zone
;*****************************************************************************
; DEMARRAGE SUR RESET *
;*****************************************************************************
org 0x000 ; Adresse de départ après reset
goto init ; Initialiser
; ////////////////////////////////////////////////////////////////////////////
; I N T E R R U P T I O N S
; ////////////////////////////////////////////////////////////////////////////
;*****************************************************************************
; ROUTINE INTERRUPTION *
;*****************************************************************************
;-----------------------------------------------------------------------------
; La suppression des lignes "goto restorereg" permet dans ce cas de traiter
; l'interruption sur réception et sur émission en une seule fois
;-----------------------------------------------------------------------------
;sauvegarder registres
;---------------------
org 0x004 ; adresse d'interruption
movwf w_temp ; sauver registre W
swapf STATUS,w ; swap status avec résultat dans w
movwf status_temp ; sauver status swappé
movf FSR , w ; charger FSR
movwf FSR_temp ; sauvegarder FSR
; switch vers différentes interrupts
;-----------------------------------
; Interruption réception USART
; ----------------------------
BANKSEL PIE1 ; sélectionner banque 1
btfss PIE1,RCIE ; tester si interrupt autorisée
goto intsw1 ; non sauter
bcf STATUS,RP0 ; oui, sélectionner banque0
btfss PIR1,RCIF ; oui, tester si interrupt en cours
goto intsw1 ; non sauter
call intrc ; oui, traiter interrupt
; Interruption transmission USART
; -------------------------------
intsw1
bsf STATUS,RP0 ; sélectionner banque1
btfss PIE1,TXIE ; tester si interrupt autorisée
goto restorereg ; non sauter
bcf STATUS,RP0 ; oui, sélectionner banque0
btfss PIR1,TXIF ; oui, tester si interrupt en cours
goto restorereg ; non sauter
call inttx ; oui, traiter interrupt
;restaurer registres
;-------------------
restorereg
movf FSR_temp , w ; charger FSR sauvé
movwf FSR ; restaurer FSR
swapf status_temp,w ; swap ancien status, résultat dans w
movwf STATUS ; restaurer status
swapf w_temp,f ; Inversion L et H de l'ancien W
; sans modifier Z
swapf w_temp,w ; Réinversion de L et H dans W
; W restauré sans modifier status
retfie ; return from interrupt
;*****************************************************************************
; INTERRUPTION RECEPTION USART *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Reçoit le caractère de l'USART et le place dans le buffer d'entrée.
; Si la longueur atteint D'94', on n'encode plus, et on place 0x0D en avant-
; dernière position et 0x0A en dernière position
; Si la réception est terminée (longueur atteinte ou 0x0A reçu), on stoppe les
; interruptions de réception et on repositionne le pointeur au début du buffer
; Les erreurs sont détectées et signalées
;-----------------------------------------------------------------------------
intrc
; tester si erreur de frame
; -------------------------
btfsc RCSTA,FERR ; tester si erreur de frame
bsf ER_FR ; oui, signaler erreur de frame
; lire la parité
; --------------
; bcf PARITE ; par défaut, parité = 0
; btfsc RCSTA,RX9D ; parité lue = 1?
; bsf PARITE ; oui, le signaler
; lire octet reçu
; ---------------
bsf STATUS,IRP ; pointer banques 2 et 3 en indirect
movf bufinptr,w ; charger pointeur destination
movwf FSR ; dans pointeur d'adresse
movf RCREG,w ; charger octet reçu
movwf INDF ; sauver dans buffer
; vérifier la parité
; ------------------
intrc1
; movf INDF,w ; charger caractère reçu
; call calcpar ; calculer la parité
; movf RCSTA,w ; charger registre commande
; xorwf flags,w ; comparer parité reçue et calculée
; andlw 0x01 ; ne garder que le résultat
; btfss STATUS,Z ; b0 = b1? (parité calculée = parité reçue?)
; bsf ER_PAR ; non, signaler erreur de parité
; tester si erreur d'overflow
; ---------------------------
btfsc PIR1,RCIF ; encore d'autres octets dans RCREG?
goto intrc2 ; oui, vérifier caractère
btfss RCSTA,OERR ; non, erreur d'overflow?
goto intrc2 ; non, vérifier caractère
bcf RCSTA,CREN ; oui, arrêt de la réception (reset de OERR)
bsf RCSTA,CREN ; remise en service de la réception
bsf ER_OV ; signaler erreur overflow
goto intrcend ; et fin d'interruption
; tester si caractère reçu = 0x0A
; -------------------------------
intrc2
movf INDF,w ; charger caractère reçu
xorlw 0x0A ; comparer avec line-feed
btfsc STATUS,Z ; identique?
goto intrcend ; oui, fin de message
; vérifier si buffer plein
; ------------------------
incf bufinptr,f ; incrémenter pointeur de caractères
movf FSR,w ; charger pointeur
xorlw 0x6D ; comparer avec dernièr emplacement possible
btfss STATUS,Z ; identique?
return ; non, fin de réception
incf FSR,f ; pointeur sur emplacement suivant
movlw 0x0D ; mettre carriage-return
movwf INDF ; en avant-dernière position
incf FSR,f ; pointer sur dernière position
movlw 0x0A ; charger line-feed
movwf INDF ; en dernière position
; fin de message
; --------------
intrcend
movlw LOW bufin ; oui, adresse de départ du buffer d'entrée
movwf bufinptr ; prochain caractère sera le premier
bsf STATUS,RP0 ; passer banque 1
bcf PIE1,RCIE ; fin des interruptions de réception
bcf STATUS,RP0 ; repasser banque 0
return ; et retour
;*****************************************************************************
; INTERRUPTION EMISSION USART *
;*****************************************************************************
;-----------------------------------------------------------------------------
; envoie le caractère pointé par bufoutptr, puis incrémente le pointeur
; Si ce caractère est le "line-feed", alors on arrête l'émission et on pointe de
; nouveau au début du buffer
;-----------------------------------------------------------------------------
inttx
; prendre octet à envoyer
; -----------------------
bsf STATUS,IRP ; pointer banques 3 et 4
movf bufoutptr,w ; charger pointeur d'octets
movwf FSR ; dans pointeur
movf INDF,w ; charger octet à envoyer
; calculer parité
; ---------------
; call calcpar ; calculer parité
; bsf STATUS,RP0 ; passer banque1
; bcf TXSTA,TX9D ; par défaut, parité = 0
; btfsc PARITE ; parité = 1?
; bsf TXSTA,TX9D ; oui, positionner parité
; envoyer octet
; -------------
movf INDF,w ; charger octet à envoyer
bcf STATUS,RP0 ; passer banque 0
movwf TXREG ; envoyer octet + parité
incf bufoutptr,f ; pointer sur octet suivant
; tester si dernier octet
; -----------------------
xorlw 0x0A ; comparer octet envoyé avec Line-feed
btfss STATUS,Z ; égalité?
return ; non, retour d'interruption
; traiter fin d'émission
; ----------------------
bsf STATUS,RP0 ; passer en banque 1
bcf PIE1,TXIE ; fin des interruptions émission USART
bcf STATUS,RP0 ; repasser banque 0
movlw LOW bufout ; adresse du buffer de sortie
movwf bufoutptr ; prochain caractère = premier
return ; fin d'interruption
; ////////////////////////////////////////////////////////////////////////////
; P R O G R A M M E
; ////////////////////////////////////////////////////////////////////////////
;*****************************************************************************
; INITIALISATIONS *
;*****************************************************************************
init
; Registre d'options (banque 1)
; -----------------------------
BANKSEL OPTION_REG ; sélectionner banque 1
movlw OPTIONVAL ; charger masque
movwf OPTION_REG ; initialiser registre option
; registres interruptions (banque 1)
; ----------------------------------
bsf INTCON,PEIE ; autoriser interruptions périphériques
; initialiser USART
; -----------------
movlw B'00000100' ; émission sur 8 bits, mode haute vitesse
movwf TXSTA ; dans registre de contrôle
movlw BRGVAL ; valeur pour baud rate generator
movwf SPBRG ; dans SPBRG
bcf STATUS,RP0 ; passer banque 0
movlw B'10000000' ; module USART en service, réception 8 bits
movwf RCSTA ; dans registre de contrôle
; Initialiser message de bienvenue
; --------------------------------
MESS "P","R","E","T" ; inscrire PRET dans le buffer de sortie
; initialiser variables
; ---------------------
clrf flags ; effacer flags
movlw LOW bufin ; adresse du buffer de réception
movwf bufinptr ; dans pointeur
movlw LOW bufout ; adresse basse du buffer d'émission
movwf bufoutptr ; dans pointeur
; autoriser interruptions (banque 0)
; ----------------------------------
bsf INTCON,GIE ; valider interruptions
goto start ; programme principal
;*****************************************************************************
; PREPARER LA REPONSE *
;*****************************************************************************
;-----------------------------------------------------------------------------
; copie le buffer d'entrée inversé dans le buffer de sortie
; en modifiant cette sous-routine, vous pouvez changer le fonctionnement
; de votre programme. Vous pouvez inventer ici de nouvelles règles de
; réponse
;-----------------------------------------------------------------------------
preprep
; rechercher la fin du message
; ----------------------------
movlw LOW bufin-1 ; pointer sur début du message-1
movwf FSR ; dans pointeur
bsf STATUS,IRP ; pointer banques 3 et 4 en indirect
prep1
incf FSR,f ; pointer sur suivant
movf INDF,w ; charger caractère
xorlw 0x0A ; comparer avec line-feed
btfss STATUS,Z ; tester si car = 0x0A
goto prep1 ; non, suivant
decf FSR,w ; oui, prendre pointeur trouvé-1
movwf ptr1 ; sauver dans pointeur temporaire1
; traiter ligne vide
; ------------------
xorlw 0x10 ; tester position pointeur
btfss STATUS,Z ; ligne vide?
goto prep3 ; non, sauter
MESS "V","I","D","E" ; inscrire "vide dans le buffer de sortie
return ; fin du traitement
; copier message inversé
; ----------------------
prep3
;*********************************************************************************
;*****************************************************************************
; PROGRAMME PRINCIPAL *
;*****************************************************************************
start
; lancer l'émission, message de bienvenue
; ---------------------------------------
bsf STATUS,RP0 ; passer en banque 1
bcf STATUS,RP1
bsf TXSTA,TXEN ; émission en service.
bsf PIE1,TXIE ; envoyer message "pret"
; attendre fin de l'émission
; --------------------------
clrwdt ; effacer watch dog
btfsc PIE1,TXIE ; reste des caractères à envoyer?
goto $-2 ; oui, attendre
btfss TXSTA,TRMT ; buffer de sortie vide?
goto $-4 ; non, attendre
; revevoir le message
; -------------------
bsf STATUS,RP0 ; passer banque 1
loop
; Attendre fin émission précédente
; --------------------------------
clrwdt ; effacer watchdog
btfsc PIE1,TXIE ; message précédent envoyé?
goto $-2 ; non, attendre
btfss TXSTA,TRMT ; buffer de sortie vide?
goto $-4 ; non, attendre
; traiter erreurs
; ----------------
movf flags,w ; charger flags
andlw B'00001110' ; conserver flags d'erreur
btfsc STATUS,Z ; tester si au moins une erreur
goto messprep ; non, traitement normal
btfss ER_PAR ; tester si erreur de parité
goto err2 ; non, sauter
MESS "P","A","R"," " ; écrire "PAR" dans le buffer de sortie
bcf ER_PAR ; acquitter l'erreur
err2
btfss ER_FR ; tester si erreur de frame
goto err3 ; non, sauter
MESS "F","E","R","R" ; écrire "FERR" dans le buffer de sortie
bcf ER_FR ; acquitter l'erreur
err3
btfss ER_OV ; tester si erreur d'overflow
goto msuite ; envoyer le message
MESS "O","E","R","R" ; écrire "OERR" dans le buffer de sortie
bcf ER_OV ; acquitter l'erreur
goto msuite ; envoyer message d'erreur
; traitement normal du message
; ----------------------------
messprep
bcf STATUS,RP0 ; passer banque 0
msuite
; envoyer réponse
; ---------------
MESS "J","M","P","1"
BANKSEL ComptSu
decf ComptSu,f
movfw ComptSu
BANKSEL bufout
movwf bufout+4
BANKSEL 0
; pause de 1 s
CALL Wait1s
bsf STATUS,RP0 ; passer banque 1
bsf PIE1,TXIE ; lancer le message
goto loop ; traiter message suivant
;**********************************************************************
; *
; Les pauses a 20Mhz *
; *
; *
;**********************************************************************
;***** Attente de 1 s (exactement 1.00204 s)
Wait1s
MOVLW D'99' ; 99 fois
MOVWF tempo1s ; stockage dans la variable tempo1s
T1sboucle CALL Wait10ms
DECFSZ tempo1s,1 ; décremente et test
GOTO T1sboucle ; on boucle tant que <>0
RETURN
;***** Attente de 15 ms (exactement 14.99 ms)
Wait15ms
MOVLW D'149' ; 149 fois
MOVWF tempo10ms ; stockage dans la variable tempo10ms
T15msboucle CALL Wait100µs
DECFSZ tempo10ms,1 ; décremente et test
GOTO T15msboucle ; on boucle tant que <>0
RETURN
;***** Attente de 10 ms (exactement 10.02 ms)
Wait10ms
MOVLW D'198' ; 198 fois
MOVWF tempo10ms ; stockage dans la variable tempo10ms
T10msboucle CALL Wait50µs
DECFSZ tempo10ms,1 ; décremente et test
GOTO T10msboucle ; on boucle tant que <>0
RETURN
;***** Attente de 1.5 ms (exactement ? ms)
Wait1.5ms
MOVLW D'29' ; 29 fois
MOVWF tempo10ms ; stockage dans la variable tempo10ms
T1.5msboucle CALL Wait50µs
DECFSZ tempo10ms,1 ; décremente et test
GOTO T1.5msboucle ; on boucle tant que <>0
RETURN
;***** Attente de 100 µs (exactement, en comptant le temps d'appel)
Wait100µs
MOVLW D'165' ; 165 fois
MOVWF tempo50µ ; stockage dans la variable tempo50µ
T100µsboucle DECFSZ tempo50µ,1 ; décremente et test
GOTO T100µsboucle ; on boucle tant que <>0 0.2*3=0.6 µs en tout
RETURN
;***** Attente de 50 µs (exactement, en comptant le temps d'appel)
Wait50µs NOP
NOP
MOVLW D'81' ; 81 fois
MOVWF tempo50µ ; stockage dans la variable tempo50µ
T50µsboucle DECFSZ tempo50µ,1 ; décremente et test
GOTO T50µsboucle ; on boucle tant que <>0 0.2*3=0.6 µs en tout
RETURN
;***** Attente de 1 µs (exactement, en comptant le temps d'appel)
Wait1µs NOP
RETURN
END ; directive fin de programme


Et en plus il fonctionne, et ne son pas HS !!
