Sie sind auf Seite 1von 16

INSA GE IF2

1/16 ToG 2007


TD Microcontrleur, famille PIC
Seance 7
Correction Correction Correction Correction Correction Correction Correction

Exercices de programmation en assembleur
Il est conseille de savoir Iaire ces exercices.
Conseils :
- commencer par Iaire un organigramme.
- ensuite. traduire rigoureusement et etape par etape votre organigramme
- ne pas hesiter a aiouter des variables temporaires (en RAM) necessaires au codage
assembleur.
- ne chercher pas trop a optimiser votre code et l`utilisation de la memoire.
- utiliser des noms de variables clairs (valeurs. Ionction ou de boucle).
- encore une Iois : utiliser des variables (temporaires. parametres. .) en RAM.

I Table de retour de fonction
a- Raliser la fonction de dcodage hexadcimal 7 segments (cf. cours).
#include <p16F84.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

org 0x0000
goto main

org 0x0010
HexaTo7Segments:
addwf PCL, f
retlw b'00111111' ;decode 0
retlw b'00000110' ;decode 1
retlw b'01011011' ;decode 2
retlw b'01001111' ;decode 3
retlw b'01100110' ;decode 4
retlw b'01101101' ;decode 5
retlw b'01111101' ;decode 6
retlw b'00000111' ;decode 7
retlw b'01111111' ;decode 8
retlw b'01101111' ;decode 9

main:
// init portB
bsf STATUS, RP0 ; bank1
movlw 0x00
movwf TRISB ; PORTB en sortie
bcf STATUS, RP0 ; bank0

movlw 5; Exemple ....
call HexaTo7Segments
movwf PORTB

END
TD 4 Microcontrleur INSA GE
2/16
Brochage du PORTB (RB0 -~ a. RB1 -~ b. .)

b- On veut connatre les valeurs approches de sin(x) pour x entier et x compris entre
0 et 90. Proposer une solution de mise en ouvre (attention aux valeurs relles.).

Faire la mme chose que pour le decodage 7 segments. mais pour 90 valeurs diIIerentes !
Une instruction est codee sur 14 bits. il Iaudra 90 instructions pour les 90 valeurs. Point
de vue utilisation memoire ce choix n`est pas le plus economique. mais :
Les instructions sont ecrites en memoire programme. La memoire programme permet de
stoker 1000 instructions sur le PIC 16C84 (8k pour 16F877). Si le programme est petit et que
les autres memoires sont utilisees. cette solution est interessante.
Nombre de valeurs maxi : 255


II Adressage index
a- Ecrire le programme permettant d`additionner 2 vecteurs de taille n. Les vecteurs
sont en mmoire RAM aux adresses v1 et v2. ainsi que leur taille n. Le vecteur rsultat s
sera aussi stock en RAM. On suppose que la somme de chaque composante est
infrieure 255. (cf. Figure 4).
#include <p16F84.inc> ; processor specific variable
definitions
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

;***** VARIABLE DEFINITIONS
v1 equ 0x0010 ; premier vecteur
v2 equ 0x0018 ; le deuxime
s equ 0x0020 ; le resultat
n equ 0x000C ; la taille des vecteurs (max: 8)
i equ 0x000D ; indice de la boucle
p_v1 equ 0x002A ; pointeur sur la case en cours de v1
p_v2 equ 0x002B
p_s equ 0x002C
tmp_v equ 0x002D ; valeur tmp pour l'addition
;****************************************************************
ORG 0x0000 ; processor reset vector
goto main ; go to beginning of program
TD 4 Microcontrleur INSA GE
3/16

ORG 0x0010

main:
bcf STATUS, RP0 ; bank0
;init des variables
clrf i ; 0-> i
movlw v1 ; on rcupre l'adresse de v1 (0x10)
movwf p_v1

movlw v2 ; on rcupre l'adresse de v2 (0x18)
movwf p_v2

movlw s ; idem avec s
movwf p_s

main_B1:
; valeur de v1[i] -> tmp_v
movf p_v1, W
movwf FSR
movf INDF, W
movwf tmp_v
; valeur de v2[i] -> W
movf p_v2, W
movwf FSR
movf INDF, W
; addition W + tmp_v -> tmp_v
addwf tmp_v, f
; tmp_v -> s[i]
movf p_s, W
movwf FSR
movf tmp_v, W
movwf INDF

; i = i+1 (et tous les pointeurs)
incf p_v1, f ;
incf p_v2, f
incf p_s , f
incf i , f ;
; on continue ?
movf i, W
subwf n, W ; n - i -> W!!!!
btfss STATUS, Z
goto main_B1 ; non fait si STATUS<Z> = 1

; fin
nop
END



b- Les 46 valeurs pour x0. 2. 4. .. 90 de

) sin( . 255 x ont t crites dans les 46
premires adresses de l`EEPROM du PIC. Ecrire la fonction retournant la valeur de
sin(x). x[0;90]. (cf. Figure 5 et Figure 6).
TD 4 Microcontrleur INSA GE
4/16
ce type de Ionction peut servir pour du calcul (asservissement. mesure de longueur.
calcul de dephasage. .). pour de la generation de signaux (on envoie ensuite la valeur
numerique sur un convertisseur numerique analogique). .
Correction en c.

