Compare commits
No commits in common. "master" and "yohan" have entirely different histories.
606
README.md
|
@ -1,606 +0,0 @@
|
||||||
# Fonctionnement et descriptions des implémentations pour le projet Voilier
|
|
||||||
|
|
||||||
## Résumé des fonctionnalitées réalisées
|
|
||||||
|
|
||||||
- [x] Batterie affichée via l'UART Rx
|
|
||||||
- [x] Temps en heure et minute de la RTC affiché via l'UART Rx
|
|
||||||
- [x] Contrôle avec PWM du moteur via l'UART en Tx
|
|
||||||
- [x] Mise à une position d'origine pour la voile à l'aide du servo moteur
|
|
||||||
- [x] Si l'accéléromètre détecte un désalage, la voile est mise à 180°
|
|
||||||
|
|
||||||
*NB : La pin ayant changé entre le servomoteur et la girouette (anciennement PA0), ce dernier n'est plus fonctionnel pour le moment.*
|
|
||||||
|
|
||||||
- [ ] Changement de la position de la voile à l'aide de la position de la girouette
|
|
||||||
- [x] Incrémentation/Décrémentation de la girouette
|
|
||||||
- [ ] Changement de la position avec cette donnée
|
|
||||||
|
|
||||||
## Documents explicatifs divers
|
|
||||||
|
|
||||||
- Explication du fonctionnement de l'UART avec un Raspberry Pi 4 [ici](implementation/remote.md)
|
|
||||||
- Explication des drivers dans une [cheat sheet](driver/driver.md)
|
|
||||||
|
|
||||||
### Tableau de répartition des services
|
|
||||||
|
|
||||||
| Service | Nom | Fonction |
|
|
||||||
| --- | :-:| :-:|
|
|
||||||
|Girouette|Simon|Mesure de l'angle girouette.|
|
|
||||||
|Module Xbee|Yohan|Communication a distance.|
|
|
||||||
|IMU|Guilhem|Mesure de roulis, système anti-chavirement.|
|
|
||||||
|RTC|Alix|Horloge temp réel.|
|
|
||||||
|Mesure analogique|Yohan|Mesure de la tension de batterie.|
|
|
||||||
|Servo moteur|Alix|Controle de l'écoute des voiles.|
|
|
||||||
|Motoréducteur|Alix|Rotation du plateau.|
|
|
||||||
|
|
||||||
### Tableau de répartition des périphériques
|
|
||||||
|
|
||||||
| Service | Nom | Designation| Périphériques Timer| Channel Timer|Périphériques GPIOX|
|
|
||||||
| --- | :-: | :-: | :-: | :-: | :-: |
|
|
||||||
|Girouette|Simon|NC|Timer-4 1MHz| 0 |PB6 PB7 PA0|
|
|
||||||
|Module Xbee|Yohan|UART|NC| NC |PA9 PA10|
|
|
||||||
|IMU|Guilhem|SPI|NC| NC |PA4 PA5 PB10 PB11|
|
|
||||||
|RTC|Alix|I2C|NC| NC |PB12 PB13 PB14 PB15|
|
|
||||||
|Mesure analogique|Yohan|NC|Timer-5 1Hz| 10 |PC0|
|
|
||||||
|Servo moteur|Alix|PWM|Timer-2 50Hz | 2 |PA1|
|
|
||||||
|Motoréducteur|Alix|NC|Timer-3 50KHz| 3 |PB0|
|
|
||||||
___
|
|
||||||
## Motoréducteur
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Le motoréducteur se contrôle via 2 broches, une où est transmise une PWM de plus de 20kHz avec un rapport cyclique de 0% à 100% afin de contrôler la vitesse de rotation du plateau et une afin de changer la direction de rotation du plateau.
|
|
||||||
|
|
||||||
*Cette implémentation utiliser les drivers Timer et GPIO faient durant le projet*
|
|
||||||
|
|
||||||
##### Calculs préliminaires
|
|
||||||
|
|
||||||
Le driver timer demande d'instancier une strcture qui contient les valeurs des futurs registres ARR et PSC. L'équation qui lie la fréquence du timer et celle du microcontrôleur est la suivante :
|
|
||||||
$$ f_{tim} = {f_µ \over ARR * PSC} $$
|
|
||||||
Sachant que la fréquence du microcontrôleur est de 72 MHz et que l'o souhaite une fréquence de 20 kHz, on peut facilement calculer les registres ARR et PSC.
|
|
||||||
$$ ARR * PSC = {f_µ \over f_{tim}} = {72000000 \over 20000} = 3600 $$
|
|
||||||
Comme on peut le voir dans la documentation, les registres sont sur 16 bits et peuvent donc avoir une valeur maximale de 65536.
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
Nous allons donc choisir de mettre ARR à 3599 (le registre compte à partir de 0) et PSC à 0, ce qui va à moindre échelle éviter au passage quelques calculs non nécessaire au microcontrôleur.
|
|
||||||
*Il faudra donc ensuite prévoir de gérer le rapport cyclique seulement entre 0 et 3599*
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
Il y a d'abord deux defines qui vont être utilisés pour simplifier la fonction de changement du sens de rotation :
|
|
||||||
```c
|
|
||||||
#define HORAIRE 0x1
|
|
||||||
#define ANTIHOR 0x0
|
|
||||||
```
|
|
||||||
|
|
||||||
3 fonctions ont été instanciées dans le fichier motoreducteur.h :
|
|
||||||
```c
|
|
||||||
void MyMotor_Init(void);
|
|
||||||
void MyMotor_ChangeSpeed(unsigned int DC);
|
|
||||||
void MyMotor_ChangeDirection(uint8_t Sens);
|
|
||||||
```
|
|
||||||
|
|
||||||
**void MyMotor_Init(void)**
|
|
||||||
```c
|
|
||||||
MyTimer_Struct_Typedef Timer;
|
|
||||||
MyGPIO_Struct_TypeDef Pin_Direction;
|
|
||||||
|
|
||||||
Timer.Timer = TIM3;
|
|
||||||
Timer.ARR = 3599;
|
|
||||||
Timer.PSC = 0;
|
|
||||||
|
|
||||||
Pin_Direction.GPIO = GPIOB;
|
|
||||||
Pin_Direction.GPIO_Pin = 1;
|
|
||||||
Pin_Direction.GPIO_Conf = Out_PullUp;
|
|
||||||
|
|
||||||
MyTimer_Base_Init(&Timer);
|
|
||||||
MyGPIO_Init(&Pin_Direction);
|
|
||||||
|
|
||||||
MyTimer_PWM(TIM3, 3);
|
|
||||||
MyTimer_DutyCycle(TIM3, 3, 0);
|
|
||||||
|
|
||||||
MyTimer_Base_Start(Timer);
|
|
||||||
MyMotor_ChangeDirection(ANTIHOR);
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyMotor_Init initialise le timer qu'elle va utiliser pour produire une PWM de fréquence 50 kHz puis initiliaser la broche sur laquelle va être transmise le sens de rotation voulu du plateau. Elle va ensuite démarrer le timer.
|
|
||||||
|
|
||||||
**void MyMotor_ChangeSpeed(unsigned int DC)**
|
|
||||||
```c
|
|
||||||
MyTimer_DutyCycle(TIM3, 3, DC);
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyMotor_ChangeSpeed sert principalement a avoir un meilleure nom et respecter le nommage des fonctions de cette implémentation, elle change la valeur du rapport cyclique du timer concerné (la valeur doit être comprise entre 0 et 10000).
|
|
||||||
|
|
||||||
**void MyMotor_ChangeDirection(uint8_t Sens)**
|
|
||||||
```c
|
|
||||||
if (Sens == HORAIRE)
|
|
||||||
MyGPIO_Set(GPIOB, 1);
|
|
||||||
if (Sens == ANTIHOR)
|
|
||||||
MyGpio_Reset(GPIOB, 1);
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyMotor_ChangeDirection met à un la broche qui gère la direction du plateau si le sens choisi est horaire et met à 0 si le sens choisi est antihoraire.
|
|
||||||
|
|
||||||
#### Test de l'implémentation
|
|
||||||
|
|
||||||
Le motoréducteur a été testé en simulation (vérification des registres, de l'avancement des timers, des signaux de PB1 et du channel 3 du timer 3) ansi que sur maquette en essayant des valeurs dans le code puis en connectant à l'implémentation de la télécommande.
|
|
||||||
|
|
||||||
En testant, nous nous sommes rendu compte qu'entre 0 et 1000, le moteur ne tournait pas car il n'avait pas assez de puissance.
|
|
||||||
|
|
||||||
|
|
||||||
___
|
|
||||||
## Servomoteur
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Le servomoteur se contrôle via 1 broches où est transmise une PWM de période de 20 ms avec un rapport cyclique de 5% à 10% afin de contrôler l'angle de l'axe du servomoteur.
|
|
||||||
|
|
||||||
*Cette implémentation utiliser le driver Timer fait durant le projet*
|
|
||||||
|
|
||||||
##### Calculs préliminaires
|
|
||||||
|
|
||||||
Le driver timer demande d'instancier une strcture qui contient les valeurs des futurs registres ARR et PSC. L'équation qui lie la fréquence du timer et celle du microcontrôleur est la suivante :
|
|
||||||
$$ f_{tim} = {f_µ \over ARR * PSC} $$
|
|
||||||
Sachant que la fréquence du microcontrôleur est de 72 MHz et que l'o souhaite une fréquence de 20 kHz, on peut facilement calculer les registres ARR et PSC.
|
|
||||||
$$ ARR * PSC = {f_µ \over f_{tim}} = {72000000 \over 50} = 1440000 $$
|
|
||||||
Comme on peut le voir dans la documentation, les registres sont sur 16 bits et peuvent donc avoir une valeur maximale de 65536.
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
Nous allons donc choisir de mettre ARR à 3599 car il faut pouvoir gérer 180° possibles sur une seule des 20 ms de la période du timer (180 * 20 = 3600) et PSC à 399 pour avoir le division de 3600 * 499 = 1440000.
|
|
||||||
*Il faudra donc ensuite prévoir de gérer le rapport cyclique seulement entre 0 et 3599*
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
2 fonctions ont été instanciées dans le fichier servo.h :
|
|
||||||
```c
|
|
||||||
void MyServo_Init(void);
|
|
||||||
void MyServo_ChangeAngle(uint8_t Angle);
|
|
||||||
```
|
|
||||||
|
|
||||||
**void MyServo_Init(void)**
|
|
||||||
```c
|
|
||||||
MyTimer_Struct_Typedef Timer;
|
|
||||||
|
|
||||||
//Période de 20ms -> F de 50Hz
|
|
||||||
Timer.Timer = TIM2;
|
|
||||||
Timer.ARR = 3599; //20*180 (angle) = 3600
|
|
||||||
Timer.PSC = 399; //72Mhz / 50Hz = 1.44Mhz et 3600*400 = 1.44M
|
|
||||||
|
|
||||||
MyTimer_Base_Init(&Timer);
|
|
||||||
|
|
||||||
//Pin Timer 2 Channel 1 PA0
|
|
||||||
MyTimer_PWM(TIM2, 1);
|
|
||||||
MyTimer_DutyCycle(TIM2, 1, 750);
|
|
||||||
|
|
||||||
MyTimer_Base_Start(Timer);
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyServo_Init initialise le timer qu'elle va utiliser pour produire une PWM de fréquence 50 Hz puis met une valeur arbitraire qui sera testée sur maquette au rapport cyclique et démarre le timer.
|
|
||||||
|
|
||||||
**void MyServo_ChangeAngle(uint8_t Angle)**
|
|
||||||
```c
|
|
||||||
if (Angle > 180)
|
|
||||||
Angle = 180;
|
|
||||||
|
|
||||||
int DC = 500 + (Angle * 500 / 180);
|
|
||||||
|
|
||||||
MyTimer_DutyCycle(TIM2, 1, DC);
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyServo_ChangeAngle reçoit en paramètre l'angle souhaité pour le servomoteur et la fonction teste si ce dernier dépasse 180° (angle maximum de rotation du servomoteur) avant de calculer la valeur correspondante entre 5% et 10% du rapport cyclique et l'appliquer au timer.
|
|
||||||
|
|
||||||
#### Test de l'implémentation
|
|
||||||
|
|
||||||
Le servomoteur a été testé en simulation (vérification des registres, de l'avancement des timers et du channel 1 du timer 2) ansi que sur maquette en essayant des valeurs entre 0 et 180°.
|
|
||||||
|
|
||||||
Les tests ont permis de mettre en valeur le fait que la voile est complètement lache à 0° et tendu à 180°.
|
|
||||||
|
|
||||||
|
|
||||||
___
|
|
||||||
## Télécommande
|
|
||||||
|
|
||||||
La télécommande permet deux choses via l'IHM :
|
|
||||||
- Transmettre la vitesse de rotation demandé et le sens pour le voilier
|
|
||||||
- Afficher le niveau de batterie actuel ainsi que le temps en heures et minutes
|
|
||||||
|
|
||||||
*Cette implémentation utilise le driver UART qui a été tout d'abord réalisé par Guilhem et modifié par la suite par Yohan pour corriger d'eventuels bugs et produire un driver adapté au besoin.*
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
3 fonctions ont été instanciées dans le fichier remote.h :
|
|
||||||
```c
|
|
||||||
void remote(uint8_t data);
|
|
||||||
void initRemote(void);
|
|
||||||
void testRemote(void);
|
|
||||||
```
|
|
||||||
|
|
||||||
**Structure de donnée MyUART**
|
|
||||||
```c
|
|
||||||
MyUART_Struct_Typedef uartCool = {USART1,9600,lengthBit8,parityNone,stopBit1};
|
|
||||||
```
|
|
||||||
Cette structure contient les informations sur quel UART va être utilisé, son baudrate ainsi que des paramètres pour la transmission (longueur de la donnée, parité et nombre de bits de stop).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**void remote(uint8_t data)**
|
|
||||||
```c
|
|
||||||
MyUART_Send(&uartCool,data);
|
|
||||||
int8_t signedData = (int8_t)data;
|
|
||||||
if(signedData >= 0)
|
|
||||||
{
|
|
||||||
MyMotor_ChangeDirection(HORAIRE);
|
|
||||||
MyMotor_ChangeSpeed(signedData*100);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MyMotor_ChangeDirection(ANTIHOR);
|
|
||||||
MyMotor_ChangeSpeed((-signedData)*100);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction remote attend la réception d'une donnée de la télécommande (la valeur de la vitesse et le sens de rotation voulu du plateau) puis utilise l'implémentation motoreducteur afin de contrôler la rotation du voilier.
|
|
||||||
|
|
||||||
**void initRemote(void)**
|
|
||||||
```c
|
|
||||||
MyUART_InitGPIO(&uartCool);
|
|
||||||
MyUART_Init(&uartCool);
|
|
||||||
MyUART_Init_Periph(remote);
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction initRemote initialise l'UART qui va être utilisé afin de communiquer avec la télécommande du projet voilier. Elle initialiser donc les broches, puis les registres et enfin déclare la fonction remote comme la nouvelle *Interrupt request handler* de ce timer. A noter que la variable **uartCool** est globale et elle sera externalisée pour être utilisée par la suite sur plusieurs autres implémentations.
|
|
||||||
|
|
||||||
**void testRemote(void)**
|
|
||||||
```c
|
|
||||||
MyUART_Send(&uartCool,'s');
|
|
||||||
MyUART_Send(&uartCool,'a');
|
|
||||||
MyUART_Send(&uartCool,'l');
|
|
||||||
MyUART_Send(&uartCool,'u');
|
|
||||||
MyUART_Send(&uartCool,'t');
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction testRemote est inutilisé mais nous a permis de savoir pendant un temps si l'UART était bien fonctionnel. Aujourd'hui une nouvelle fonction permettant l'envoi d'une chaîne de caractère a été réalisé. A la demande du projet, la taille est demandée comme argument de fonction :
|
|
||||||
**int MyUART_SendArray(MyUART_Struct_Typedef *UART, uint8_t * data, int dataLength)**
|
|
||||||
```c
|
|
||||||
int i;
|
|
||||||
for(i=0; i<dataLength; i++)
|
|
||||||
{
|
|
||||||
UART->UART->DR = data[i];
|
|
||||||
while (!(UART->UART->SR & USART_SR_TXE));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
```
|
|
||||||
|
|
||||||
Ici, pour une chaîne donnée, on envoie chacune des données de la même manière que MyUART_Send, mais plus complet. Une fonction prenant comme argument un **const char \*** aurait pu lui aussi être utilisé.
|
|
||||||
|
|
||||||
#### Test de l'implémentation
|
|
||||||
|
|
||||||
Le fonctionnement de la télécommande et la réception de la donnée de vitesse et rotation du plateau à d'abord été testée en déboguage afin de connapitre le format de cette donnée. Les tests suivant sur maquette ont permis de vérifier le bon envoi de données ainsi que la réception de la commande et son application au plateau.
|
|
||||||
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
## Real Time Clock
|
|
||||||
|
|
||||||
La real time clock est un composant sur la carte du voilier qui permet de garder en mémoire le temps qui s'écoule précisément.
|
|
||||||
|
|
||||||
*Cette implémentation utiliser le driver I2C founit durant le projet*
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
2 fonctions ont été instanciées dans le fichier rtc.h :
|
|
||||||
```c
|
|
||||||
void MyRTC_Init(void);
|
|
||||||
void MyRTC_GetTime(int* sec, int* min, int* hour, int* day, int* date, int* month, int* year);
|
|
||||||
```
|
|
||||||
|
|
||||||
**void MyRTC_Init(void)**
|
|
||||||
```c
|
|
||||||
MyI2C_Init(I2C2, 15, IT_I2C_Err);
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyRTC_Init utilise la librarie founie I2C afin d'initialiser l'I2C 2 du microcontrôleur et demande une priorité minimale à son interruption (cela ne pose pas de problème de ne pas avoir l'heure).
|
|
||||||
|
|
||||||
**void MyRTC_GetTime(int* sec, int* min, int* hour, int* day, int* date, int* month, int* year)**
|
|
||||||
```c
|
|
||||||
MyI2C_RecSendData_Typedef data;
|
|
||||||
char regCopy = 0;
|
|
||||||
|
|
||||||
data.SlaveAdress7bits = 0x68;
|
|
||||||
data.Ptr_Data = ®Copy;
|
|
||||||
data.Nb_Data = 1;
|
|
||||||
|
|
||||||
MyI2C_GetString(I2C2, 0x00, &data);
|
|
||||||
*sec = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
|
|
||||||
MyI2C_GetString(I2C2, 0x01, &data);
|
|
||||||
*min = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
|
|
||||||
MyI2C_GetString(I2C2, 0x02, &data);
|
|
||||||
*hour = 0;
|
|
||||||
MyI2C_GetString(I2C2, 0x03, &data);
|
|
||||||
*day = (regCopy & 0x07);
|
|
||||||
MyI2C_GetString(I2C2, 0x04, &data);
|
|
||||||
*date = ((regCopy >> 4) & 0x03) * 10 + (regCopy & 0x0F);
|
|
||||||
MyI2C_GetString(I2C2, 0x05, &data);
|
|
||||||
*month = ((regCopy >> 4) & 0x01) * 10 + (regCopy & 0x0F);
|
|
||||||
MyI2C_GetString(I2C2, 0x06, &data);
|
|
||||||
*year = ((regCopy >> 4) & 0xF0) * 10 + (regCopy & 0x0F) + 2000;
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyRTC_GetTime instancie une structure de donnée I2C en fournissant l'adresse esclave du composant RTC, l'adresse de la variable qui va contenir les données reçu mais également le nombre d'octet à recevoir.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Elle va ensuite utilisé le driver SPI pour lire les regsitres de l'adresse 0x00 à 0x06 (en 7 fois donc) et lire les secondes, minutes, heures, jour, date, mois et années puis les écrires dans les variables contenu par les pointeurs fournis en paramètres à la fonction.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
#### Test de l'implémentation
|
|
||||||
|
|
||||||
Un simple affichage du contenu des variables après l'appel à cette fonction en mode déboguage à permis de vérifier que l'implémentation rtc fonctionne bien.
|
|
||||||
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
## Accéléromètre
|
|
||||||
|
|
||||||
L'accéléromètre est un composant qui est sur la carte du voilier et qui permet de connaître la position angulaire de ce dernier dans l'espace via de la lecture dans les regsitres à l'aide du SPI.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
*Cette implémentation utiliser le driver SPI founit durant le projet*
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
2 fonctions ont été instanciées dans le fichier accelerometer.h :
|
|
||||||
```c
|
|
||||||
void Init_accelerometre(void);
|
|
||||||
void Lecture_accelerometre(float *GX, float* GY, float* GZ);
|
|
||||||
```
|
|
||||||
|
|
||||||
**void Init_accelerometre(void)**
|
|
||||||
```c
|
|
||||||
MySPI_Init(SPI1);
|
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
|
||||||
MySPI_Send(0x2D);//Registre Auto_sleep + Write + measure a 1
|
|
||||||
MySPI_Send(0x08);// d<>sactive
|
|
||||||
MySPI_Set_NSS();//CS HIGH
|
|
||||||
/*
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
|
||||||
MySPI_Send(0xAD);// regisstre 0x2D en lecture
|
|
||||||
testReg = MySPI_Read(); // lecture de la valeur du registre
|
|
||||||
MySPI_Set_NSS();//CS HIGH
|
|
||||||
*/
|
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
|
||||||
MySPI_Send(0X2C);//Registre power consuption + Write
|
|
||||||
MySPI_Send(0X1A);//Param<61>trage hors low consumption + 100Hz output data rate
|
|
||||||
MySPI_Set_NSS();//CS HIGH
|
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
|
||||||
MySPI_Send(0x31);//registre Data format + write
|
|
||||||
MySPI_Send(0x17);//
|
|
||||||
MySPI_Set_NSS();//CS HIGH
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction Init_accelerometre utiliser d'abord la librarie SPI founit afin d'initialiser le SPI 1.
|
|
||||||
Elle paramètre ensuite l'accéléromètre comme souhaité pour désactiver le mode auto sleep, utiliser le mode de faible consommation et formater les données qui vont être ensuite lues.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
**void Lecture_accelerometre(float* GX, float* GY, float* GZ)**
|
|
||||||
```c
|
|
||||||
int16_t dataX ;
|
|
||||||
int16_t dataY ;
|
|
||||||
int16_t dataZ ;
|
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
|
||||||
|
|
||||||
MySPI_Send(0xF2);//lecture 1er registre acc<63>l<EFBFBD>rom<6F>tre + lecture multibytes
|
|
||||||
dataX = MySPI_Read()<<8; // donn<EFBFBD>es sur 13 (12 data + sign) bits passage 8 bit en PF
|
|
||||||
dataX |= MySPI_Read(); //lecture SPI
|
|
||||||
dataX &= 0x1FFF; //masquage au dessus du bit 13
|
|
||||||
if (dataX > 511)
|
|
||||||
{
|
|
||||||
dataX -= 1024;
|
|
||||||
}
|
|
||||||
*GX = dataX*0.004;//valeur du registre x pas accelerometre
|
|
||||||
|
|
||||||
dataY = MySPI_Read()<<8;
|
|
||||||
dataY |= MySPI_Read();
|
|
||||||
dataY &= 0x1FFF;
|
|
||||||
if (dataY > 511)
|
|
||||||
{
|
|
||||||
dataY -= 1024;
|
|
||||||
}
|
|
||||||
*GY = dataY*0.004;//valeur du registre x pas accelerometre
|
|
||||||
|
|
||||||
dataZ = ((MySPI_Read()<<8)|MySPI_Read());
|
|
||||||
dataZ &= 0x1FFF;
|
|
||||||
/* if (dataZ > 511)
|
|
||||||
{
|
|
||||||
dataZ -= 1024;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
*GZ = dataZ*0.004;//valeur du registre x pas accelerometre
|
|
||||||
|
|
||||||
MySPI_Set_NSS();//CS HIGH
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction Lecture_accelerometre renvoie dans des variables pointé en paramètres les valeurs de la force en X, en Y et en Z.
|
|
||||||
Le fonctionnement est comme suis :
|
|
||||||
- Envoi de l'adresse du resgistre désiré
|
|
||||||
- Lecture et mise dans une variable locale de la valeur du regsitre
|
|
||||||
- Masque et calcul afin de formater la données à renvoyer
|
|
||||||
|
|
||||||
Ces trois étapes sont faites pour fournir en X, Y et Z la gravité (donc ensuite l'angle) que chaque axe perçoit.
|
|
||||||
|
|
||||||
#### Test de l'implémentation
|
|
||||||
|
|
||||||
l'implémenation a été testée en mode débogage afion de savoir dans un premier temps si les données sont bien reçues puis dans un second temps des calculs ont été faits afin de vérifier si les données sont correctes.
|
|
||||||
Des test sur maquette sont en cours...
|
|
||||||
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
## Batterie
|
|
||||||
|
|
||||||
L'implémentation batterie va permettre de savoir si la tension de la batterie intégrée au projet voilier à une tension suffisante au bon fonctionnement du système et d'envoyer ensuite cette donnée vers l'UART connecté à la télécommande.
|
|
||||||
|
|
||||||
*Cette implémentation utiliser les drivers ADC et GPIO faient durant le projet*
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
Il y a d'abord un define qui permet de tester facilement la tension minimala acceptable pour la batterie intégré au voilier.
|
|
||||||
```c
|
|
||||||
#define MAX_BAT 1145
|
|
||||||
```
|
|
||||||
|
|
||||||
4 fonctions ont été instanciées dans le fichier battery.h :
|
|
||||||
```c
|
|
||||||
void battery(uint32_t data);
|
|
||||||
void getGauge(char gauge[], float percent);
|
|
||||||
void initBattery(void);
|
|
||||||
char isClose(uint32_t data, uint32_t compare, int precision);
|
|
||||||
```
|
|
||||||
|
|
||||||
**void battery(uint32_t data)**
|
|
||||||
```c
|
|
||||||
MyRTC_Struct_TypeDef rtcBattery;
|
|
||||||
MyRTC_GetTime(&rtcBattery);
|
|
||||||
|
|
||||||
if((actualMinutes == rtcBattery.minutes) && isClose(oldAdc,data,50)) //pas de precision/10 %
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldAdc = data;
|
|
||||||
actualMinutes = rtcBattery.minutes;
|
|
||||||
float percentBattery = ((float)data)/MAX_BAT;
|
|
||||||
char batteryBar[13]="[__________]";
|
|
||||||
char testChar[24];
|
|
||||||
|
|
||||||
getGauge(batteryBar, percentBattery);
|
|
||||||
sprintf(testChar,"[%.2d:%.2d] %s %.2d%%",rtcBattery.hours,rtcBattery.minutes,batteryBar,(int)(percentBattery*100));
|
|
||||||
MyUART_SendArray(&uartCool, (uint8_t *)testChar, 24);
|
|
||||||
|
|
||||||
MyUART_Send(&uartCool, '\n');
|
|
||||||
```
|
|
||||||
|
|
||||||
Cette dernière affiche le niveau de la batterie ainsi que les heures et les minutes de la manière suivante :
|
|
||||||
```
|
|
||||||
[19:11] [_#########] 088%
|
|
||||||
```
|
|
||||||
|
|
||||||
**void getGauge(char gauge[], float percent)**
|
|
||||||
```c
|
|
||||||
int i;
|
|
||||||
percent=percent*10;
|
|
||||||
if(percent>10)
|
|
||||||
{
|
|
||||||
percent = 10.0;
|
|
||||||
}
|
|
||||||
for(i=(10-percent)+1; i<11; i++)
|
|
||||||
{
|
|
||||||
gauge[i]='#';
|
|
||||||
}
|
|
||||||
gauge[12]='\0';
|
|
||||||
```
|
|
||||||
|
|
||||||
Cette fonction permet, en fonction d'un pourcentage de batterie donnée, de remplir la chaîne de caractère gauge avec des dièse correspondant au niveau de la batterie (max : 10)
|
|
||||||
|
|
||||||
**void initBattery(void)**
|
|
||||||
```c
|
|
||||||
MyADC_Init_Periph(battery);
|
|
||||||
MyADC_Struct_TypeDef adcBattery = {ADC1,10,cycles41d5};
|
|
||||||
MyADC_Init(&adcBattery);
|
|
||||||
MyGPIO_Struct_TypeDef gpioBattery = {GPIOC,0,In_Analog};
|
|
||||||
MyGPIO_Init(&gpioBattery);
|
|
||||||
```
|
|
||||||
|
|
||||||
initialisation de la batterie, avec les gpio associées à l'ADC, ainsi que les règlages pour l'ADC.
|
|
||||||
|
|
||||||
**char isClose(uint32_t data, uint32_t compare, int precision)**
|
|
||||||
```c
|
|
||||||
if(data < precision)
|
|
||||||
{
|
|
||||||
return !(data >= compare+precision);
|
|
||||||
}
|
|
||||||
return !((data >= compare+precision) || (data <= compare-precision));
|
|
||||||
```
|
|
||||||
|
|
||||||
Fonction pour tester si l'adc détecte une forte augmentation ou diminution de l'adc. data correspond à la donnée actuelle, et compare à la donnée précédente. La precision correspond à un pas permettant de vérifier cette dite augmentation. Par exemple si la tension chute de 50 unités et que la précision est de 40, alors la fonction renverra 0. Sinon 1.
|
|
||||||
|
|
||||||
#### Test de l'implémentation
|
|
||||||
|
|
||||||
Des test sur maquette ont été dans un premier temps faits pour vérifier que l'ADC renvoyé une valeur correcte (changeante en fonction de la tension d'une alimentation émulant la batterie).
|
|
||||||
Des test sur maquette sont en cours...
|
|
||||||
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
## Girouette
|
|
||||||
|
|
||||||
|
|
||||||
*Cette implémentation utiliser les drivers Timer et GPIO faient durant le projet*
|
|
||||||
|
|
||||||
___
|
|
||||||
|
|
||||||
3 fonctions ont été instanciées dans le fichier girouette.h :
|
|
||||||
```c
|
|
||||||
int MyGirouette_Angle(TIM_TypeDef *TIMX);
|
|
||||||
void MyGirouette_Init(TIM_TypeDef *TIMX);
|
|
||||||
void MyGirouette_Init_IT_Z(uint8_t GPIO_Pin);
|
|
||||||
```
|
|
||||||
|
|
||||||
**void MyGirouette_Init(TIM_TypeDef* TIMX)**
|
|
||||||
```c
|
|
||||||
//configuration gpiob6 et gpiob7 en entrées In_Floating imposer par le timer4
|
|
||||||
MyGPIO_Struct_TypeDef MyGPIO={GPIOB,6,In_Floating};
|
|
||||||
MyGPIO_Init(&MyGPIO);
|
|
||||||
MyGPIO.GPIO_Pin=7;
|
|
||||||
MyGPIO_Init(&MyGPIO);
|
|
||||||
//config pa0 en entrées
|
|
||||||
MyGPIO.GPIO_Pin=0;
|
|
||||||
MyGPIO.GPIO=GPIOA;
|
|
||||||
MyGPIO_Init(&MyGPIO);
|
|
||||||
//configuration TIM4 reset a 360
|
|
||||||
MyTimer_Struct_Typedef MyTimerGirouette ={TIMX,1439,0};
|
|
||||||
MyTimer_Base_Init(&MyTimerGirouette);
|
|
||||||
|
|
||||||
TIMX->SMCR &=~0x07;
|
|
||||||
TIMX->SMCR |=TIM_SMCR_SMS_1;
|
|
||||||
TIMX->CCMR1 &=~(0xF2F2);
|
|
||||||
TIMX->CCMR1 |= TIM_CCMR1_CC1S_0;
|
|
||||||
TIMX->CCMR1 |= TIM_CCMR1_CC2S_0; //CC2S dans CCMR1 et pas CCMR2
|
|
||||||
TIMX->CCER &=~TIM_CCER_CC1P;
|
|
||||||
TIMX->CCER &=~TIM_CCER_CC2P;
|
|
||||||
TIMX->CCMR1&=~(0x0F<<4); //IC1F
|
|
||||||
TIMX->CCMR1&=~(0x0F<<12);//IC2F
|
|
||||||
TIMX->CR1 |= 1;
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyGirouette_Angle initialise d'abord les broches dont elle a besoin puis instancie une structure de timer et le paramètre en codeur incrémental.
|
|
||||||
|
|
||||||
**int MyGirouette_Angle(TIM_TypeDef* TIMX)**
|
|
||||||
```c
|
|
||||||
return (TIMX->CNT)/4;
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyGirouette_Angle retourne la valeur de l'angle de la girouette en calculant à partir du resgistre CTN du timer en codeur incrémental.
|
|
||||||
|
|
||||||
**void MyGirouette_Init_IT_Z(uint8_t GPIO_Pin)**
|
|
||||||
```c
|
|
||||||
RCC->APB2ENR |=0x01;
|
|
||||||
EXTI->IMR |= (0x01<<GPIO_Pin); // Autorisation de l'interruption de la ligne
|
|
||||||
EXTI->RTSR|= (0x01<<GPIO_Pin); // Activation du déclenchement de l'interruption sur un front montant
|
|
||||||
AFIO->EXTICR[0] &= ~(0x0000000F);// L'interruption « EXTI0 » doit être provoquée par une modification PA0
|
|
||||||
NVIC->IP[EXTI0_IRQn] |= (1 << 0x4); //Prio de l'interruption (p.197 manuel reference RM0008 pour ADC1_IRQn)
|
|
||||||
NVIC->ISER[0] |= (1 << (6 & 0x1F)); // Autorisation de l'interruption « EXTI0 » NUMERO 6,
|
|
||||||
```
|
|
||||||
|
|
||||||
La fonction MyGirouette_Init_IT_Z paramètre une interruption extérieure sur broche afin de faire fonctionner le codeur incrémental et pour récuperer les données de la girouette.
|
|
||||||
|
|
||||||
#### Test de l'implémentation
|
|
||||||
|
|
||||||
Le fonctionnement a été vérifié sur site par Simon.
|
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 4.1 KiB |
BIN
assets/ccer.png
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 24 KiB |
BIN
assets/crl.PNG
Before Width: | Height: | Size: 13 KiB |
BIN
assets/odr.png
Before Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 14 KiB |
|
@ -23,7 +23,7 @@ void MyADC_Init(MyADC_Struct_TypeDef * ADCStructPtr)
|
||||||
ADCStructPtr->ADC->SQR3 |= ADCStructPtr->channel; //Sequence Reader, seulement le SQ1 est lu dans notre cas, nous associons un channel <20> ce dernier.
|
ADCStructPtr->ADC->SQR3 |= ADCStructPtr->channel; //Sequence Reader, seulement le SQ1 est lu dans notre cas, nous associons un channel <20> ce dernier.
|
||||||
ADCStructPtr->ADC->CR2 |= ADC_CR2_EXTTRIG; //Activation du trigger externe
|
ADCStructPtr->ADC->CR2 |= ADC_CR2_EXTTRIG; //Activation du trigger externe
|
||||||
ADCStructPtr->ADC->CR2 |= ADC_CR2_EXTSEL; //Event externe choisie : SWSTART
|
ADCStructPtr->ADC->CR2 |= ADC_CR2_EXTSEL; //Event externe choisie : SWSTART
|
||||||
MyADC_ActiveIT(ADCStructPtr->ADC,2);
|
MyADC_ActiveIT(ADCStructPtr->ADC,0);
|
||||||
ADCStructPtr->ADC->CR2 |= ADC_CR2_ADON; //Init l'ADC
|
ADCStructPtr->ADC->CR2 |= ADC_CR2_ADON; //Init l'ADC
|
||||||
MyADC_Base_Start(ADCStructPtr->ADC); //Debut du premier ADC
|
MyADC_Base_Start(ADCStructPtr->ADC); //Debut du premier ADC
|
||||||
}
|
}
|
||||||
|
@ -37,13 +37,8 @@ void MyADC_ActiveIT(ADC_TypeDef * ADC, uint8_t Prio)
|
||||||
|
|
||||||
void ADC1_2_IRQHandler(void)
|
void ADC1_2_IRQHandler(void)
|
||||||
{
|
{
|
||||||
if (ADC1->SR & ADC_SR_EOC)
|
|
||||||
{
|
|
||||||
ADC1->SR &= ~ADC_SR_EOC; //Prochaine lecture pouvant <20>tre effectu<74>e.
|
|
||||||
if (pFncADC != 0)
|
if (pFncADC != 0)
|
||||||
{
|
|
||||||
(*pFncADC) (ADC1->DR); /* appel indirect de la fonction */
|
(*pFncADC) (ADC1->DR); /* appel indirect de la fonction */
|
||||||
}
|
|
||||||
MyADC_Base_Start(ADC1);
|
MyADC_Base_Start(ADC1);
|
||||||
}
|
ADC1->SR &= ~ADC_SR_EOC; //Prochaine lecture pouvant <20>tre effectu<74>e.
|
||||||
}
|
}
|
||||||
|
|
221
driver/driver.md
|
@ -1,221 +0,0 @@
|
||||||
# Driver cheat sheet
|
|
||||||
## GPIO
|
|
||||||
Ne pas oublier de toujours activer la clock pour le driver concerné. Dans le cas du GPIO il faut activer celui pour GPIO_X, le registre est dans **RCC->APBXENR**
|
|
||||||
Dans notre cas chaque GPIO est dans APB2ENR (page 112 de [Reference Manual](../assets/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf)) : Des variables sont disponibles comme *RCC_APB2ENR_IOPAEN*
|
|
||||||
|
|
||||||
---
|
|
||||||
Par la suite il faut choisir quelle pin activer dans le GPIO et en quel mode. Tout cela se passe dans le registre CR ainsi que ODR pour un GPIO Précis. ODR lui va permettre de sélectionner le pull-up/pull-down. Voici le registre :
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Pour sélectionner le mode, cela se passe dans le registre CR L/H :
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Attention pour les pins > 7 -> Il faut aller sur le registre high, donc CRH, qui suit la même logique que ce dernier, mais à la différence que celui-ci commence par le bit 8.
|
|
||||||
Il suffit donc avec tous ces registres de suivre le tableau **Figure 20** Sur les différents modes :
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
L'un des meilleurs moyens pour respecter ce dernier est donc de faire une énumération avec le configuration mode voulu. Comme ça plus besoin de chercher les bons bits. Pour les bits MODE, il suffit de mettre à 0 pour Input, et n'importe quelle autre variable pour Output.
|
|
||||||
Ensuite il faut modifier en conséquence CNF\[1:0], soit le tableau suivant :
|
|
||||||
|
|
||||||
|Configuration Name|Bits sets|
|
|
||||||
|:-:|---|
|
|
||||||
|In_Floating|0x04|
|
|
||||||
|In_PullDown|0x08|
|
|
||||||
|In_PullUp|0xF8 *(normalement 0x08, mais ici différencié)*|
|
|
||||||
|In_Analog|0x00|
|
|
||||||
|Out_PullUp|0x01|
|
|
||||||
|Out_OD|0x05|
|
|
||||||
|AltOut_Ppull|0x09|
|
|
||||||
|AltOut_OD|0x0d|
|
|
||||||
Tout ces defines doivent être décalés de 4 \* PinNumber.
|
|
||||||
|
|
||||||
---
|
|
||||||
Pour ensuite set ou reset ces pins il suffit d'utiliser les deux registres suivants :
|
|
||||||
- BSRR pour set -> 1 décalé de la pin
|
|
||||||
- BRR pour reset -> 1 décalé de la pin
|
|
||||||
Pour observer ces dernières, le registre IDR est le plus intéressant :
|
|
||||||
```c
|
|
||||||
char gpioRead = (GPIO->IDR & (0x1 << GPIO_Pin)) > 0;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Timer
|
|
||||||
Dans le cas du Timer il faut activer celui pour TIMXEN, le registre est dans **RCC->APBXENR**. Pour le timer 1 il se trouve dans APB2ENR, et pour les autres dans APB1ENR.
|
|
||||||
|
|
||||||
---
|
|
||||||
Il suffit ensuite de régler le PSC et l'ARR pour pouvoir obtenir l'horloge de notre choix sur un timer donné.
|
|
||||||
Le PSC permet de diviser la clock par un certain nombre en respectant cette formule :
|
|
||||||
|
|
||||||
```
|
|
||||||
fCKPSC/PSC+1 = fCKCNT
|
|
||||||
```
|
|
||||||
|
|
||||||
Ensuite en fonction du Time-base unit différents modes sont possible pour ARR, le registre de comptage va s'arrêter de compter à partir de cette valeur ARR. Mais le signal renvoyé par la clock, ou même le flag du timer ne répondra pas de la même manière.
|
|
||||||
Le mode par défaut est donc celui du change on reset. pour trouver la fréquence associée il nous suffit de faire :
|
|
||||||
|
|
||||||
```
|
|
||||||
fCKCNT/ARR+1 = CK_ARR
|
|
||||||
```
|
|
||||||
|
|
||||||
Au final les deux registres étant sur 16 bits, il est possible d'avoir une précision de la division à 32 bits/
|
|
||||||
|
|
||||||
## Interruption
|
|
||||||
Les interruptions doivent être activées de manières différente pour chaque module, mais cela dit il reste quelques similaritées sur le module NVIC qui doit être correctement configuré pour un module donné.
|
|
||||||
Il faut tout d'abord activer l'interruption du côté du module et ensuite modifier la table des vecteurs du NVIC.
|
|
||||||
La première est celle des prioritées, trouvable dans le [Manuel de Référence RM008](../assets/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf) page 197, la second e est l'ISER qui permet la réecriture des fonction d'IRQ trouvable dans le [Manuel de programmation PM0056](../assets/New_Programming_Manual_CortexM3.pdf) page 119.
|
|
||||||
|
|
||||||
```c
|
|
||||||
int iserRegister = 0; //A voir par rapport au manue lde reference RM008 -> emplacement de la table
|
|
||||||
uint32_t IRQNumber = GetInterruptNum(); //XXX_IRQn
|
|
||||||
NVIC->IP[IRQNumber] |= (Prio << 0x4);
|
|
||||||
NVIC->ISER[iserRegister] |= (0x1<<(IRQNumber-(32*iserRegister)));
|
|
||||||
```
|
|
||||||
Enfin, une fonction nommée XXX_IRQHandler sera appelée à l'interruption, il suffiera de réecrire cette dernière pour qu'elle soit active.
|
|
||||||
*NB : Il est important de remettre le flag d'interruption à 0 pour relancer ce dernier.*
|
|
||||||
|
|
||||||
### Timer Interruption
|
|
||||||
Le registre pour l'activation de l'interruption est dans TimerX_DIER, sur le bit 0 nommé UIE (Update Interrupt Enable).
|
|
||||||
Le flag d'interruption est UIF.
|
|
||||||
### ADC Interruption
|
|
||||||
L'adc est plus complexe que les autres car il demande des pins pour être liés à une interruption, pour activer ce dernier nous allons observer un registre en particulier, **ADC_CR2** :
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Ici quelques bits vont être mis à 1 pour permettre l'interruption, soit :
|
|
||||||
- **ADC_CR2_EXTTRIG** : active un trigger externe
|
|
||||||
- **ADC_CR2_EXTSEL** : On choisi l'event externe pour l'allumage de l'adc, par défaut SWSTART
|
|
||||||
On active ensuite l'interruption avec le bit **EOCIE** qui est présent dans le registre **CR1**.
|
|
||||||
Le flag d'intteruption est **EOC** (End of Conversion) dans le registre **SR**.
|
|
||||||
|
|
||||||
Pour relancer une conversion ou init le premier, il faut mettre à 1 dans le registre **CR2** le bit SWSTART comme ceci :
|
|
||||||
```c
|
|
||||||
ADC->CR2 |= ADC_CR2_SWSTART;
|
|
||||||
```
|
|
||||||
|
|
||||||
*NB : Il est important de faire tout ce qui est fait dans la partie ADC avant de faire les interruptions. En effet ADON sert toujours à l'initialisation mais ne servira pas pour relancer une conversion, il est remplacé par SW_START*
|
|
||||||
### UART Interruption
|
|
||||||
Le registre pour l'activation de l'interruption est dans USART_CR1, sur le bit 5 (RXNEIE pour la recepetion) et 7 (TXEIE pour la transmission).
|
|
||||||
Le flag d'intteruption est RXNE ou TXE.
|
|
||||||
|
|
||||||
## PWM
|
|
||||||
Pour activer le mode PWM il existe un registre pour chacun des timers permettant d'activer un mode pwm précis. Ce dernier est présent dans le registre CCMRx. Les bits qui nous intéresse sont OCXM. Il existe différents modes pouvant être trouvés page 414 du [Reference Manual](../assets/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf). Ici nous utiliseront le même car il est simple :
|
|
||||||
- 110 : **PWM Mode 1**, tant que TIMx_CNT < TIMx_CCRX le channel est actif.
|
|
||||||
CCMR2 possède les channels 3 et 4, et CCMR1 1 et 2. Tous sont utilisable pour chaque Timer.
|
|
||||||
|
|
||||||
---
|
|
||||||
Le CCRX (Capture/Compare Register) est un registre de 16 bit qui va déterminer pour un mode de PWM donné le moment où le timer renverra 1 ou 0. Cette variable peut être directement liée à l'ARR : ce qui permet de régler l'alpha d'un PWM directement.
|
|
||||||
|
|
||||||
Et finalement pour activer ce registre le Timer possède un registre nommé CCER
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Ce dernier permet d'activer avec CCXE le registre précedemment paramétré.
|
|
||||||
|
|
||||||
---
|
|
||||||
Une GPIO est ainsi associé à chaque PIN. Pour la retrouver il suffit de se rendre à la page 28 du [Manuel F103RB](../assets/STM32F103RB-3.pdf) et voir quelle pin est associée à quel channel de timer. Il suffit de mettre cette dernière en AltOutPpull.
|
|
||||||
|
|
||||||
## ADC
|
|
||||||
Dans le cas de l'ADC il faut activer celui pour ADCX, le registre est dans **RCC->APB2ENR**.
|
|
||||||
|
|
||||||
---
|
|
||||||
L'une des difficultés que nous pouvons rencontrer avec l'ADC est la prédivision de la clock qui doit être réalisé pour qu'une conversion soit possible. En effet la clock de base de 72 MHz fonctionne bien trop rapidement par rapport au module ADC. Ce dernier fonctionne au maxmimum à 16 MHz. Pour régler ce dernier il faut alors toucher au **RCC_CFGR**, le registre de clock configuration. Les bits qui nous intéresses sont 15 et 14 : **ADCPRE** :
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Le minimum pouvant être mis en place est donc "10" avec PCLK2 divisé par 6, ce qui donne 12 MHz
|
|
||||||
|
|
||||||
```c
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
|
||||||
RCC->CFGR |= RCC_CFGR_ADCPRE_1;
|
|
||||||
```
|
|
||||||
---
|
|
||||||
Le second registre qui nous intéressera sera **ADC_SMPRX**. Ce dernier permet de modifier pour un channel donné X, le nombre de cycle que l'adc devra réalisé pour récupérer une donnée. Une explication liée au résistance peut être faite, mais ici nous nous sommes contentés de mettre sa valeur à 41.5 cycles, soit 100.
|
|
||||||
|
|
||||||
```c
|
|
||||||
ADCStructPtr->ADC->SMPR2 |= (ADCStructPtr->cycle<<(ADCStructPtr->channel*3));
|
|
||||||
//ou pour channel > 10 :
|
|
||||||
ADCStructPtr->ADC->SMPR1 |= (ADCStructPtr->cycle<<((ADCStructPtr->channel-10)*3));
|
|
||||||
```
|
|
||||||
---
|
|
||||||
Le prochain registre est le **ADC_SQR1** : Ce dernier va nous permettre de faire un certain nombre de conversions. Ici nous ne voulons qu'une seule donc la donnée dans les bits **L** (Bits 23-20) sera *0000*.
|
|
||||||
```c
|
|
||||||
ADCStructPtr->ADC->SQR1 &= ADC_SQR1_L;
|
|
||||||
```
|
|
||||||
---
|
|
||||||
Le registre **ADC_SQR3** va par la suite nous permettre de sélectionner quel channel nous utilisons pour l'ADC. En effet après avoir changé le nombre de cycles, il faut faire comprendre au STM32 que nous voulons la donnée sur un channel précis. C'est donc aux bits SQ1(Bits 4-0) que nous mettrons un numéro de channel sur 5 bits. C'est le premier channel de conversion, il est possible dans régler d'autres par la suite, mais nous ne l'avons pas fait.
|
|
||||||
```c
|
|
||||||
ADCStructPtr->ADC->SQR3 |= channel; //avec channel de 0 à 17
|
|
||||||
```
|
|
||||||
---
|
|
||||||
Finalement, pour initialiser ou faire une une conversion analogique numérique un biot précis dans le registre **ADC_CR2** doit être mis à 1.
|
|
||||||
Ce dernier est ADON et permet dans un premier temps d'initialiser l'ADC, et dans un second, de faire une conversion quelconque, il est donc préférable de l'utiliser en tant que MACRO :
|
|
||||||
```c
|
|
||||||
ADCStructPtr->ADC->CR2 |= ADC_CR2_ADON;
|
|
||||||
//utilisation en macro :
|
|
||||||
#define MyADC_Start(ADC) (ADC->CR2 |= ADC_CR2_ADON)
|
|
||||||
```
|
|
||||||
|
|
||||||
## UART
|
|
||||||
Dans le cas de l'UART il faut activer celui pour USARTXEN, le registre est dans **RCC->APBXENR**. Pour l'USART 1 il se trouve dans APB2ENR, et pour les autres dans APB1ENR.
|
|
||||||
|
|
||||||
---
|
|
||||||
Après cela il suffit de régler le registre BRR. C'est un registre de 16 bits qui permet de calculer le baud rate. Il existe une méthode de calcul avec le chiffre après la virgule mais il est ici inutile de l'utiliser. Il suffit de faire :
|
|
||||||
|
|
||||||
```
|
|
||||||
BRR=f_CLK/BaudRate
|
|
||||||
```
|
|
||||||
|
|
||||||
A noter que le f_CLK est différent en fonction de l'U(S)ART choisi. Ici nous avons retenu que :
|
|
||||||
|
|
||||||
|UART Channel|f_CLK|
|
|
||||||
|:-:|---|
|
|
||||||
|1|72 MHz|
|
|
||||||
|2|36 MHz|
|
|
||||||
|3|36 MHz|
|
|
||||||
|
|
||||||
*Ces données sont trouvables dans le schéma de câblage des UARTs*
|
|
||||||
|
|
||||||
---
|
|
||||||
Par la suite il faut régler le mode de l'UART, pour cela nous allons nous concentrer sur deux registres :
|
|
||||||
|
|
||||||
|Registre|Fonctions|
|
|
||||||
|:-:|:--|
|
|
||||||
|CR1|Enable, Taille, Parité, RxD/TxD Enable, Interruption|
|
|
||||||
|CR2|Bits de stop|
|
|
||||||
|
|
||||||
Voici le registre CR1 de l'UART et quels bits modifier pour chacune des fonctions voulues :
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Les registres qui nous intéresse sont donc les suivants :
|
|
||||||
- **UE** : USART Enable, à activer dès le début
|
|
||||||
- **M** : Taille de la donnée, 0->8 bits, 1->9 bits
|
|
||||||
- **PCE** et **PS** : PCE active ou non la parité. Si PCE=1, alors PS détermine le type de parité : 0 pour paire, 1 pour impaire.
|
|
||||||
- **TE** et **RE** : Activation de la transmission et de la reception
|
|
||||||
- **RXNEIE** : Activation de l'interruption pour la reception
|
|
||||||
Pour CR2 tout ce qui nous intéresse sont les bits **STOP** (12 et 13):
|
|
||||||
|
|
||||||
|STOP \[1:0]|Stop bit|
|
|
||||||
|:-:|---|
|
|
||||||
|00|1|
|
|
||||||
|01|0.5|
|
|
||||||
|10|1.5|
|
|
||||||
|11|2|
|
|
||||||
|
|
||||||
---
|
|
||||||
Pour la reception ou la transmission des bits sont associés pour savoir si le uC a bien envoyé ou reçu une donnée depuis le TR/RR (TxD Register, RxD Register) vers le Data Register, Ils sont tous présents dans le SR (Status Register) :
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
- RXNE détermine qu'une donnée est reçue si ce bit est à 1. Après lecture de la donnée dans le DR(Data Register), il faut forcer ce dernier à 0 pour le reset
|
|
||||||
- TXE permet de savoir si le registre TR est vide (ce qui veut dire que la donnée a bien été envoyée).
|
|
||||||
- TC permet de savoir si le dernier bit de stop a bien été mis dans le TR.
|
|
||||||
*NB : Il est préférable d'utiliser TXE pour l'envoi de donnée.
|
|
||||||
Ces trois bits fonctionnent aussi en interruption*
|
|
||||||
|
|
||||||
---
|
|
||||||
Une GPIO est ainsi associé à chaque PIN. Pour la retrouver il suffit de se rendre à la page 28 du [Manuel F103RB](../assets/STM32F103RB-3.pdf) et voir quelle pin est associée à quel USART Tx/Rx. Par la suite il est conseillé de mettre les différentes pins dans ces modes :
|
|
||||||
- RXD : In Floating/In Pull up (pour un RaspberryPi par exemple)
|
|
||||||
- TXD : AltOut Push Pull
|
|
|
@ -26,7 +26,7 @@ void MyTimer_Base_Init(MyTimer_Struct_Typedef * Timer) {
|
||||||
|
|
||||||
void MyTimer_ActiveIT(TIM_TypeDef * Timer, char Prio, void (*IT_function) (void)) {
|
void MyTimer_ActiveIT(TIM_TypeDef * Timer, char Prio, void (*IT_function) (void)) {
|
||||||
Timer->DIER |= TIM_DIER_UIE;
|
Timer->DIER |= TIM_DIER_UIE;
|
||||||
if (Timer == TIM1) {
|
if (Timer == TIM2) {
|
||||||
NVIC_EnableIRQ(TIM1_BRK_IRQn);
|
NVIC_EnableIRQ(TIM1_BRK_IRQn);
|
||||||
NVIC_SetPriority(TIM1_BRK_IRQn, Prio);
|
NVIC_SetPriority(TIM1_BRK_IRQn, Prio);
|
||||||
IT_Tim1 = IT_function;
|
IT_Tim1 = IT_function;
|
||||||
|
@ -48,33 +48,6 @@ void MyTimer_ActiveIT(TIM_TypeDef * Timer, char Prio, void (*IT_function) (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGPIO_Struct_TypeDef GPIOFromPWM(TIM_TypeDef * Timer, int channel)
|
|
||||||
{
|
|
||||||
//use of C99 compound literal for return statement, may not work on C90.
|
|
||||||
if(Timer == TIM2)
|
|
||||||
{
|
|
||||||
//PA0 -> TIM2,CH1... iteration
|
|
||||||
return (MyGPIO_Struct_TypeDef){GPIOA,channel-1,AltOut_Ppull};
|
|
||||||
}
|
|
||||||
else if(Timer == TIM3)
|
|
||||||
{
|
|
||||||
if(channel > 2) {
|
|
||||||
return (MyGPIO_Struct_TypeDef){GPIOB,channel-3,AltOut_Ppull}; //PB0 -> TIM3,CH3;PB1 -> TIM3,CH4
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (MyGPIO_Struct_TypeDef){GPIOA,channel+5,AltOut_Ppull}; //PA6 -> TIM3,CH1;PA7 -> TIM3,CH2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(Timer == TIM4)
|
|
||||||
{
|
|
||||||
return (MyGPIO_Struct_TypeDef){GPIOB,channel+5,AltOut_Ppull}; //PB6 -> TIM4,CH1... iteration
|
|
||||||
}
|
|
||||||
else { //TIM1 case
|
|
||||||
return (MyGPIO_Struct_TypeDef){GPIOA,channel+7,AltOut_Ppull};//PA8 -> TIM1,CH1... iteration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TIM1_IRQHandler(void) {
|
void TIM1_IRQHandler(void) {
|
||||||
TIM1->SR &= ~TIM_SR_UIF;
|
TIM1->SR &= ~TIM_SR_UIF;
|
||||||
(*IT_Tim1)();
|
(*IT_Tim1)();
|
||||||
|
|
|
@ -80,7 +80,7 @@ void MyUART_Init(MyUART_Struct_Typedef * UARTStructPtr){
|
||||||
}
|
}
|
||||||
//TxD Enable, RxD Enable, USART Global Enable
|
//TxD Enable, RxD Enable, USART Global Enable
|
||||||
UARTStructPtr->UART->CR1 |= (USART_CR1_TE | USART_CR1_RE);
|
UARTStructPtr->UART->CR1 |= (USART_CR1_TE | USART_CR1_RE);
|
||||||
MyUART_ActiveIT(UARTStructPtr->UART,3);
|
MyUART_ActiveIT(UARTStructPtr->UART,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyUART_InitGPIO(MyUART_Struct_Typedef * UARTStructPtr)
|
void MyUART_InitGPIO(MyUART_Struct_Typedef * UARTStructPtr)
|
||||||
|
|
|
@ -3,69 +3,55 @@
|
||||||
#include "MySPI.h"
|
#include "MySPI.h"
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
|
|
||||||
void Init_accelerometre(void)
|
void accelerometre(void)
|
||||||
{
|
{
|
||||||
//char testReg;
|
int dataX ;
|
||||||
|
float GX ;
|
||||||
|
int dataY ;
|
||||||
|
float GY;
|
||||||
|
int dataZ ;
|
||||||
|
float GZ;
|
||||||
|
|
||||||
|
char testReg;
|
||||||
MySPI_Init(SPI1);
|
MySPI_Init(SPI1);
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
MySPI_Clear_NSS(); //CS LOW
|
||||||
MySPI_Send(0x2D);//Registre Auto_sleep + Write + measure a 1
|
MySPI_Send(0x2D);//Registre Auto_sleep + Write + measure a 1
|
||||||
MySPI_Send(0x08);// d<EFBFBD>sactive
|
MySPI_Send(0x08);// désactive
|
||||||
MySPI_Set_NSS();//CS HIGH
|
MySPI_Set_NSS();//CS HIGH
|
||||||
/*
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
MySPI_Clear_NSS(); //CS LOW
|
||||||
MySPI_Send(0xAD);// regisstre 0x2D en lecture
|
MySPI_Send(0xAD);// regisstre 0x2D en lecture
|
||||||
testReg = MySPI_Read(); // lecture de la valeur du registre
|
testReg = MySPI_Read(); // lecture de la valeur du registre
|
||||||
MySPI_Set_NSS();//CS HIGH
|
MySPI_Set_NSS();//CS HIGH
|
||||||
*/
|
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
MySPI_Clear_NSS(); //CS LOW
|
||||||
MySPI_Send(0X2C);//Registre power consuption + Write
|
MySPI_Send(0X2C);//Registre power consuption + Write
|
||||||
MySPI_Send(0X1A);//Param<EFBFBD>trage hors low consumption + 100Hz output data rate
|
MySPI_Send(0X1A);//Paramétrage hors low consumption + 100Hz output data rate
|
||||||
MySPI_Set_NSS();//CS HIGH
|
MySPI_Set_NSS();//CS HIGH
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
MySPI_Clear_NSS(); //CS LOW
|
||||||
MySPI_Send(0x31);//registre Data format + write
|
MySPI_Send(0x31);//registre Data format + write
|
||||||
MySPI_Send(0x17);//
|
MySPI_Send(0x17);//
|
||||||
MySPI_Set_NSS();//CS HIGH
|
MySPI_Set_NSS();//CS HIGH
|
||||||
}
|
|
||||||
|
|
||||||
void Lecture_accelerometre(float* GX, float* GY, float* GZ)
|
|
||||||
{
|
|
||||||
int16_t dataX ;
|
|
||||||
int16_t dataY ;
|
|
||||||
int16_t dataZ ;
|
|
||||||
|
|
||||||
MySPI_Clear_NSS(); //CS LOW
|
MySPI_Clear_NSS(); //CS LOW
|
||||||
|
MySPI_Send(0xF2);
|
||||||
MySPI_Send(0xF2);//lecture 1er registre acc<63>l<EFBFBD>rom<6F>tre + lecture multibytes
|
dataX = MySPI_Read()<<8;
|
||||||
dataX = MySPI_Read()<<8; // donn<6E>es sur 13 (12 data + sign) bits passage 8 bit en PF
|
dataX |= MySPI_Read();
|
||||||
dataX |= MySPI_Read(); //lecture SPI
|
dataX &= 0xE;
|
||||||
dataX &= 0x1FFF; //masquage au dessus du bit 13
|
GX = dataX*0.004;
|
||||||
if (dataX > 511)
|
|
||||||
{
|
|
||||||
dataX -= 1024;
|
|
||||||
}
|
|
||||||
*GX = dataX*0.004;//valeur du registre x pas accelerometre
|
|
||||||
|
|
||||||
dataY = MySPI_Read()<<8;
|
dataY = MySPI_Read()<<8;
|
||||||
dataY |= MySPI_Read();
|
dataY |= MySPI_Read();
|
||||||
dataY &= 0x1FFF;
|
dataY &= 0xE;
|
||||||
if (dataY > 511)
|
GY = dataY*0.004;
|
||||||
{
|
dataZ = MySPI_Read()<<8;
|
||||||
dataY -= 1024;
|
dataZ |= MySPI_Read();
|
||||||
}
|
dataZ &= 0xE;
|
||||||
*GY = dataY*0.004;//valeur du registre x pas accelerometre
|
GZ = dataZ*0.004;
|
||||||
|
|
||||||
dataZ = ((MySPI_Read()<<8)|MySPI_Read());
|
|
||||||
dataZ &= 0x1FFF;
|
|
||||||
/* if (dataZ > 511)
|
|
||||||
{
|
|
||||||
dataZ -= 1024;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
*GZ = dataZ*0.004;//valeur du registre x pas accelerometre
|
|
||||||
|
|
||||||
MySPI_Set_NSS();//CS HIGH
|
MySPI_Set_NSS();//CS HIGH
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define INC_ACCELEROMETER_H_
|
#define INC_ACCELEROMETER_H_
|
||||||
|
|
||||||
#include "../driver/MySPI.h"
|
#include "../driver/MySPI.h"
|
||||||
|
void accelerometre(void);
|
||||||
|
|
||||||
|
|
||||||
void Init_accelerometre(void);
|
|
||||||
void Lecture_accelerometre(float *GX, float* GY, float* GZ);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,32 +1,29 @@
|
||||||
#include "battery.h"
|
#include "battery.h"
|
||||||
|
|
||||||
extern MyUART_Struct_Typedef uartCool;
|
extern MyUART_Struct_Typedef uartCool;
|
||||||
extern int actualMinutes;
|
int actualMinutes =-1;
|
||||||
extern uint32_t oldAdc;
|
uint32_t oldAdc =0;
|
||||||
|
|
||||||
void battery(uint32_t data)
|
void battery(uint32_t data)
|
||||||
{
|
{
|
||||||
MyRTC_Struct_TypeDef rtcBattery;
|
MyRTC_Struct_TypeDef rtcBattery;
|
||||||
MyRTC_GetTime(&rtcBattery);
|
MyRTC_GetTime(&rtcBattery);
|
||||||
|
|
||||||
if((actualMinutes == rtcBattery.minutes) && isClose(oldAdc,data,100)) //pas de precision/10 %
|
if((actualMinutes == rtcBattery.minutes) && isClose(oldAdc,data,50)) //pas de precision/10 %
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
float percentBattery = ((float)data)/MAX_BAT;
|
|
||||||
if(percentBattery > 1)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
oldAdc = data;
|
oldAdc = data;
|
||||||
actualMinutes = rtcBattery.minutes;
|
actualMinutes = rtcBattery.minutes;
|
||||||
|
float percentBattery = ((float)data)/MAX_BAT;
|
||||||
char batteryBar[13]="[__________]";
|
char batteryBar[13]="[__________]";
|
||||||
char testChar[25];
|
char testChar[24];
|
||||||
|
|
||||||
getGauge(batteryBar, percentBattery);
|
getGauge(batteryBar, percentBattery);
|
||||||
sprintf(testChar,"[%.2d:%.2d] %s %.3d%%",rtcBattery.hours,rtcBattery.minutes,batteryBar,(int)(percentBattery*100));
|
sprintf(testChar,"[%.2d:%.2d] %s %.2d%%",rtcBattery.hours,rtcBattery.minutes,batteryBar,(int)(percentBattery*100));
|
||||||
MyUART_SendArray(&uartCool, (uint8_t *)testChar, 25);
|
MyUART_SendArray(&uartCool, (uint8_t *)testChar, 24);
|
||||||
|
|
||||||
MyUART_Send(&uartCool, '\n');
|
MyUART_Send(&uartCool, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +31,10 @@ void getGauge(char gauge[], float percent)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
percent=percent*10;
|
percent=percent*10;
|
||||||
|
if(percent>10)
|
||||||
|
{
|
||||||
|
percent = 10.0;
|
||||||
|
}
|
||||||
for(i=(10-percent)+1; i<11; i++)
|
for(i=(10-percent)+1; i<11; i++)
|
||||||
{
|
{
|
||||||
gauge[i]='#';
|
gauge[i]='#';
|
||||||
|
@ -53,7 +54,7 @@ char isClose(uint32_t data, uint32_t compare, int precision)
|
||||||
void initBattery(void)
|
void initBattery(void)
|
||||||
{
|
{
|
||||||
MyADC_Init_Periph(battery);
|
MyADC_Init_Periph(battery);
|
||||||
MyADC_Struct_TypeDef adcBattery = {ADC1,10,cycles239d5};
|
MyADC_Struct_TypeDef adcBattery = {ADC1,10,cycles41d5};
|
||||||
MyADC_Init(&adcBattery);
|
MyADC_Init(&adcBattery);
|
||||||
MyGPIO_Struct_TypeDef gpioBattery = {GPIOC,0,In_Analog};
|
MyGPIO_Struct_TypeDef gpioBattery = {GPIOC,0,In_Analog};
|
||||||
MyGPIO_Init(&gpioBattery);
|
MyGPIO_Init(&gpioBattery);
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
#include "girouette.h"
|
|
||||||
|
|
||||||
void MyGirouette_Init(TIM_TypeDef *TIMX)
|
|
||||||
{
|
|
||||||
RCC->APB1ENR |=RCC_APB1ENR_TIM4EN;
|
|
||||||
//configuration gpiob6 et gpiob7 en entrées In_Floating imposer par le timer4
|
|
||||||
MyGPIO_Struct_TypeDef MyGPIO={GPIOB,6,In_Floating};
|
|
||||||
MyGPIO_Init(&MyGPIO);
|
|
||||||
MyGPIO.GPIO_Pin=7;
|
|
||||||
MyGPIO_Init(&MyGPIO);
|
|
||||||
//config pa0 en entrées
|
|
||||||
MyGPIO.GPIO_Pin=0;
|
|
||||||
MyGPIO.GPIO=GPIOA;
|
|
||||||
MyGPIO_Init(&MyGPIO);
|
|
||||||
//configuration TIM4 reset a 360
|
|
||||||
MyTimer_Struct_Typedef MyTimerGirouette ={TIMX,1439,0};
|
|
||||||
MyTimer_Base_Init(&MyTimerGirouette);
|
|
||||||
|
|
||||||
TIMX->SMCR &=~0x07;
|
|
||||||
TIMX->SMCR |=TIM_SMCR_SMS_1;
|
|
||||||
TIMX->CCMR1 &=~(0xF2F2);
|
|
||||||
TIMX->CCMR1 |= TIM_CCMR1_CC1S_0;
|
|
||||||
TIMX->CCMR1 |= TIM_CCMR1_CC2S_0; //CC2S dans CCMR1 et pas CCMR2
|
|
||||||
TIMX->CCER &=~TIM_CCER_CC1P;
|
|
||||||
TIMX->CCER &=~TIM_CCER_CC2P;
|
|
||||||
TIMX->CCMR1&=~(0x0F<<4); //IC1F
|
|
||||||
TIMX->CCMR1&=~(0x0F<<12);//IC2F
|
|
||||||
TIMX->CR1 |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int MyGirouette_Angle(TIM_TypeDef *TIMX)
|
|
||||||
{
|
|
||||||
return (TIMX->CNT)/4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MyGirouette_Init_IT_Z(uint8_t GPIO_Pin)
|
|
||||||
{
|
|
||||||
RCC->APB2ENR |=0x01;
|
|
||||||
EXTI->IMR |= (0x01<<GPIO_Pin); // Autorisation de l'interruption de la ligne
|
|
||||||
EXTI->RTSR|= (0x01<<GPIO_Pin); // Activation du déclenchement de l'interruption sur un front montant
|
|
||||||
AFIO->EXTICR[0] &= ~(0x0000000F);// L'interruption « EXTI0 » doit être provoquée par une modification PA0
|
|
||||||
NVIC->IP[EXTI0_IRQn] |= (1 << 0x4); //Prio de l'interruption (p.197 manuel reference RM0008 pour ADC1_IRQn)
|
|
||||||
NVIC->ISER[0] |= (1 << (6 & 0x1F)); // Autorisation de l'interruption « EXTI0 » NUMERO 6,
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void EXTI0_IRQHandler(void) {
|
|
||||||
TIM4->CNT=0;
|
|
||||||
EXTI->PR|=0x01;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef MYGIROUETTE_H
|
|
||||||
#define MYGIROUETTE_H
|
|
||||||
#include "stm32f10x.h"
|
|
||||||
#include "../driver/gpio.h"
|
|
||||||
#include "../driver/timer.h"
|
|
||||||
|
|
||||||
int MyGirouette_Angle(TIM_TypeDef *TIMX);
|
|
||||||
void MyGirouette_Init(TIM_TypeDef *TIMX);
|
|
||||||
void MyGirouette_Init_IT_Z(uint8_t GPIO_Pin);
|
|
||||||
void EXTI0_IRQHandler(void);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -25,7 +25,7 @@ void MyRTC_GetTime(MyRTC_Struct_TypeDef * rtc)
|
||||||
MyI2C_GetString(I2C2, 0x01, &data);
|
MyI2C_GetString(I2C2, 0x01, &data);
|
||||||
rtc->minutes = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
|
rtc->minutes = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
|
||||||
MyI2C_GetString(I2C2, 0x02, &data);
|
MyI2C_GetString(I2C2, 0x02, &data);
|
||||||
rtc->hours = ((regCopy>>4)&0x01)*10 + (regCopy & 0x0F);
|
rtc->hours = 0;
|
||||||
MyI2C_GetString(I2C2, 0x03, &data);
|
MyI2C_GetString(I2C2, 0x03, &data);
|
||||||
rtc->day = (regCopy & 0x07);
|
rtc->day = (regCopy & 0x07);
|
||||||
MyI2C_GetString(I2C2, 0x04, &data);
|
MyI2C_GetString(I2C2, 0x04, &data);
|
||||||
|
|
|
@ -13,8 +13,8 @@ void MyServo_Init(void)
|
||||||
MyTimer_Base_Init(&Timer);
|
MyTimer_Base_Init(&Timer);
|
||||||
|
|
||||||
//Pin Timer 2 Channel 1 PA0
|
//Pin Timer 2 Channel 1 PA0
|
||||||
MyTimer_PWM(TIM2, 2);
|
MyTimer_PWM(TIM2, 1);
|
||||||
MyTimer_DutyCycle(TIM2, 2, 750);
|
MyTimer_DutyCycle(TIM2, 1, 750);
|
||||||
|
|
||||||
MyTimer_Base_Start(Timer);
|
MyTimer_Base_Start(Timer);
|
||||||
}
|
}
|
||||||
|
@ -26,5 +26,5 @@ void MyServo_ChangeAngle(uint8_t Angle)
|
||||||
|
|
||||||
int DC = 500 + (Angle * 500 / 180);
|
int DC = 500 + (Angle * 500 / 180);
|
||||||
|
|
||||||
MyTimer_DutyCycle(TIM2, 2, DC);
|
MyTimer_DutyCycle(TIM2, 1, DC);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,50 +4,30 @@
|
||||||
#include "motoreducteur.h"
|
#include "motoreducteur.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
#include "accelerometer.h"
|
|
||||||
#include "battery.h"
|
#include "battery.h"
|
||||||
#include "timer.h"
|
#include "accelerometer.h"
|
||||||
#include "girouette.h"
|
|
||||||
|
|
||||||
void initImplementation(void);
|
void initImplementation(void);
|
||||||
|
|
||||||
float GX, GY, GZ;
|
|
||||||
int Angle_Girouette=0;
|
|
||||||
int actualMinutes=-1;
|
|
||||||
uint32_t oldAdc=0;
|
|
||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
{
|
{
|
||||||
|
|
||||||
//MyGPIO_Struct_TypeDef led = {GPIOA,5,Out_PullUp}; //led
|
//MyGPIO_Struct_TypeDef led = {GPIOA,5,Out_PullUp}; //led
|
||||||
//MyGPIO_Init(&led); //test des leds pour ignorer les contraintes li<EFBFBD>es aux diff<66>rents ports
|
//MyGPIO_Init(&led); //test des leds pour ignorer les contraintes liées aux différents ports
|
||||||
initImplementation();
|
initImplementation();
|
||||||
MyServo_ChangeAngle(90);
|
|
||||||
//MyRTC_GetTime(&sec, &min, &hour, &day, &date, &month, &year);
|
//MyRTC_GetTime(&sec, &min, &hour, &day, &date, &month, &year);
|
||||||
while(1){
|
while(1){};
|
||||||
Lecture_accelerometre(&GX,&GY,&GZ);
|
|
||||||
if(GZ < 5.5)
|
|
||||||
{
|
|
||||||
MyServo_ChangeAngle(179);
|
|
||||||
}
|
|
||||||
Angle_Girouette=MyGirouette_Angle(TIM4);
|
|
||||||
MyServo_ChangeAngle(Angle_Girouette/4);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initImplementation(void)
|
void initImplementation(void)
|
||||||
{
|
{
|
||||||
initRemote();
|
|
||||||
MyServo_Init();
|
MyServo_Init();
|
||||||
MyServo_ChangeAngle(179);
|
MyServo_ChangeAngle(179);
|
||||||
Init_accelerometre();
|
initRemote();
|
||||||
MyGirouette_Init(TIM4);
|
testRemote();
|
||||||
MyGirouette_Init_IT_Z(0);
|
|
||||||
MyMotor_Init();
|
MyMotor_Init();
|
||||||
MyMotor_ChangeSpeed(0);
|
MyMotor_ChangeSpeed(0);
|
||||||
MyMotor_ChangeDirection(HORAIRE);
|
MyMotor_ChangeDirection(HORAIRE);
|
||||||
MyRTC_Init();
|
MyRTC_Init();
|
||||||
initBattery();
|
initBattery();
|
||||||
|
accelerometre();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,196 +26,9 @@
|
||||||
<ToolsetNumber>0x4</ToolsetNumber>
|
<ToolsetNumber>0x4</ToolsetNumber>
|
||||||
<ToolsetName>ARM-ADS</ToolsetName>
|
<ToolsetName>ARM-ADS</ToolsetName>
|
||||||
<TargetOption>
|
<TargetOption>
|
||||||
<CLKADS>8000000</CLKADS>
|
<CLKADS>12000000</CLKADS>
|
||||||
<OPTTT>
|
<OPTTT>
|
||||||
<gFlags>1</gFlags>
|
<gFlags>0</gFlags>
|
||||||
<BeepAtEnd>1</BeepAtEnd>
|
|
||||||
<RunSim>0</RunSim>
|
|
||||||
<RunTarget>1</RunTarget>
|
|
||||||
<RunAbUc>0</RunAbUc>
|
|
||||||
</OPTTT>
|
|
||||||
<OPTHX>
|
|
||||||
<HexSelection>1</HexSelection>
|
|
||||||
<FlashByte>65535</FlashByte>
|
|
||||||
<HexRangeLowAddress>0</HexRangeLowAddress>
|
|
||||||
<HexRangeHighAddress>0</HexRangeHighAddress>
|
|
||||||
<HexOffset>0</HexOffset>
|
|
||||||
</OPTHX>
|
|
||||||
<OPTLEX>
|
|
||||||
<PageWidth>79</PageWidth>
|
|
||||||
<PageLength>66</PageLength>
|
|
||||||
<TabStop>8</TabStop>
|
|
||||||
<ListingPath>.\Listings\</ListingPath>
|
|
||||||
</OPTLEX>
|
|
||||||
<ListingPage>
|
|
||||||
<CreateCListing>1</CreateCListing>
|
|
||||||
<CreateAListing>1</CreateAListing>
|
|
||||||
<CreateLListing>1</CreateLListing>
|
|
||||||
<CreateIListing>0</CreateIListing>
|
|
||||||
<AsmCond>1</AsmCond>
|
|
||||||
<AsmSymb>1</AsmSymb>
|
|
||||||
<AsmXref>0</AsmXref>
|
|
||||||
<CCond>1</CCond>
|
|
||||||
<CCode>0</CCode>
|
|
||||||
<CListInc>0</CListInc>
|
|
||||||
<CSymb>0</CSymb>
|
|
||||||
<LinkerCodeListing>0</LinkerCodeListing>
|
|
||||||
</ListingPage>
|
|
||||||
<OPTXL>
|
|
||||||
<LMap>1</LMap>
|
|
||||||
<LComments>1</LComments>
|
|
||||||
<LGenerateSymbols>1</LGenerateSymbols>
|
|
||||||
<LLibSym>1</LLibSym>
|
|
||||||
<LLines>1</LLines>
|
|
||||||
<LLocSym>1</LLocSym>
|
|
||||||
<LPubSym>1</LPubSym>
|
|
||||||
<LXref>0</LXref>
|
|
||||||
<LExpSel>0</LExpSel>
|
|
||||||
</OPTXL>
|
|
||||||
<OPTFL>
|
|
||||||
<tvExp>1</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<IsCurrentTarget>1</IsCurrentTarget>
|
|
||||||
</OPTFL>
|
|
||||||
<CpuCode>18</CpuCode>
|
|
||||||
<DebugOpt>
|
|
||||||
<uSim>1</uSim>
|
|
||||||
<uTrg>0</uTrg>
|
|
||||||
<sLdApp>1</sLdApp>
|
|
||||||
<sGomain>1</sGomain>
|
|
||||||
<sRbreak>1</sRbreak>
|
|
||||||
<sRwatch>1</sRwatch>
|
|
||||||
<sRmem>1</sRmem>
|
|
||||||
<sRfunc>1</sRfunc>
|
|
||||||
<sRbox>1</sRbox>
|
|
||||||
<tLdApp>1</tLdApp>
|
|
||||||
<tGomain>1</tGomain>
|
|
||||||
<tRbreak>1</tRbreak>
|
|
||||||
<tRwatch>1</tRwatch>
|
|
||||||
<tRmem>1</tRmem>
|
|
||||||
<tRfunc>0</tRfunc>
|
|
||||||
<tRbox>1</tRbox>
|
|
||||||
<tRtrace>1</tRtrace>
|
|
||||||
<sRSysVw>1</sRSysVw>
|
|
||||||
<tRSysVw>1</tRSysVw>
|
|
||||||
<sRunDeb>0</sRunDeb>
|
|
||||||
<sLrtime>0</sLrtime>
|
|
||||||
<bEvRecOn>1</bEvRecOn>
|
|
||||||
<bSchkAxf>0</bSchkAxf>
|
|
||||||
<bTchkAxf>0</bTchkAxf>
|
|
||||||
<nTsel>0</nTsel>
|
|
||||||
<sDll></sDll>
|
|
||||||
<sDllPa></sDllPa>
|
|
||||||
<sDlgDll></sDlgDll>
|
|
||||||
<sDlgPa></sDlgPa>
|
|
||||||
<sIfile></sIfile>
|
|
||||||
<tDll></tDll>
|
|
||||||
<tDllPa></tDllPa>
|
|
||||||
<tDlgDll></tDlgDll>
|
|
||||||
<tDlgPa></tDlgPa>
|
|
||||||
<tIfile></tIfile>
|
|
||||||
<pMon>BIN\UL2CM3.DLL</pMon>
|
|
||||||
</DebugOpt>
|
|
||||||
<TargetDriverDllRegistry>
|
|
||||||
<SetRegEntry>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Key>ARMRTXEVENTFLAGS</Key>
|
|
||||||
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
|
|
||||||
</SetRegEntry>
|
|
||||||
<SetRegEntry>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Key>DLGDARM</Key>
|
|
||||||
<Name>(1010=752,272,1128,829,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(111=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(180=-1,-1,-1,-1,0)(120=832,432,1253,859,0)(121=247,294,668,721,0)(122=875,109,1296,536,0)(123=-1,-1,-1,-1,0)(140=-1,-1,-1,-1,0)(240=-1,-1,-1,-1,0)(190=-1,-1,-1,-1,0)(200=-1,-1,-1,-1,0)(170=-1,-1,-1,-1,0)(130=-1,-1,-1,-1,0)(131=751,208,1345,959,0)(132=-1,-1,-1,-1,0)(133=235,63,829,814,0)(160=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(210=-1,-1,-1,-1,0)(211=-1,-1,-1,-1,0)(220=-1,-1,-1,-1,0)(221=-1,-1,-1,-1,0)(230=-1,-1,-1,-1,0)(234=-1,-1,-1,-1,0)(231=-1,-1,-1,-1,0)(232=-1,-1,-1,-1,0)(233=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)</Name>
|
|
||||||
</SetRegEntry>
|
|
||||||
<SetRegEntry>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Key>ARMDBGFLAGS</Key>
|
|
||||||
<Name>-T0</Name>
|
|
||||||
</SetRegEntry>
|
|
||||||
<SetRegEntry>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Key>UL2CM3</Key>
|
|
||||||
<Name>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128 -FS08000000 -FL020000 -FP0($$Device:STM32F103RB$Flash\STM32F10x_128.FLM))</Name>
|
|
||||||
</SetRegEntry>
|
|
||||||
</TargetDriverDllRegistry>
|
|
||||||
<Breakpoint/>
|
|
||||||
<WatchWindow1>
|
|
||||||
<Ww>
|
|
||||||
<count>0</count>
|
|
||||||
<WinNumber>1</WinNumber>
|
|
||||||
<ItemText>voyons</ItemText>
|
|
||||||
</Ww>
|
|
||||||
<Ww>
|
|
||||||
<count>1</count>
|
|
||||||
<WinNumber>1</WinNumber>
|
|
||||||
<ItemText>returnValue</ItemText>
|
|
||||||
</Ww>
|
|
||||||
<Ww>
|
|
||||||
<count>2</count>
|
|
||||||
<WinNumber>1</WinNumber>
|
|
||||||
<ItemText>Angle_Girouette</ItemText>
|
|
||||||
</Ww>
|
|
||||||
</WatchWindow1>
|
|
||||||
<Tracepoint>
|
|
||||||
<THDelay>0</THDelay>
|
|
||||||
</Tracepoint>
|
|
||||||
<DebugFlag>
|
|
||||||
<trace>0</trace>
|
|
||||||
<periodic>1</periodic>
|
|
||||||
<aLwin>1</aLwin>
|
|
||||||
<aCover>0</aCover>
|
|
||||||
<aSer1>0</aSer1>
|
|
||||||
<aSer2>0</aSer2>
|
|
||||||
<aPa>0</aPa>
|
|
||||||
<viewmode>1</viewmode>
|
|
||||||
<vrSel>0</vrSel>
|
|
||||||
<aSym>0</aSym>
|
|
||||||
<aTbox>0</aTbox>
|
|
||||||
<AscS1>0</AscS1>
|
|
||||||
<AscS2>0</AscS2>
|
|
||||||
<AscS3>0</AscS3>
|
|
||||||
<aSer3>0</aSer3>
|
|
||||||
<eProf>0</eProf>
|
|
||||||
<aLa>0</aLa>
|
|
||||||
<aPa1>0</aPa1>
|
|
||||||
<AscS4>0</AscS4>
|
|
||||||
<aSer4>0</aSer4>
|
|
||||||
<StkLoc>0</StkLoc>
|
|
||||||
<TrcWin>0</TrcWin>
|
|
||||||
<newCpu>0</newCpu>
|
|
||||||
<uProt>0</uProt>
|
|
||||||
</DebugFlag>
|
|
||||||
<LintExecutable></LintExecutable>
|
|
||||||
<LintConfigFile></LintConfigFile>
|
|
||||||
<bLintAuto>0</bLintAuto>
|
|
||||||
<bAutoGenD>0</bAutoGenD>
|
|
||||||
<LntExFlags>0</LntExFlags>
|
|
||||||
<pMisraName></pMisraName>
|
|
||||||
<pszMrule></pszMrule>
|
|
||||||
<pSingCmds></pSingCmds>
|
|
||||||
<pMultCmds></pMultCmds>
|
|
||||||
<pMisraNamep></pMisraNamep>
|
|
||||||
<pszMrulep></pszMrulep>
|
|
||||||
<pSingCmdsp></pSingCmdsp>
|
|
||||||
<pMultCmdsp></pMultCmdsp>
|
|
||||||
<DebugDescription>
|
|
||||||
<Enable>1</Enable>
|
|
||||||
<EnableFlashSeq>1</EnableFlashSeq>
|
|
||||||
<EnableLog>0</EnableLog>
|
|
||||||
<Protocol>2</Protocol>
|
|
||||||
<DbgClock>10000000</DbgClock>
|
|
||||||
</DebugDescription>
|
|
||||||
</TargetOption>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target>
|
|
||||||
<TargetName>Réel</TargetName>
|
|
||||||
<ToolsetNumber>0x4</ToolsetNumber>
|
|
||||||
<ToolsetName>ARM-ADS</ToolsetName>
|
|
||||||
<TargetOption>
|
|
||||||
<CLKADS>8000000</CLKADS>
|
|
||||||
<OPTTT>
|
|
||||||
<gFlags>1</gFlags>
|
|
||||||
<BeepAtEnd>1</BeepAtEnd>
|
<BeepAtEnd>1</BeepAtEnd>
|
||||||
<RunSim>0</RunSim>
|
<RunSim>0</RunSim>
|
||||||
<RunTarget>1</RunTarget>
|
<RunTarget>1</RunTarget>
|
||||||
|
@ -265,6 +78,161 @@
|
||||||
<IsCurrentTarget>0</IsCurrentTarget>
|
<IsCurrentTarget>0</IsCurrentTarget>
|
||||||
</OPTFL>
|
</OPTFL>
|
||||||
<CpuCode>18</CpuCode>
|
<CpuCode>18</CpuCode>
|
||||||
|
<DebugOpt>
|
||||||
|
<uSim>0</uSim>
|
||||||
|
<uTrg>1</uTrg>
|
||||||
|
<sLdApp>1</sLdApp>
|
||||||
|
<sGomain>1</sGomain>
|
||||||
|
<sRbreak>1</sRbreak>
|
||||||
|
<sRwatch>1</sRwatch>
|
||||||
|
<sRmem>1</sRmem>
|
||||||
|
<sRfunc>1</sRfunc>
|
||||||
|
<sRbox>1</sRbox>
|
||||||
|
<tLdApp>1</tLdApp>
|
||||||
|
<tGomain>1</tGomain>
|
||||||
|
<tRbreak>1</tRbreak>
|
||||||
|
<tRwatch>1</tRwatch>
|
||||||
|
<tRmem>1</tRmem>
|
||||||
|
<tRfunc>0</tRfunc>
|
||||||
|
<tRbox>1</tRbox>
|
||||||
|
<tRtrace>1</tRtrace>
|
||||||
|
<sRSysVw>1</sRSysVw>
|
||||||
|
<tRSysVw>1</tRSysVw>
|
||||||
|
<sRunDeb>0</sRunDeb>
|
||||||
|
<sLrtime>0</sLrtime>
|
||||||
|
<bEvRecOn>1</bEvRecOn>
|
||||||
|
<bSchkAxf>0</bSchkAxf>
|
||||||
|
<bTchkAxf>0</bTchkAxf>
|
||||||
|
<nTsel>0</nTsel>
|
||||||
|
<sDll></sDll>
|
||||||
|
<sDllPa></sDllPa>
|
||||||
|
<sDlgDll></sDlgDll>
|
||||||
|
<sDlgPa></sDlgPa>
|
||||||
|
<sIfile></sIfile>
|
||||||
|
<tDll></tDll>
|
||||||
|
<tDllPa></tDllPa>
|
||||||
|
<tDlgDll></tDlgDll>
|
||||||
|
<tDlgPa></tDlgPa>
|
||||||
|
<tIfile></tIfile>
|
||||||
|
<pMon>BIN\UL2CM3.DLL</pMon>
|
||||||
|
</DebugOpt>
|
||||||
|
<TargetDriverDllRegistry>
|
||||||
|
<SetRegEntry>
|
||||||
|
<Number>0</Number>
|
||||||
|
<Key>UL2CM3</Key>
|
||||||
|
<Name>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128 -FS08000000 -FL020000 -FP0($$Device:STM32F103RB$Flash\STM32F10x_128.FLM))</Name>
|
||||||
|
</SetRegEntry>
|
||||||
|
</TargetDriverDllRegistry>
|
||||||
|
<Breakpoint/>
|
||||||
|
<Tracepoint>
|
||||||
|
<THDelay>0</THDelay>
|
||||||
|
</Tracepoint>
|
||||||
|
<DebugFlag>
|
||||||
|
<trace>0</trace>
|
||||||
|
<periodic>0</periodic>
|
||||||
|
<aLwin>0</aLwin>
|
||||||
|
<aCover>0</aCover>
|
||||||
|
<aSer1>0</aSer1>
|
||||||
|
<aSer2>0</aSer2>
|
||||||
|
<aPa>0</aPa>
|
||||||
|
<viewmode>0</viewmode>
|
||||||
|
<vrSel>0</vrSel>
|
||||||
|
<aSym>0</aSym>
|
||||||
|
<aTbox>0</aTbox>
|
||||||
|
<AscS1>0</AscS1>
|
||||||
|
<AscS2>0</AscS2>
|
||||||
|
<AscS3>0</AscS3>
|
||||||
|
<aSer3>0</aSer3>
|
||||||
|
<eProf>0</eProf>
|
||||||
|
<aLa>0</aLa>
|
||||||
|
<aPa1>0</aPa1>
|
||||||
|
<AscS4>0</AscS4>
|
||||||
|
<aSer4>0</aSer4>
|
||||||
|
<StkLoc>0</StkLoc>
|
||||||
|
<TrcWin>0</TrcWin>
|
||||||
|
<newCpu>0</newCpu>
|
||||||
|
<uProt>0</uProt>
|
||||||
|
</DebugFlag>
|
||||||
|
<LintExecutable></LintExecutable>
|
||||||
|
<LintConfigFile></LintConfigFile>
|
||||||
|
<bLintAuto>0</bLintAuto>
|
||||||
|
<bAutoGenD>0</bAutoGenD>
|
||||||
|
<LntExFlags>0</LntExFlags>
|
||||||
|
<pMisraName></pMisraName>
|
||||||
|
<pszMrule></pszMrule>
|
||||||
|
<pSingCmds></pSingCmds>
|
||||||
|
<pMultCmds></pMultCmds>
|
||||||
|
<pMisraNamep></pMisraNamep>
|
||||||
|
<pszMrulep></pszMrulep>
|
||||||
|
<pSingCmdsp></pSingCmdsp>
|
||||||
|
<pMultCmdsp></pMultCmdsp>
|
||||||
|
<DebugDescription>
|
||||||
|
<Enable>1</Enable>
|
||||||
|
<EnableFlashSeq>1</EnableFlashSeq>
|
||||||
|
<EnableLog>0</EnableLog>
|
||||||
|
<Protocol>2</Protocol>
|
||||||
|
<DbgClock>10000000</DbgClock>
|
||||||
|
</DebugDescription>
|
||||||
|
</TargetOption>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target>
|
||||||
|
<TargetName>Réel</TargetName>
|
||||||
|
<ToolsetNumber>0x4</ToolsetNumber>
|
||||||
|
<ToolsetName>ARM-ADS</ToolsetName>
|
||||||
|
<TargetOption>
|
||||||
|
<CLKADS>12000000</CLKADS>
|
||||||
|
<OPTTT>
|
||||||
|
<gFlags>1</gFlags>
|
||||||
|
<BeepAtEnd>1</BeepAtEnd>
|
||||||
|
<RunSim>0</RunSim>
|
||||||
|
<RunTarget>1</RunTarget>
|
||||||
|
<RunAbUc>0</RunAbUc>
|
||||||
|
</OPTTT>
|
||||||
|
<OPTHX>
|
||||||
|
<HexSelection>1</HexSelection>
|
||||||
|
<FlashByte>65535</FlashByte>
|
||||||
|
<HexRangeLowAddress>0</HexRangeLowAddress>
|
||||||
|
<HexRangeHighAddress>0</HexRangeHighAddress>
|
||||||
|
<HexOffset>0</HexOffset>
|
||||||
|
</OPTHX>
|
||||||
|
<OPTLEX>
|
||||||
|
<PageWidth>79</PageWidth>
|
||||||
|
<PageLength>66</PageLength>
|
||||||
|
<TabStop>8</TabStop>
|
||||||
|
<ListingPath>.\Listings\</ListingPath>
|
||||||
|
</OPTLEX>
|
||||||
|
<ListingPage>
|
||||||
|
<CreateCListing>1</CreateCListing>
|
||||||
|
<CreateAListing>1</CreateAListing>
|
||||||
|
<CreateLListing>1</CreateLListing>
|
||||||
|
<CreateIListing>0</CreateIListing>
|
||||||
|
<AsmCond>1</AsmCond>
|
||||||
|
<AsmSymb>1</AsmSymb>
|
||||||
|
<AsmXref>0</AsmXref>
|
||||||
|
<CCond>1</CCond>
|
||||||
|
<CCode>0</CCode>
|
||||||
|
<CListInc>0</CListInc>
|
||||||
|
<CSymb>0</CSymb>
|
||||||
|
<LinkerCodeListing>0</LinkerCodeListing>
|
||||||
|
</ListingPage>
|
||||||
|
<OPTXL>
|
||||||
|
<LMap>1</LMap>
|
||||||
|
<LComments>1</LComments>
|
||||||
|
<LGenerateSymbols>1</LGenerateSymbols>
|
||||||
|
<LLibSym>1</LLibSym>
|
||||||
|
<LLines>1</LLines>
|
||||||
|
<LLocSym>1</LLocSym>
|
||||||
|
<LPubSym>1</LPubSym>
|
||||||
|
<LXref>0</LXref>
|
||||||
|
<LExpSel>0</LExpSel>
|
||||||
|
</OPTXL>
|
||||||
|
<OPTFL>
|
||||||
|
<tvExp>1</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<IsCurrentTarget>1</IsCurrentTarget>
|
||||||
|
</OPTFL>
|
||||||
|
<CpuCode>18</CpuCode>
|
||||||
<DebugOpt>
|
<DebugOpt>
|
||||||
<uSim>0</uSim>
|
<uSim>0</uSim>
|
||||||
<uTrg>1</uTrg>
|
<uTrg>1</uTrg>
|
||||||
|
@ -304,11 +272,21 @@
|
||||||
<pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
|
<pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
|
||||||
</DebugOpt>
|
</DebugOpt>
|
||||||
<TargetDriverDllRegistry>
|
<TargetDriverDllRegistry>
|
||||||
|
<SetRegEntry>
|
||||||
|
<Number>0</Number>
|
||||||
|
<Key>ARMRTXEVENTFLAGS</Key>
|
||||||
|
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
|
||||||
|
</SetRegEntry>
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Key>DLGTARM</Key>
|
<Key>DLGTARM</Key>
|
||||||
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
||||||
</SetRegEntry>
|
</SetRegEntry>
|
||||||
|
<SetRegEntry>
|
||||||
|
<Number>0</Number>
|
||||||
|
<Key>ARMDBGFLAGS</Key>
|
||||||
|
<Name></Name>
|
||||||
|
</SetRegEntry>
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Key>DLGUARM</Key>
|
<Key>DLGUARM</Key>
|
||||||
|
@ -317,22 +295,7 @@
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Key>ST-LINKIII-KEIL_SWO</Key>
|
<Key>ST-LINKIII-KEIL_SWO</Key>
|
||||||
<Name>-U066FFF504955857567155843 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8000 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32F103RB$Flash\STM32F10x_128.FLM)</Name>
|
<Name>-U066FFF504955857567155843 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32F103RB$Flash\STM32F10x_128.FLM)</Name>
|
||||||
</SetRegEntry>
|
|
||||||
<SetRegEntry>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Key>ARMRTXEVENTFLAGS</Key>
|
|
||||||
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
|
|
||||||
</SetRegEntry>
|
|
||||||
<SetRegEntry>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Key>DLGDARM</Key>
|
|
||||||
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
|
||||||
</SetRegEntry>
|
|
||||||
<SetRegEntry>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Key>ARMDBGFLAGS</Key>
|
|
||||||
<Name>-T0</Name>
|
|
||||||
</SetRegEntry>
|
</SetRegEntry>
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
|
@ -341,29 +304,12 @@
|
||||||
</SetRegEntry>
|
</SetRegEntry>
|
||||||
</TargetDriverDllRegistry>
|
</TargetDriverDllRegistry>
|
||||||
<Breakpoint/>
|
<Breakpoint/>
|
||||||
<WatchWindow1>
|
|
||||||
<Ww>
|
|
||||||
<count>0</count>
|
|
||||||
<WinNumber>1</WinNumber>
|
|
||||||
<ItemText>quelquechose</ItemText>
|
|
||||||
</Ww>
|
|
||||||
<Ww>
|
|
||||||
<count>1</count>
|
|
||||||
<WinNumber>1</WinNumber>
|
|
||||||
<ItemText>returnValue</ItemText>
|
|
||||||
</Ww>
|
|
||||||
<Ww>
|
|
||||||
<count>2</count>
|
|
||||||
<WinNumber>1</WinNumber>
|
|
||||||
<ItemText>GZ</ItemText>
|
|
||||||
</Ww>
|
|
||||||
</WatchWindow1>
|
|
||||||
<Tracepoint>
|
<Tracepoint>
|
||||||
<THDelay>0</THDelay>
|
<THDelay>0</THDelay>
|
||||||
</Tracepoint>
|
</Tracepoint>
|
||||||
<DebugFlag>
|
<DebugFlag>
|
||||||
<trace>0</trace>
|
<trace>0</trace>
|
||||||
<periodic>1</periodic>
|
<periodic>0</periodic>
|
||||||
<aLwin>1</aLwin>
|
<aLwin>1</aLwin>
|
||||||
<aCover>0</aCover>
|
<aCover>0</aCover>
|
||||||
<aSer1>0</aSer1>
|
<aSer1>0</aSer1>
|
||||||
|
@ -461,18 +407,6 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\driver\adc.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>adc.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>2</GroupNumber>
|
|
||||||
<FileNumber>4</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\driver\gpio.c</PathWithFileName>
|
<PathWithFileName>..\driver\gpio.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>gpio.c</FilenameWithoutPath>
|
<FilenameWithoutPath>gpio.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
|
@ -480,7 +414,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>2</GroupNumber>
|
<GroupNumber>2</GroupNumber>
|
||||||
<FileNumber>5</FileNumber>
|
<FileNumber>4</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -492,7 +426,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>2</GroupNumber>
|
<GroupNumber>2</GroupNumber>
|
||||||
<FileNumber>6</FileNumber>
|
<FileNumber>5</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -504,25 +438,13 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>2</GroupNumber>
|
<GroupNumber>2</GroupNumber>
|
||||||
<FileNumber>7</FileNumber>
|
<FileNumber>6</FileNumber>
|
||||||
<FileType>5</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>1</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\driver\MyI2C.h</PathWithFileName>
|
<PathWithFileName>..\driver\adc.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>MyI2C.h</FilenameWithoutPath>
|
<FilenameWithoutPath>adc.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>2</GroupNumber>
|
|
||||||
<FileNumber>8</FileNumber>
|
|
||||||
<FileType>5</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\driver\MySPI.h</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>MySPI.h</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -536,55 +458,7 @@
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>3</GroupNumber>
|
<GroupNumber>3</GroupNumber>
|
||||||
<FileNumber>9</FileNumber>
|
<FileNumber>7</FileNumber>
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\implementation\accelerometer.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>accelerometer.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>3</GroupNumber>
|
|
||||||
<FileNumber>10</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\implementation\motoreducteur.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>motoreducteur.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>3</GroupNumber>
|
|
||||||
<FileNumber>11</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\implementation\remote.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>remote.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>3</GroupNumber>
|
|
||||||
<FileNumber>12</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\implementation\rtc.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>rtc.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>3</GroupNumber>
|
|
||||||
<FileNumber>13</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -596,7 +470,43 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>3</GroupNumber>
|
<GroupNumber>3</GroupNumber>
|
||||||
<FileNumber>14</FileNumber>
|
<FileNumber>8</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\implementation\motoreducteur.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>motoreducteur.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>3</GroupNumber>
|
||||||
|
<FileNumber>9</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\implementation\rtc.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>rtc.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>3</GroupNumber>
|
||||||
|
<FileNumber>10</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\implementation\remote.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>remote.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>3</GroupNumber>
|
||||||
|
<FileNumber>11</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -608,13 +518,13 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>3</GroupNumber>
|
<GroupNumber>3</GroupNumber>
|
||||||
<FileNumber>15</FileNumber>
|
<FileNumber>12</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\implementation\girouette.c</PathWithFileName>
|
<PathWithFileName>..\implementation\accelerometer.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>girouette.c</FilenameWithoutPath>
|
<FilenameWithoutPath>accelerometer.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -630,7 +540,7 @@
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>::Device</GroupName>
|
<GroupName>::Device</GroupName>
|
||||||
<tvExp>1</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<cbSel>0</cbSel>
|
<cbSel>0</cbSel>
|
||||||
<RteFlg>1</RteFlg>
|
<RteFlg>1</RteFlg>
|
||||||
|
|