TP microcontrˆ oleur 16 bits : MSP430
J.-M Friedt, 5 avril 2015 Objectif de ce TP :
— pr´esentation de GNU/Linux et de commandes unix
— faire clignoter des diodes, exemples en C
— communication RS232, communication de donn´ees en ASCII
— timer, processus p´eriodiques, interruptions
— conversion num´erique-analogique de donn´ees, ´echantillonnage
— communication SPI, acc`es `a la carte SD
1 GNU/Linux
L’arborescence de GNU/Linux et comment s’y retrouver : dans l’ordre de priorit´e :
— /est la racine de l’arborescence. Le s´eparateur entre r´epertoire sera toujours le/.
— /home contient les r´epertoires des utilisateurs. Unix, et Linux en particulier, impose un confinement strict des fichiers de chaque utilisateur dans son r´epertoire. Seul l’administrateur (root) peut acc´eder aux fichiers du syst`eme en ´ecriture :ne jamais travailler en tant qu’administrateur.
— /usrcontient les programmes locaux `a un ordinateur : applications, entˆetes de compilation (/usr/include), sources du syst`eme (/usr/src)
— /lib contient les biblioth`eques du syst`eme d’exploitation
— /proccontient des pseudo fichiers fournissant des informations sur la configuration et l’´etat du mat´eriel et du syst`eme d’exploitation. Par exemple,cat /proc/cpuinfo.
— /etccontient les fichiers de configuration du syst`eme ou la configuration par d´efaut des logiciels utilis´es par les utilisateurs en l’absence de fichier de configuration locale (par exemplecat /etc/profile).
— /bin contient les outils du syst`eme accessibles aux utilisateurs et/sbin contient les outils du syst`emes qu’a prioriseul l’administrateur a `a utiliser.
Les commandes de base :
— ls: list, afficher le contenu d’un r´epertoire
— mv: move, d´eplacer ou renommer un fichier.mv source dest
— cd: change directory, se d´eplacer dans l’arborescence. Pour remonter dans l’arborescence :cd ..
— rm: remove, effacer un fichier
— cp: copy, copier un fichier.cp source destAfin de copier un r´epertoire et son contenu, cp -r repertoire destination.
— cat: afficher le contenu d’un fichier.cat fichier
— man, manuel, est la commande la plus importante sous Unix, qui donne la liste des options et le mode d’emploi de chaque commande.
Afin de remonter dans l’historique, utiliser SHIFT+PgUp. Toute commande est lanc´ee en tˆache de fond lorsqu’elle est termin´ee par&.
L’interface graphique est une sur-couche qui ralentit le syst`eme d’exploitation et occupe des ressources, mais peut parfois faciliter la vie en proposant de travailler dans plusieurs fenˆetres simultan´ement. Elle se lance au moyen destartx.
Parmi les outils mis `a disposition, un ´editeur de texte (scite), un clone opensource de matlab nomm´eoctave, un outil pour tracer des courbes (gnuplot), affichage des fichiers au format PDF par xpdf, un gestionnaire de fichiers (pcmanfm).
La liste des modules noyaux (´equivalent des pilotes, charg´es de r´ealiser l’interface logicielle entre le noyau Linux et l’espace utilisateur) s’obtient par/sbin/lsmod.
2 Premier pas avec gcc
Dans un ´editeur de texte (scite), taper le programme suivant :
#include <stdio.h>
#include <stdlib.h>
int main() {printf("hello world %d\n",getpid());}
Nous n’utiliserons pas d’environnement int´egr´e de d´eveloppement (IDE) : un ´editeur de texte sert `a entrer son programme, et une fenˆetre de commande (xtermou Terminal) servira `a la compilation.
Une fois le programme tap´e, sauver dans un fichier exemple1.c et compiler dans un terminal en entrant la ligne de commande : gcc -o exemple1 exemple1.c (compiler le programme C exemple1.c r´esultant en l’ex´ecutableexemple1).
Exercice :ex´ecuter le programme par./exemple1.
3 Premier pas sur MSP430
L’exemple pr´ec´edent ´etait une compilation de programme : l’architecture sur laquelle le programme sera ex´ecut´e est la mˆeme que celle sur laquelle le programme est compil´e (ici, Intel x86).
Nous allons d´esormais compiler des programmes `a destination du microcontrˆoleur : il s’agit de cross- compilation.
GND
100n
VDD
GND 1n 1n
GND
2k
>22µ
GND
VDD
2k
100n
F/TMB
RACON12 RACON12 RACON12 LE33CZ
GMSTBA2 5_Ohms
VDD
GND
GND
GND
VDD
GND 74HC245DW
74HC245DW VDD
VDD
GND
HD-H103
HD-H103
GND VDD GND
VDD
GND
VDD
GND VDD
100n
10k
10k 10k 10k10k
10k 10k
10k
10k 10k
10k 10k
10k
10k 10k 10k
3k
10k
10k 10k
4k7
10k
10k 10k 10k 10k 10k 10k 10k 10k
10k 74LS47N
VDD
GND
100n 100n
100n GND OP11D
OP11D
OP11D GND
VDD
VDD
VDD
DVCCP$1P6.3/A3P$2P6.4/A4P$3P6.5/A5P$4P6.6/A7P$5P6.7/A7P$6VREF+P$7XINP$8XOUTP$9VEREF+P$10VREF-P$11P1.0/TACLKP$12P1.1/TA0P$13P1.2/TA1P$14P1.3/TA2P$15P1.4/SMCLKP$16
P1.5/TA0 P$17
P1.6/TA1 P$18
P1.7/TA2 P$19
P2.0/ACLK P$20
P2.1/TAINCLK P$21
P2.2/CAOUT P$22
P2.3/TA1 P$23
P2.4/TA2 P$24
P2.5/ROSC P$25
P2.6/ADC12CLK P$26
P2.7/TA0 P$27
P3.0/STE0 P$28
P3.1/SIMO0 P$29
P3.2/SOMI0 P$30
P3.3/UCLK0 P$31
P3.4/UTXD0 P$32
P3.5/URXD0P$33 P3.6P$34 P3.7P$35 P4.0/TB0P$36 P4.1/TB1P$37 P4.2/TB2P$38 P4.3P$39 P4.4P$40 P4.5P$41 P4.6P$42 P4.7/TBCLKP$43 P5.0P$44 P5.1P$45 P5.2P$46 P5.3P$47 P5.4/MCLKP$48 P5.5/SMCLKP$49 P5.6/ACLKP$50 P5.7/TBOUTHP$51 XT2OUTP$52 XT2INP$53 TDO/TDIP$54 TDI/TCLKP$55 TMSP$56 TCKP$57 RST#/NMIP$58 P6.0/A0P$59 P6.1/A1P$60 P6.2/A2P$61 AVSSP$62 DVSSP$63 AVCCP$64
MSP430H149C1C2 C3 21Q1 C4C5 C6
C7 12345678
JP1
VCCIO 4 20 VCC
USBDM 16
USBDP 15
8 NC _RESET 19 24 NC 27 OSCI 28 OSCO
3V3OUT 17
TXD 1
RXD 5
_RTS 3
_CTS 11
_DTR2
_DSR9
_DCD10
_RI 6
CBUS0 23
CBUS1 22
CBUS2 13
CBUS3 14
CBUS4 12
AGND25 GND7 GND18 GND21 TEST26 IC1
FT232RL
R3
C8
D1
1 2 3 4
X1 R5
C9
LED1 LED2 LED3 LED4 LED5 LED6 LED7 LED8
910 11 12 13 14 1516 12 3 4 5 6 78 S1
LEDALIM
BUZZER -+
1 3 4 S2
2
1 3 4 S3
2
1 3 4 S4
2 3VI
2
VO1
IC2 GND X2-1 1
X2-2 2 RESMES1
C10
1 JP2
1 JP3
1 DIR 2 A1 3 A2 4 A3 5 A4 6 A5 7 A6 8 A7 9 A8 B8B7B6B5B4B3B2B1 1112131415161718
19 G
1020
IC3P
GNDVCC
1 DIR 2 A1 3 A2 4 A3 5 A4 6 A5 7 A6 8 A7 9 A8 B8B7B6B5B4B3B2B1 1112131415161718
19 G
1020
IC4P
GNDVCC
1
2 3
4 5
6 7
8
JP5
10 9 2 6
7 3
DIS1
4 1
5
8 CC CC dp
a b c d e f g
109 2
67 3
DIS2 4 1
5 8 CC CC
dp a b c d e f g CSDI 12
GNDVCCSCK 345 GND1IRQDO 678
WP WP
CD CD
SW SW
SHIELD 14
1 23 4 5 6 7 8 SV2
C11 12 RN2A3 RN2B4 RN2C5 RN2D
12 RN1A3 RN1B4 RN1C5 RN1D6 RN1E7 RN1F8 RN1G9 RN1H
R6
R9 R10 R8R11
R12 R25
R26
R27 R28
R29 R30
R31
R32 R33 R1
R2
R34
R21 R22
R4
R23
R13 R14 R15 R16 R17 R18 R19 R20
R24 816
IC6G$2
GNDVCC
1 IB 2 IC
3 LT BI/RBO 4 5 RBI 6 ID 7 IA
E 9
D 10
C 11
B 12
A 13
GF 1415 IC6 1
2 3 4
5SV3
Q3
C12 C13
C14
DVCC1P6.3/A32P6.4/A43P6.5/A54P6.6/A65P6.7/A76VREF+7XIN8XOUT/TCLK9VEREF+10VEREF-11P1.0/TACLK12P1.1/TA013P1.2/TA114P1.3/TA215P1.4/SMCLK16
P1.5/TA0 17
P1.6/TA1 18
P1.7/TA2 19
P2.0/ACLK 20
P2.1/TAINCLK 21
P2.2/CAOUT/TA0 22
P2.3/CA0/TA1 23
P2.4/CA1/TA2 24
P2.5/ROSC 25
P2.6/ADC12CLK 26
P2.7/TA0 27
P3.0/STE0 28
P3.1/SIMO0 29
P3.2/SOMI0 30
P3.3/UCLK 31
P3.4/UTXD0 32
P3.5/URXD033 P3.6/UTXD134 P3.7/URXD135 P4.0/TB036 P4.1/TB137 P4.2/TB238 P4.3/TB339 P4.4/TB440 P4.5/TB541 P4.6/TB642 P4.7/TBCLK43 P5.0/STE144 P5.1/SIMO145 P5.2/SOMI146 P5.3/UCLK147 P5.4/MCLK48 P5.5/SMCLKP5.6/ALK 4950 P5.7/TBOUTHRST/NMIXT2OUTTDO/TDIP6.0/A0P6.1/A1P6.2/A2XT2INAVSSDVSSAVCCTMSTCKTDI 5152535455565758596061626364
2 3 1 IC7A
6 5 7 IC7B
9 8 10 IC7C
4 11
R7
R35
R36 R37
R38
R39 R40
R41
R42 1 2 JP4
1 2 JP6
12 JP7
USB ON
12345678
+
Le MSP4301se programme en C au moyen du mˆeme compilateur que vu pr´ec´edemment (gcc), mais configur´e pour g´en´erer du code `a destination de la nouvelle architecture cible (MSP430), diff´erente de l’architecture hˆote (Intel 32 bits). Il s’agit donc decrosscompilation.
XOR 0 0 1
1
1 0
1
#include <msp430x14x.h> 0
#include <string.h>
#include <legacymsp430.h> // #include <signal.h>
#include <msp430.h> // #include <io.h>
#include <stdio.h>
void init_PORT(void){
P1SEL = 0x00;
P1DIR = 0xFF;
P1OUT = 0x00;
}
int main (void) {
unsigned int led1=0x01,sens=0,k;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
1. focus.ti.com/lit/ds/symlink/msp430f149.pdfethttp://focus.ti.com/lit/ug/slau049f/slau049f.pdf
init_PORT();
while (1) { P1OUT=led1;
if(led1==0x80) {sens=1;}
if(led1==0x01) {sens=0;}
if(sens==0) {led1<<=1;}
if(sens==1) {led1>>=1;}
for(k=0;k<50000;k++) {}
}
return(0);
}
Compilation du programme :
msp430-gcc -Os -mmcu=msp430f149 -o sortie.elf entree.c pour g´en´erer le listing correspondant :
msp430-objdump -dSt sortie.elf > sortie.lst
et la liste d’instructions au format hexad´ecimal Intel `a partir du fichier ELF : msp430-objcopy -O ihex sortie.elf sortie.hex
Rappel :gcc -Sarrˆete la compilation `a la g´en´eration de l’assembleur (fichier .s),gcc -oarrˆete la compilation
`
a la g´en´eration des objets (avant le linker).
Une fois le programme compil´e, il est transf´er´e au MSP430 par l’interface JTAG, ici ´emul´ee par le port parall`ele (imprimante) du PC. La commande pour transf´erer par le convertisseur parall`ele-JTAG le programme sortie.elf est :
msp430-jtag -e sortie.elf
Chaque port d’entr´ee sortie n´ecessite de d´efinir :
— la fonction de chaque broche avec le registre PxSEL : 0 pour du GPIO, 1 pour la fonction sp´ecifique
— la direction du port dans PxDIR : 0 pour une entr´ee, 1 pour une sortie
— le niveau de la broche, 1 pour un niveau haut (3,3 V) et 0 pour le niveau bas (masse)
Exercices
1. analyser le sch´ema du circuit et identifier le port auquel sont connect´ees les diodes ´electroluminescentes (LED).
2. les composants 74245 (IC3 et IC4) se comportent comme des latchs : quelle est leur utilit´e dans ce circuit ?
Les ports du MSP430 sont capables d’absorber ou fournir la vingtaine de milliamp`eres n´ecessaires `a alimenter une LED.
Cet exemple exploite la fonction de d´ecalage pour p´eriodiquement changer l’´etat du port et donc allumer ou
´
eteindre les diodes qui y sont connect´ees.
Exercices :
— au lieu de faire d´efiler les diodes, faire clignoter l’ensemble des 8 diodes simultan´ement.
— visualiser le code assembleur g´en´er´e
— Comment s’´ecrit 2048 en hexad´ecimal ?
— comment est initialis´e le pointeur de pile (R1) ? commenter ce choix, sachant que la RAM commence `a l’adresse 0x200 (page 1-4 de slau049) et que ce processeur contient 2048 octets de RAM.
— modifier les options d’optimisation en modifiant l’option -Os par -O1, -O2 et -O3. Comparer les codes assembleur r´esultant.
4 Communiquer par RS232
Initialisation d’un port s´erie : pour le port 0, avec un d´ebit de 9600 bauds
#include <msp430x14x.h>
#include <string.h>
#include <legacymsp430.h> // #include <signal.h>
#include <msp430.h> // #include <io.h>
#include <stdio.h>
void init_rs1_9600(){
UCTL1=SWRST; // SetupUART1: mov.b #SWRST,&UCTL1 UCTL1|=CHAR; // bis.b #CHAR,&UCTL1
UTCTL1=SSEL0; // mov.b #SSEL0,&UTCTL1 UBR01=0x03; // mov.b #0x03,&UBR01 UBR11=0x00; // mov.b #0x00,&UBR11 UMCTL1=0x4A; // mov.b #0x4A,&UMCTL1 UCTL1&=~SWRST; // bic.b #SWRST,&UCTL1
ME2|=UTXE1+URXE1; // bis.b #UTXE1+URXE1,&ME2 }
void snd_rs1(char cara)
{while ((IFG2 & UTXIFG1)==0); // jz rs_tx1 TXBUF1=cara;
}
void str_rs1(char* cara) {int k=0;
do {snd_rs1(cara[k]);k++;} while (cara[k]!=0);
}
void init_PORT(void){
P3SEL=0xFE; // ; P3.6,7 = USART select P3DIR=0x5B; // ; P3.6 = output direction P3OUT=0x01; // ; P3.6 = output val }
int main (void) { char chaine[30];
unsigned long k;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT init_PORT();
init_rs1_9600();
while (1) {
snd_rs1(’!’);snd_rs1(33);
sprintf(chaine,"Hello World\r\n");
str_rs1(chaine);
for(k=0;k<8000;k++) {}
}
return(0);
}
Le MSP430 poss`ede un module de communication asynchrone (RS232) mat´eriel. Les param`etres de configu- ration incluent le d´ebit de communication (dans cet exemple 9600 bauds), le nombre de bits par trame transmise et l’encapsulation de ces trames. Les ordinateurs ´etant de moins en moins souvent ´equip´es de port s´erie, nous exploitons un composant convertisseur du format RS232 vers l’USB.
Exercice :
identifier le composant permettant la conversion RS232 vers USB sur le sch´ema de la carte.
Cˆot´e PC, la communication par port s´erie se fait au moyen de minicom : CTRL A-O pour d´efinir le port (/dev/ttyUSB0) et le contrˆole de flux (ni mat´eriel, ni logiciel).CTRL A-Ppour d´efinir la vitesse (ici 9600 bauds, N81).
Exercices :
1. envoyer une valeur hexad´ecimale (par exemple 0x55 et 0xAA) en ASCII 2. envoyer une valeur en d´ecimal (par exemple 250) en ASCII
3. sachant qu’une chaˆıne de caract`eres est repr´esent´ee en C par un tableau de caract`eres se terminant par le caract`ere de valeur 0, expliquer le fonction- nement de la proc´edurestr rs1.
4. dans le programme en C faisant clignoter les diodes, communiquer la valeur courante d’une variable.
Idle
MSB Stop Bit
LSB Start Bit
5 Exploitation d’une interruption
Nous avons vu que le code assembleur g´en´er´e depuis un programme C d´epend des options d’optimisation.
Cela signifie notamment que la dur´ee d’ex´ecution d’une boucle vide d´epend de ces options, et ´evidemment de la nature du compilateur.
Le microcontrˆoleur poss`ede en interne des compteurs (timers) qui permettent de mesurer avec pr´ecision un intervalle de temps selon une horloge cadenc´ee sur un oscillateur externe et donc ind´ependant du code ex´ecut´e. Cette strat´egie rend la dur´ee d’ex´ecution du programme ind´ependante de la nature des optimisa- tions.
La fr´equence de d´eclenchement du timer est d´efinie par la variable TBCCR0. Le timer compte de 0 `a TBCCR0, et lorsque la valeur stock´ee dans ce registre est atteinte, l’interruption se d´eclenche. Noter que de cette fa¸con, le timer compte TBCCR0+1 fois. La cadence de l’hor- loge dans notre configuration est 32768 Hz.
Par ailleurs, le microcontrˆoleur peut ˆetre plac´e en mode de veille au moyen des instructions LPM (Low Power Mode) termin´ees par le num´ero du mode de veille. Plus le num´ero est ´elev´e, plus le nombre de p´eriph´eriques d´esactiv´es est important, mais plus le nombre de sources d’interruption devient r´eduit. Ainsi, une uti- lisation tr`es utile du timer est la sortie p´eriodique du mode veille dans lequel on place le microcontrˆoleur afin d’´economiser l’´energie.
Extrait du manuel de l’utilisateur du MSP430
#include <msp430x14x.h>
#include <string.h>
#include <legacymsp430.h> // #include <signal.h>
#include <msp430.h> // #include <io.h>
#include <stdio.h>
void Sommeil(void);
void Pause_TIMERB(unsigned short Compteur);
void Pause_ms(unsigned short ms);
interrupt(TIMERB0_VECTOR ) wakeup Vector_TIMERB0(void);
void init_horloge(void);
void init_PORT(void);
void init_TIMER(void);
unsigned char TIMERB=0;
void Sommeil(void) {LPM3;}
void Pause_TIMERB(unsigned short Compteur) {TIMERB=0;
TBCCR0=Compteur;
TBCTL=TBSSEL0+TBCLR + MC_1;
while(TIMERB==0) Sommeil();
}
void Pause_ms(unsigned short ms)
{Pause_TIMERB((unsigned short)(ms*32768/1000));}
interrupt(TIMERB0_VECTOR ) wakeup Vector_TIMERB0(void) {TIMERB=1;}
void init_horloge(void){
BCSCTL1 = 0x87;
BCSCTL2 = SELM1 + SELS;
WDTCTL = WDTPW + WDTHOLD;
}
void init_PORT(void){
P1SEL = 0x00;
P1DIR = 0xFF;
P1OUT = 0x00;
}
void init_TIMER(void) {TBCTL=TBSSEL0 + TBCLR;
TBCCTL0|=CCIE; // CCR0 interrupt enabled TBCCR0=16000;
TBCTL|= MC_0;
}
int main (void)
{unsigned int led1=0x01,sens=0,pause;
init_horloge();
init_PORT();
init_TIMER();
eint();
pause=15;
while (1) { P1OUT=led1;
if(led1==0x80) {sens=1;}
if(led1==0x01) {sens=0;}
if(sens==0) {led1<<=1;}
if(sens==1) {led1>>=1;}
Pause_ms(pause);
if(pause>80) pause=1; else pause++;
}
return(0);
}
Exercices :
1. exploiter une interruption timer pour faire clignoter une diode `a fr´equence pr´ecis´ement d´etermin´ee depuis la fr´equence du r´esonateur `a quartz
2. ´ecrire une fonction d’horloge temps-r´eel capable d’afficher le temps en secondes et minutes 3. modifier la vitesse de d´efilement du chenillard
R´eduire la p´eriode d’oscillation des LEDs se traduit `a terme par la perte de sensation de clignotement par persistance r´etinienne. Cependant, si au lieu de commuter l’´etat d’une diode, nous commutons un haut parleur, un signal sonore de fr´equence ´egale au signal d’excitation se fait entendre. Ce haut parleur est connect´e `a la broche P4.0. Un second timer (le MSP430 poss`ede deux timers, TimerA et TimerB) permet de r´egler la dur´ee des notes ainsi g´en´er´ees.
#include <msp430x14x.h>
#include <string.h>
#include <legacymsp430.h> // #include <signal.h>
#include <msp430.h> // #include <io.h>
#include <stdio.h>
void Sommeil(void);
void Pause_TIMERB(unsigned short Compteur);
void Pause_ms(unsigned short ms);
interrupt(TIMERB0_VECTOR ) wakeup Vector_TIMERB0(void);
void init_horloge(void);
void init_PORT(void);
void init_TIMER(void);
unsigned int PWM=0;
unsigned int ma_note=0;
unsigned int note[14]={74,66,63,56,50,47,42,37,35, \ 33,31,27,25,23};
#define labas 0
#define sibas 1
#define do 2
#define re 3
#define mi 4
#define fa 5
#define sol 6
#define la 7
#define sid 8
#define si 9
#define dohaut 10
#define rehaut 11
#define mihaut 12
#define fahaut 13
#define solhaut 14
#define A3 labas
#define B3 sibas
#define C3 do
#define D3 re
#define E3 mi
#define F3 fa
#define G3 sol
#define A4 la
#define B4x sid
#define B4 si
#define C4 dohaut
#define D4 rehaut
#define E4 mihaut
#define F4 fahaut
#define G4 solhaut // #define Nbr_Max 16
// unsigned int musique[Nbr_Max]={sol,sol,sol,la,si,si,la,la,sol,\
// si,la,la,sol,sol,sol,sol};
#define Nbr_Max 98
unsigned int musique[Nbr_Max]= \
{A4 ,A4 ,E3 ,F3 ,G3 ,G3 ,F3 ,E3 ,D3 ,D3 ,D3 ,D3 ,F3 ,A4 ,A4 , \
G3, F3 ,E3 ,E3 ,E3 ,E3 ,F3 ,G3,G3,A4,A4,F3,F3,D3,D3,D3,D3,\
B4x,B4x,B4x,B4x,C4 ,D4 ,D4 ,C4 ,B4x,A4 ,A4 ,A4 ,A4 ,F3 ,A4 , \ A4, G3 ,F3 ,E3 ,E3 ,E3 ,E3 ,F3,G3,G3,A4,A4,F3,F3,D3,D3,D3,D3,\
B4x,B4x,B4x,B4x,C4 ,D4 ,D4 ,C4 ,B4x,A4 ,A4 ,A4 ,A4 ,F3 ,A4 ,A4\
,G3 ,F3 ,E3 ,E3 ,E3 ,E3 ,F3,G3,G3,A4,A4,F3,F3,D3,D3,D3,D3};
interrupt(TIMERA0_VECTOR ) /*wakeup*/ Vector_TIMERA0(void) {ma_note++;
if(ma_note==Nbr_Max) ma_note=0;
P1OUT=(1<<(musique[ma_note]-D3));
TBCCR0=note[musique[ma_note]];
}
interrupt(TIMERB0_VECTOR ) /*wakeup*/ Vector_TIMERB0(void) {P4OUT^=0x01;}
void init_horloge(void){
BCSCTL1 = 0x87;
BCSCTL2 = SELM1 + SELS;
WDTCTL = WDTPW + WDTHOLD;
}
void init_PORT(void){
P1SEL = 0x00;
P1DIR = 0xFF;
P1OUT = 0x00;
P4SEL=0x00;
P4DIR=0xFF;
P4OUT=0x00;
}
void init_TIMER(void){
TACTL=TASSEL0 + TACLR;
TACCTL0|=CCIE; // CCR0 interrupt enabled TACCR0=8192;
TACTL|= MC_0;
TBCTL=TBSSEL0 + TBCLR;
TBCCTL0|=CCIE;
TBCCR0=PWM;
TBCTL|= MC_0;
}
int main (void) {init_horloge();
init_PORT();
init_TIMER();
eint();
TACTL|= MC_1 + TACLR;
TBCTL|= MC_1 + TBCLR;
TBCCR0=note[musique[0]];
while (1) {LPM3;}
return(0);
}
6 Lire une valeur analogique
Tous les programmes r´ealis´es jusqu’ici vont nous permettre d’atteindre le but de ce TP : mesurer une grandeur physique `a intervalles de temps r´eguliers et retranscrire ces informations pour les rendre exploitables par un utilisateur.
#include <msp430x14x.h>
#include <string.h>
#include <legacymsp430.h> // #include <signal.h>
#include <msp430.h> // #include <io.h>
#include <stdio.h>
void init_rs1_9600(){
UCTL1=SWRST; // SetupUART1: mov.b #SWRST,&UCTL1 UCTL1|=CHAR; // bis.b #CHAR,&UCTL1
UTCTL1=SSEL0; // mov.b #SSEL0,&UTCTL1 UBR01=0x03; // mov.b #0x03,&UBR01 UBR11=0x00; // mov.b #0x00,&UBR11 UMCTL1=0x4A; // mov.b #0x4A,&UMCTL1 UCTL1&=~SWRST; // bic.b #SWRST,&UCTL1 ME2|=UTXE1+URXE1; // bis.b #UTXE1+URXE1,&ME2 }
void snd_rs1(char cara)
{while ((IFG2 & UTXIFG1)==0); // jz rs_tx1 TXBUF1=cara;
}
void str_rs1(char* cara) {int k=0;
do {snd_rs1(cara[k]);k++;} while (cara[k]!=0);
}
void init_PORT(void){
P1SEL = 0x00;
P1DIR = 0xFF;
P1OUT = 0x00;
P3SEL=0xFE; // ; P3.6,7 = USART select P3DIR=0x5B; // ; P3.6 = output direction P3OUT=0x01; // ; P3.6 = output val }
void init_ADC(void){
ADC12CTL0=SHT0_6+REFON+ADC12ON; // V_REF=1.5 V ADC12CTL1=SHP;
ADC12MCTL0=INCH_10+SREF_1; // p.17-11: single conversion ADC12CTL0|=ENC;
}
unsigned short temperature()
{ADC12CTL0|=ADC12SC; // start conversion do {} while ((ADC12CTL1 & 1)!=0);
return(ADC12MEM0);
}
int main (void) { char chaine[30];
unsigned short t;
unsigned int temp;
unsigned long k;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT init_PORT();
init_ADC();
init_rs1_9600();
while (1) {
t=0;for (k=0;k<16;k++) t+=temperature();
t/=16;
temp=(int)(((float)t*1.5/4096.-0.986)/0.00355*10.);
sprintf(chaine,"Temperature=%x\r\n",temp);
str_rs1(chaine);
for(k=0;k<8000;k++) {}
}
return(0);
}
Le canal 10 (INCH 10) est un cas particulier : il s’agit d’une sonde interne de temp´erature.
Exercice :
lire la temp´erature et la transmettre sous forme hexad´ecimale (caract`eres ASCII) sur le port s´erie.
La conversion s’obtient (User Manual p.17-16) parVT emp = 0,00355×T empdegC+ 0,986. Nous observons exp´erimentalement un d´ecalage entre la temp´erature et la valeur du microcontrˆoleur qu’il semble n´ecessaire de calibrer pour chaque nouveau composant.
La temp´erature est une grandeur qui varie lentement. Un microcontrˆoleur travaille `a une fr´equence ´elev´ee et est donc susceptible de mesurer des ph´enom`enes se d´eroulant `a des fr´equences du mˆeme ordre de grandeur que les fr´equences audibles.
Afin de g´en´erer des signaux de l’ordre de quelques dizaines de Hz `a quelques kilohertz, nous allons exploiter la carte son qui ´equipe la majorit´e des ordinateurs personnels. Un logiciel,audacity2 propose de synth´etiser un signal et de l’´emettre sur la sortie de sa carte son.
2. disponible pour GNU/Linux, MacOS X et MS-Windows `ahttp://audacity.sourceforge.net/
Nous nous contenterons pour le moment de g´en´erer une sinuso¨ıde, pour n’exploiter que plus tard les formes d’ondes plus complexes (chirp).
Exercices :
1. enregistrer une s´equence issue de la carte son du PC
2. visualiser au moyen de GNU/Octave le r´esultat de l’acquisition (commandes identiques `a celles de Matlab, voir section 8 pour un rappel)
3. ´etablir la fr´equence d’´echantillonnage.
Nous pouvons suivre deux strat´egies pour ´etablir la fr´equence d’´echantillonnagefe: temporelle ou fr´equentielle.
Dans le premier cas nous comptons le nombre M d’´echantillons dansN p´eriodes et ´etablissons, connaissant la fr´equencefs du signal mesur´e, alors
fe= M Nfs
D’un point de vue fr´equentiel, la transform´ee de Fou- rier sur M points d’un signal num´eris´e `a fe s’´etend de
−fe/2 `a +fe/2. Connaissant la fr´equence de ce signal num´eris´e qui se pr´esente dans la transform´ee de Fourier comme une raie de puissance maximale en position N, nous d´eduisons que
N/M =fs/fe⇔fe=M
Nfs 500
1000 1500 2000 2500 3000 3500
0 20 40 60 80 100
tension (V)
echantillon (?)
signal a 440 Hz : plot
"minicom.cap" u 2
7 Acc` es carte m´ emoire
Les microcontrˆoleurs 8 et 16 bits ne fournissent pas une puissance de calcul importante mais sont capable d’effectuer un certain nombre d’op´erations simples telles qu’asservissements et acquisitions de donn´ees. Dans tous les cas, par soucis de contrˆolea posterioriou de dupliquer en local les donn´ees transmises en temps r´eel, les applications de ces microcontrˆoleurs sont ´etendues par la possibilit´e de stocker ces informations sur un support peu coˆuteux et consommant peu de courant en mode veille (Fig. 2). Nous nous proposons d’´etudier le stockage d’informations sur cartes m´emoires de type MutliMediaCard (MMC) ou Secure Digital (SD).
Afin de gagner du temps, nous ne d´etaillerons pas le protocole d’initialisation et de communication d’une carte SD : nous utiliserons une biblioth`eque mise `a disposition par son auteur pour conserver et relire des donn´ees sur support de stockage de masse non volatile3. L’utilisation d’une biblioth`eque opensource ne prive cependant pas d’en lire le contenu en vue d’en comprendre le fonctionnement.
1 = CS 2= MOSI 3=GND 5=CK 6=GND 7=MISO 4=Vcc=3,3 V
1 2 3 4 5 6 7 8 9
8,9 : NC (SD)
Figure 1 – Assignation des broches d’une carte SD. Les broches 8 et 9 n’existent pas dans les cartes MMC, qui fonctionnent sinon de la mˆeme fa¸con.
Les cartes SD fonctionnent en deux mode : le mode natif, rapide et supportant l’encryption des donn´ees, et le mode SPI, plus lent mais facilement accessible depuis n’importe quel microcontrˆoleur. Nous utiliserons ce second mode, dans lequel seules 4 broches sont utiles (fig. 1).
3. http://www.true-random.com/homepage/projects/msp430_mmc/
Apr`es initialisation parif (initMMC() == MMC SUCCESS), deux commandes de base nous servent `a ´ecrire (mmcWriteBlock(adresse)) et lire (mmcReadBlock(adresse, taille)) des donn´ees sur la carte. Il s’agit d’´ecritures non-format´ees : la carte n’est pas lisible depuis un PC qui s’attend `a trouver un syst`eme de fi- chier. Toute transaction sur une carte SD se fait par blocs de 512 octets (tableaummc buffer). Les informations ne sont pas stock´ees en zone non-volatile tant que l’acquittement d’´ecriture n’est pas ´emis : lors des acquisitions lentes, une partie de la derni`ere s´equence d’acquisitions pourra ˆetre perdue lors de la mise hors tension du circuit.
Afin de compiler notre programmeprogramme.c avec les biblioth`eques d’acc`es `a la carte SD : msp430-gcc -mmcu=msp430f149 -o sd.elf test_jmf.c led.o mmc.o
Pour programmer et voir imm´ediatement le r´esultat :
msp430-jtag -e sd.elf && stty -F /dev/ttyUSB0 9600 && cat < /dev/ttyUSB0
Exercices :
— valider quelques fonctions de debuggage dont nous devons ˆetre certain du bon fonctionnement : allu- mage/extinction des diodes, transmission de donn´ees en RS232
— ´ecrire dans un bloc de la carte SD une s´erie de valeurs, r´einitialiser le tableau de caract`eres et lire les valeurs stock´ees. V´erifier qu’il s’agit des valeurs ´ecrites.
— ´ecrire et relire sur plusieurs blocs m´emoire. Attention : les adresses doivent toujours ˆetre multiples de 512.
— ´ecrire des valeurs issues de la conversion analogique-num´erique ou de la lecture d’un port s´erie. Que se passe-t-il lors du passage d’un bloc de la carte SD au suivant ?
47.225 47.23 47.235 47.24 47.245 47.25
6.014 6.016 6.018 6.02 6.022 6.024 6.026 6.028 6.03 6.032 6.034 6.036
latitude (deg.)
longitude (deg.)
"080920_msp430.asc" u 1:2
6.014 6.016 6.018 6.02 6.022 6.024 6.026 6.028 6.03 6.032 6.034 6.036
47.225 47.23 47.235 47.24 47.245 47.25 250
300 350 altitude (m) 400
"080920_msp430.asc" u 1:2:3
longitude (deg.)
latitude (deg.) altitude (m)
Figure 2 – Exemple d’acquisition de trames GPS avec une fr´equence de 1 Hz, et restitution du trac´e en 2D (gauche) et 3D (droite) sousgnuplot.
8 Afficher des donn´ ees
Deux outils sont mis `a disposition pour afficher des courbes : gnuplotetoctave4. gnuplotaffiche des courbes lues dans des fichiers :
plot "fichier"
on peut pr´eciser les colonnes `a afficher, l’axe des abscisses et ordonn´ees... : plot "fichier" using 2:3 with lines
pour utiliser la seconde colonne comme abscisse et la troisi`eme colonne comme ordonn´ee, les points ´etant reli´es par des lignes.help plotpour toutes les options.
octaveest une version opensource de Matlab et en reprend toutes les syntaxes. Seule fonctionnalit´e nouvelle qui nous sera utile ici : octavepeut lire des donn´ees au format hexad´ecimal :
f=fopen("fichier","r");d=fscanf("%x");fclose(d);
La variabledcontient alors les informations qui ´etaient stock´ees dans le fichierfichierau format hexad´ecimal.
Si le fichier contenaitNlignes, les donn´ees sont lues par colonne et les informations d’une colonne donn´ee d’ob- tiennent par d(1:N:length(d)).
4. Pour une description plus exaustive des fonctionnalit´es degnuplotetoctave, on pourra consulterhttp://jmfriedt.free.
fr/lm_octave.pdf.
>22µ100n
carte TP MSP430 2009
RS232-USB
analog IN
32 kHz
JTAG BCD-7seg
buzzer
1
corrige 18/08/09
E L E C T R O N I C S
1 2 3 4 5 6 7 8
12 34
12 34 12 34
1 2
1 8
1
1
1
5
C1 C2
C3 Q1
C4
C5 JP1C6 C7
IC1
R3 D1
X1
R5
C9
LED1 LED2 LED3 LED4 LED5 LED6 LED7 LED8
S1
LEDALIM BUZZER
S2
S3 S4
IC2
X2
RESMES1
C10
JP2JP3
IC3
IC4 JP5
DIS1DIS2 SV2
RN2
RN1
R6 R8 R9
R10 R11 R12 R25
R26 R27
R28 R29 R30
R31
R32
R33
R1
R2
R34
R21
R22
R4
R23
R13 R14 R15 R16 R17 R18 R19 R20
R24
IC6 SV3
Q3
C12
C13
C14
IC5
R7 IC7
R35 R36
R37
R38 R39
R40
R41
R42
JP4
JP6 JP7 100n
1n 1n FT232RL
2k 2k
100n
F/TMB
RACON12
RACON12 RACON12
LE33CZ
GMSTBA2
5_Ohms 74HC245DW74HC245DW
HD-H103HD-H103
10k 10k 10k
10k 10k 10k 10k
10k 10k
10k 10k 10k
10k10k
10k
10k
3k
10k 10k10k
4k7
10k
10k 10k 10k 10k 10k 10k 10k 10k
10k
74LS47N
100n
100n
100n
F147
OP11D
Routage de la face sup´erieure et implantation des composants
>22µ100n
SD
E L E C T R O N I C S
1 2 3 4 5 6 7 8
12 34
12 34 12 34
1 2
1 8
1
1
1
5
C1 C2
C3 Q1
C4
C5 JP1C6 C7
IC1
R3 D1
X1
R5
C9
LED1 LED2 LED3 LED4 LED5 LED6 LED7 LED8
S1
LEDALIM BUZZER
S2
S3 S4
IC2
X2
RESMES1
C10
JP2JP3
IC3
IC4 JP5
DIS1DIS2 SV2
RN2
RN1
R6 R8 R9
R10 R11 R12 R25
R26 R27
R28 R29 R30
R31
R32
R33
R1
R2
R34
R21
R22
R4
R23
R13 R14 R15 R16 R17 R18 R19 R20
R24
IC6 SV3
Q3
C12
C13
C14
IC5
R7 IC7
R35 R36
R37
R38 R39
R40
R41
R42
JP4
JP6 JP7 100n
1n 1n FT232RL
2k 2k
100n
F/TMB
RACON12
RACON12 RACON12
LE33CZ
GMSTBA2
5_Ohms 74HC245DW74HC245DW
HD-H103HD-H103
10k 10k 10k
10k 10k 10k 10k
10k 10k
10k 10k 10k
10k10k
10k
10k
3k
10k 10k10k
4k7
10k
10k 10k 10k 10k 10k 10k 10k 10k
10k
74LS47N
100n
100n
100n
F147
OP11D
Routage de la face inf´erieure et implantation des composants