c- Modifier la fonction prcdente afin d`obtenir sin(x) pour x[0;180] (cf. Figure
8).
Le probleme est de generaliser le calcul de |0 ; 90| a |0 ; 180| a partir des mmes
valeurs. Il Iaut utiliser la parite de sin(x) en pi/2 : pour pi/2~x~pi. on a sin(pi-x) sin(x).
#include <p16F84.inc> ; processor specific variable
definitions
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC


;***** VARIABLE DEFINITIONS
org 0x2100 ; 10 0001 0000 0000 (14 bits) : adresse EEPROM
; de permet de stocker des valeurs (ou variables) en EEPROM
t_sinus de .0, .9, .18, .27, .36, .45
de .54, .62, .71, .79, .88, .96
de .104, .112, .120, .128, .136, .143
de .150, .157, .164, .171, .178, .184
de .190, .196, .201, .207, .212, .217
de .221, .226, .230, .233, .237, .240
de .243, .246, .248, .250, .252, .253
de .254, .255, .255, .255

; variable en RAM
sinus_indice equ 0x0010
tmp_W equ 0x0011
;*******************************************************************
***
; processor reset vector
ORG 0x0000
goto main ; go to beginning of program

ORG 0x0010
Sinus_W: ; la valeur en degr est dans W
; sauvegarde de W
movwf sinus_indice

; ajouter ces lignes pour la question c
; W > 90 ?
sublw .90 ; 90 - W -> W
btfsc STATUS, C
goto Sinus_p90
; W>90 : calculer sin(180 - W)
movf sinus_indice, W;
sublw .180; k - W -> W
movwf sinus_indice;

Sinus_p90:
bcf STATUS, C ; si W = 90, mise 0 du flag C (rrf !)
; fin ajout pour question c

TD 4 Microcontrleur INSA GE
5/16
; division par 2
rrf sinus_indice, f

bcf STATUS, RP0 ; bank 0
movlw t_sinus ; debut de la table
addwf sinus_indice, W ; + offset (indice)

movwf EEADR ; positionner le pointeur EEPROM
bsf STATUS, RP0; bank 1
bsf EECON1, RD ; lecture
bcf STATUS, RP0; bank 0
movf EEDATA, W ; lire la valeur
; t_sinus[sinus_indice] -> W
return

main:
nop
; movlw .10 ; .10 : table: 0x2D = 45 -> /256 = 0.1764;
sin(10)=0.1736
movlw .170 ; question c
call Sinus_W
nop
END



III Arithmtique : addition 16 bits
- Faire la fonction Add1 permettant d`additionner deux valeurs a et b de 16 bits. Le
rsultat de l`addition s fera aussi 16 bits. Chaque variable 16 bits sera compose de 2
octets : la partie basse (octet de poids faible. par exemple al pour a) et la partie haute
(poids fort. ah).
- Ecrire un programme utilisant la fonction Add1. Les variables a et b seront
initialiser aux valeurs de votre choix.
- Signaler le dpassement de capacit (cf. Figure 3) en allumant une LED sur
PORTB<0>.
#include <p16F84.inc> ; processor specific variable
definitions
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

;***** VARIABLE DEFINITIONS
ah equ 0x0010 ; poids fort a
al equ 0x0011 ; poids faible a
bh equ 0x0012 ; poids fort b
bl equ 0x0013 ; poids faible b
sh equ 0x0014 ; poids fort s (resultat)
sl equ 0x0015 ; poids faible s

;****************************************************************
ORG 0x0000 ; processor reset vector
goto main ; go to beginning of program

ORG 0x0010
Add16:
TD 4 Microcontrleur INSA GE
6/16
; init de s
; ah -> sh
movf ah, W
movwf sh

; al -> sl
movf al, W
movwf sl

; somme sl + bl
movf bl, W
addwf sl, f

;dpassement ?
btfsc STATUS, C
incf sh, f

; somme sh + bh -> sh
movf bh, W
addwf sh, f
return


main:
; init du portB
bsf STATUS, RP0 ; bank 1
bcf TRISB, 0 ; RB0 en sortie
bcf STATUS, RP0 ; bank 0
; init a
movlw H'FE'
movwf al
movlw H'30'
movwf ah

; init b
movlw H'FF'
movwf bl
movlw H'D0'
movwf bh

call Add16
; LED ?
bcf PORTB, 0 ; LED teinte
btfsc STATUS, C
bsf PORTB, 0 ; LED allume

; goto main
nop

END




TD 4 Microcontrleur INSA GE
7/16
IV Arithmtique : Multiplication 8 bits
- Faire l`organigramme d`une fonction permettant de multiplier deux valeurs 8 bits a
et b. Le rsultat sur 16 bits sera crit dans 2 variables 8 bits ml (octet de poids faible) et
mh (octet de poids fort).
- Ecrire le code assembleur de cette fonction.

Plusieurs solutions : la plus simple etant de se servir de a appels a la Ionction Add16
precedente via une boucle.
Une solution plus rapide (temps constant de 41 cycles avec l`appel.) :
#include <p16F84.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

