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
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
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
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