;***** VARIABLE DEFINITIONS
m_a equ 0x0010 ;
m_b equ 0x0011 ;
m_h equ 0x0012 ; poids fort b
m_l equ 0x0013 ; poids faible b

;*******MACRO DEFINITION
AddRoll MACRO ; addition et roll via la carry de m_h m_l
btfsc STATUS,C
addwf m_h,F ; addition de W
rrf m_h,F ; on passe par la carry
rrf m_l,F ; la valeur de C passe sur m_l<7>
ENDM

ORG 0x0000 ; processor reset vector
goto main ; go to beginning of program

ORG 0x0010
Mul8x8: ;* 2 cycles for call - instruction
;m_a * m_b => m_h:m_l
movf m_a, W ; m_a -> m_l
movwf m_l
movf m_b, W ; m_b -> W
clrf m_h ; 1 cycle
rrf m_l,F ; 1 cycle
; utilisation de la macro AddRoll
AddRoll ; 4 cycles
AddRoll
AddRoll
AddRoll
AddRoll
AddRoll
AddRoll
AddRoll
retlw 0 ; 2 cycles

main:
movlw .50
movwf m_a

movlw .10
movwf m_b
TD 4 Microcontrleur INSA GE
8/16

call Mul8x8
END


TD 4 Microcontrleur INSA GE
9/16

Annexes :
Extraits de la documentation Microchip PIC16C84

http://ww1.microchip.com/downloads/en/devicedoc/30445c.pdI



Figure 1. Organisation de la memoire. PIC 16C84

TD 4 Microcontrleur INSA GE
10/16

Figure 2 . Details des registres du PIC16C84.


TD 4 Microcontrleur INSA GE
11/16

Figure 3. Detail du registre STATUS

TD 4 Microcontrleur INSA GE
12/16


Figure 4 . Description de ladressage indirect



TD 4 Microcontrleur INSA GE
13/16

Figure 5. Description des acces a lEEPROM (1/2)

TD 4 Microcontrleur INSA GE
14/16

Figure 6 . Description des acces a lEEPROM (2/2)




TD 4 Microcontrleur INSA GE
15/16


Figure 7. Jeu dinstructions des PIC 16CXXX

TD 4 Microcontrleur INSA GE
16/16

Figure 8 . Description detaillee des instructions SUBLW et SUBWF