Compare commits

...

35 commits
alix ... master

Author SHA1 Message Date
Simon Paris
18e312d6c5 Controle Voile et Debug PWM channel 2023-04-13 13:27:48 +02:00
8793ad9d28 Updated readme with battery and remote 2023-04-13 11:35:19 +02:00
ee1bc88962 Added GPIOFromPWM function which can be used to optimise the GPIO selection, Fixed MyTimer_ActiveIT which wouldn't work for TIM1 2023-04-13 11:19:42 +02:00
15885e832a Added ADC section in driver.mds 2023-04-12 22:43:31 +02:00
5c83198ad4 link problems 2023-04-12 00:17:45 +02:00
546d2720c5 Certains problèmes dû à gitetud.. 2023-04-12 00:16:21 +02:00
ffe7010957 Changed some names for assets pictures, added summary in readme and some links to other markdown files 2023-04-12 00:13:47 +02:00
fb484e3c88 Merge branch 'origin/alix' 2023-04-11 23:40:29 +02:00
41f7830086 RTC fixed, display hours 2023-04-11 19:18:27 +02:00
30e02a0cbf Battery fixed, changing some priorities for interrupts. Modified ADC Interrupt function, getGauge function 2023-04-11 19:06:27 +02:00
8cfcdf0385 Added Simon part, trying to correct some bugs on battery given by all the while loop 2023-04-11 15:38:36 +02:00
1ea43525ce merge from simon to master 2023-04-11 15:26:48 +02:00
Simon
5f5f8a156e README 2023-04-11 15:09:09 +02:00
Simon
bcad9feebb README 2023-04-11 14:58:48 +02:00
a1ca0c9cf4 merge yohan to master 2023-04-11 14:56:52 +02:00
Simon
a4dee289ec girouette complet 2023-04-11 14:56:00 +02:00
75ec6ed662 integration accelerometre dans le principal 2023-04-11 14:50:19 +02:00
b232a42eba Added isClose to test if the adc changes brutally, and getGauge which simplifies the battery bar. 2023-04-11 14:38:54 +02:00
9d6c764ca5 Merge branch 'guilhem' 2023-04-11 14:21:35 +02:00
c2a78c3a95 acceleromètre avec valeurs en +-12G sur l'axe Z 2023-04-11 13:47:22 +02:00
Simon
b838f0ee8d Variation girouette 2023-04-11 13:35:12 +02:00
33d73b2c82 Added MyRTC_Struct_TypeDef, modified battery function to show the time, and the percent 2023-04-11 11:28:42 +02:00
91fbddca0d cedric me fait changer un truc <3 2023-04-11 09:48:20 +02:00
179f7b0f13 Added MyUART_SendArray function in uart.c, Modified battery function to send a battery gauge. Created MAX_BAT that defines the max level of the battery 2023-04-10 23:48:53 +02:00
6e780d03a3 Fixes on driver.md 2023-04-09 18:29:16 +02:00
c5e1ee0a59 Added driver explainations 2023-04-09 18:21:25 +02:00
Simon
25b871f48e Girouette avec fonction intern du uc 2023-04-07 15:33:22 +02:00
1874f666d4 Added battery and initBattery functions, using external variable uartCool 2023-04-07 15:28:30 +02:00
24cd95c9e3 Merging from guilhem to master 2023-04-07 14:34:13 +02:00
51aa50f505 Accelerometer library finished with 2 functions 1 for Init and 1 for data reading. 2023-04-07 14:26:51 +02:00
381f0b6147 Remote now uses the motor, creation of initImplementation 2023-04-07 14:13:00 +02:00
ed15d8a584 Modifications README et création de la fonction Girouette_Angle. 2023-04-04 16:39:20 +02:00
8530d2a8a1 Fonction V1 de paramétrage et lecture des registre de l'accéléromètre. 2023-04-04 15:17:30 +02:00
e035bfb760 creation de MySPI_Init() 2023-04-03 08:24:42 +02:00
6edec4d684 README Tableau de répartition 2023-03-31 12:13:06 +02:00
39 changed files with 891 additions and 127 deletions

View file

@ -1,5 +1,24 @@
# 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 |
@ -12,7 +31,6 @@
|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|
@ -24,12 +42,10 @@
|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
![[cdc motor.png]]
![CDC MOTOR](assets/cdc_motor.png)
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.
@ -42,9 +58,8 @@ $$ 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.
![[arr motor.png]]
![[psc motor.png]]
![ARR MOTOR](assets/arr_motor.png)
![PSC MOTOR](assets/psc_motor.png)
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*
@ -116,7 +131,7 @@ En testant, nous nous sommes rendu compte qu'entre 0 et 1000, le moteur ne tourn
___
## Servomoteur
![[pwm servo.png]]
![PWM SERVO](assets/pwm_servo.png)
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.
@ -130,8 +145,8 @@ Sachant que la fréquence du microcontrôleur est de 72 MHz et que l'o souhaite
$$ 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.
![[arr motor.png]]
![[psc motor.png]]
![ARR MOTOR](assets/arr_motor.png)
![PSC MOTOR](assets/psc_motor.png)
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*
@ -188,9 +203,9 @@ ___
La télécommande permet deux choses via l'IHM :
- Transmettre la vitesse de rotation demandé et le sens pour le voilier
- Afficher une transmission série d'informations importantes comme la tension de la batterie, si le voilier a chavirer et toutes les 3 secondes les données de l'accéléromètre
- Afficher le niveau de batterie actuel ainsi que le temps en heures et minutes
*Cette implémentation utiliser le driver Uart fait durant le projet*
*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.*
___
@ -233,7 +248,7 @@ 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.
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
@ -244,7 +259,19 @@ MyUART_Send(&uartCool,'u');
MyUART_Send(&uartCool,'t');
```
La fonction testRemote teste basiquement si la télécommande fonctionne en lui envoyant une chaîne de caractère.
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
@ -301,11 +328,11 @@ MyI2C_GetString(I2C2, 0x06, &data);
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.
![[add rtc.png]]
![ADD RTC](assets/add_rtc.png)
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.
![[reg rtc.png]]
![REG RTC](assets/reg_rtc.png)
#### Test de l'implémentation
@ -318,7 +345,7 @@ ___
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.
![[adc accel.png]]
![ADC ACCEL](assets/adc_accel.png)
*Cette implémentation utiliser le driver SPI founit durant le projet*
@ -359,7 +386,7 @@ 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.
![[reg accel.png]]
![REG ACCEL](assets/reg_accel.png)
**void Lecture_accelerometre(float* GX, float* GY, float* GZ)**
```c
@ -460,7 +487,10 @@ MyUART_SendArray(&uartCool, (uint8_t *)testChar, 24);
MyUART_Send(&uartCool, '\n');
```
ss
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
@ -477,7 +507,7 @@ for(i=(10-percent)+1; i<11; i++)
gauge[12]='\0';
```
ss
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
@ -488,7 +518,7 @@ MyGPIO_Struct_TypeDef gpioBattery = {GPIOC,0,In_Analog};
MyGPIO_Init(&gpioBattery);
```
ss
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
@ -499,7 +529,7 @@ if(data < precision)
return !((data >= compare+precision) || (data <= compare-precision));
```
ss
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

Binary file not shown.

BIN
assets/STM32F103RB-3.pdf Normal file

Binary file not shown.

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

BIN
assets/adc_cfgr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
assets/adc_cr2.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View file

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
assets/ccer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

BIN
assets/crl.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/odr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View file

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

BIN
assets/table20_portbit.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/usart_cr1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
assets/usart_sr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,8 +1,8 @@
#include "adc.h"
void (* pFncADC) (void); /* d<>claration d<>un pointeur de fonction */
void (* pFncADC) (uint32_t); /* d<>claration d<>un pointeur de fonction */
void MyADC_Init_Periph (void (* ptrFonction)(void))
void MyADC_Init_Periph (void (* ptrFonction)(uint32_t))
{
pFncADC = ptrFonction; /* affectation du pointeur */
}
@ -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->CR2 |= ADC_CR2_EXTTRIG; //Activation du trigger externe
ADCStructPtr->ADC->CR2 |= ADC_CR2_EXTSEL; //Event externe choisie : SWSTART
MyADC_ActiveIT(ADCStructPtr->ADC,0);
MyADC_ActiveIT(ADCStructPtr->ADC,2);
ADCStructPtr->ADC->CR2 |= ADC_CR2_ADON; //Init l'ADC
MyADC_Base_Start(ADCStructPtr->ADC); //Debut du premier ADC
}
@ -32,13 +32,18 @@ void MyADC_ActiveIT(ADC_TypeDef * ADC, uint8_t Prio)
{
ADC->CR1 |= ADC_CR1_EOCIE; //Interruption active
NVIC->IP[ADC1_2_IRQn] |= (Prio << 0x4); //Prio de l'interruption (p.197 manuel reference RM0008 pour ADC1_IRQn)
NVIC->ISER[0] |= (0x1<<ADC1_2_IRQn); //Active l'interruption au niveau NVIC (p.119 manuel programming pour ISER[0])
NVIC->ISER[0] |= (1<<ADC1_2_IRQn); //Active l'interruption au niveau NVIC (p.119 manuel programming pour ISER[0])
}
void ADC1_2_IRQHandler(void)
{
if (pFncADC != 0)
(*pFncADC) (); /* appel indirect de la fonction */
MyADC_Base_Start(ADC1);
if (ADC1->SR & ADC_SR_EOC)
{
ADC1->SR &= ~ADC_SR_EOC; //Prochaine lecture pouvant <20>tre effectu<74>e.
if (pFncADC != 0)
{
(*pFncADC) (ADC1->DR); /* appel indirect de la fonction */
}
MyADC_Base_Start(ADC1);
}
}

View file

@ -23,7 +23,7 @@ typedef struct
void MyADC_Init(MyADC_Struct_TypeDef * ADCStructPtr);
void MyADC_ActiveIT(ADC_TypeDef * ADC, uint8_t Prio);
void MyADC_Init_Periph (void (* ptrFonction)(void));
void MyADC_Init_Periph (void (* ptrFonction)(uint32_t));
MyGPIO_Struct_TypeDef GPIOFromADC(MyADC_Struct_TypeDef ADC);
#define MyADC_Base_Start(ADC) (ADC->CR2 |= ADC_CR2_SWSTART)

221
driver/driver.md Normal file
View file

@ -0,0 +1,221 @@
# 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 :
![ODR](../assets/odr.png)
Pour sélectionner le mode, cela se passe dans le registre CR L/H :
![CRLH](../assets/crl.PNG)
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 :
![CRLH](../assets/table20_portbit.PNG)
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** :
![ADC CR2](../assets/adc_cr2.png)
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
![ODR](../assets/ccer.png)
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** :
![ADCPRE](../assets/adc_cfgr.png)
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 :
![ODR](../assets/usart_cr1.png)
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) :
![ODR](../assets/usart_sr.png)
- 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

View file

@ -26,7 +26,7 @@ void MyTimer_Base_Init(MyTimer_Struct_Typedef * Timer) {
void MyTimer_ActiveIT(TIM_TypeDef * Timer, char Prio, void (*IT_function) (void)) {
Timer->DIER |= TIM_DIER_UIE;
if (Timer == TIM2) {
if (Timer == TIM1) {
NVIC_EnableIRQ(TIM1_BRK_IRQn);
NVIC_SetPriority(TIM1_BRK_IRQn, Prio);
IT_Tim1 = IT_function;
@ -48,6 +48,33 @@ 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) {
TIM1->SR &= ~TIM_SR_UIF;
(*IT_Tim1)();

View file

@ -80,7 +80,7 @@ void MyUART_Init(MyUART_Struct_Typedef * UARTStructPtr){
}
//TxD Enable, RxD Enable, USART Global Enable
UARTStructPtr->UART->CR1 |= (USART_CR1_TE | USART_CR1_RE);
MyUART_ActiveIT(UARTStructPtr->UART,1);
MyUART_ActiveIT(UARTStructPtr->UART,3);
}
void MyUART_InitGPIO(MyUART_Struct_Typedef * UARTStructPtr)
@ -106,6 +106,17 @@ void MyUART_InitGPIO(MyUART_Struct_Typedef * UARTStructPtr)
MyGPIO_Init(&txd);
}
int MyUART_SendArray(MyUART_Struct_Typedef *UART, uint8_t * data, int dataLength)
{
int i;
for(i=0; i<dataLength; i++)
{
UART->UART->DR = data[i];
while (!(UART->UART->SR & USART_SR_TXE));
}
return 0;
}
void MyUART_Send(MyUART_Struct_Typedef *UART, uint8_t data)
{
UART->UART->DR = data;

View file

@ -30,6 +30,7 @@ typedef struct {
void MyUART_Init(MyUART_Struct_Typedef * UARTStructPtr);
void MyUART_InitGPIO(MyUART_Struct_Typedef * UARTStructPtr);
int MyUART_SendArray(MyUART_Struct_Typedef *UART, uint8_t * data, int dataLength);
void MyUART_Send(MyUART_Struct_Typedef *UART, uint8_t data);
uint8_t MyUART_Receive(MyUART_Struct_Typedef *UART);
void MyUART_Init_Periph (void (* ptrFonction)(uint8_t));

View file

@ -0,0 +1,71 @@
#include "stm32f10x.h"
#include "accelerometer.h"
#include "MySPI.h"
#include "gpio.h"
void Init_accelerometre(void)
{
//char testReg;
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
}
void Lecture_accelerometre(float* GX, float* GY, float* GZ)
{
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<6E>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
}

View file

@ -0,0 +1,8 @@
#ifndef INC_ACCELEROMETER_H_
#define INC_ACCELEROMETER_H_
#include "../driver/MySPI.h"
void Init_accelerometre(void);
void Lecture_accelerometre(float *GX, float* GY, float* GZ);
#endif

60
implementation/battery.c Normal file
View file

@ -0,0 +1,60 @@
#include "battery.h"
extern MyUART_Struct_Typedef uartCool;
extern int actualMinutes;
extern uint32_t oldAdc;
void battery(uint32_t data)
{
MyRTC_Struct_TypeDef rtcBattery;
MyRTC_GetTime(&rtcBattery);
if((actualMinutes == rtcBattery.minutes) && isClose(oldAdc,data,100)) //pas de precision/10 %
{
return;
}
float percentBattery = ((float)data)/MAX_BAT;
if(percentBattery > 1)
{
return;
}
oldAdc = data;
actualMinutes = rtcBattery.minutes;
char batteryBar[13]="[__________]";
char testChar[25];
getGauge(batteryBar, percentBattery);
sprintf(testChar,"[%.2d:%.2d] %s %.3d%%",rtcBattery.hours,rtcBattery.minutes,batteryBar,(int)(percentBattery*100));
MyUART_SendArray(&uartCool, (uint8_t *)testChar, 25);
MyUART_Send(&uartCool, '\n');
}
void getGauge(char gauge[], float percent)
{
int i;
percent=percent*10;
for(i=(10-percent)+1; i<11; i++)
{
gauge[i]='#';
}
gauge[12]='\0';
}
char isClose(uint32_t data, uint32_t compare, int precision)
{
if(data < precision)
{
return !(data >= compare+precision);
}
return !((data >= compare+precision) || (data <= compare-precision));
}
void initBattery(void)
{
MyADC_Init_Periph(battery);
MyADC_Struct_TypeDef adcBattery = {ADC1,10,cycles239d5};
MyADC_Init(&adcBattery);
MyGPIO_Struct_TypeDef gpioBattery = {GPIOC,0,In_Analog};
MyGPIO_Init(&gpioBattery);
}

15
implementation/battery.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef BATTERY_H
#define BATTERY_H
#include "stm32f10x.h"
#include "adc.h"
#include "remote.h"
#include "rtc.h"
#include <stdio.h>
#define MAX_BAT 1145
void battery(uint32_t data);
void getGauge(char gauge[], float percent);
void initBattery(void);
char isClose(uint32_t data, uint32_t compare, int precision);
#endif

View file

@ -0,0 +1,54 @@
#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;
}

View file

@ -0,0 +1,12 @@
#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

View file

@ -1,18 +1,20 @@
#include "remote.h"
#include "gpio.h"
#include "motoreducteur.h"
MyUART_Struct_Typedef uartCool = {USART1,9600,lengthBit8,parityNone,stopBit1};
void remote(uint8_t data)
{
MyUART_Send(&uartCool,data);
int8_t signedData = (int8_t)data;
if(signedData > 0)
if(signedData >= 0)
{
MyGPIO_Set(GPIOA,5);
MyMotor_ChangeDirection(HORAIRE);
MyMotor_ChangeSpeed(signedData*100);
}
else {
MyGPIO_Reset(GPIOA,5);
MyMotor_ChangeDirection(ANTIHOR);
MyMotor_ChangeSpeed((-signedData)*100);
}
}

View file

@ -8,10 +8,10 @@ void (*IT_I2C_Err) (void) = plantage_i2C;
void MyRTC_Init(void)
{
MyI2C_Init(I2C1, 15, IT_I2C_Err);
MyI2C_Init(I2C2, 15, IT_I2C_Err);
}
void MyRTC_GetTime(int* sec, int* min, int* hour, int* day, int* date, int* month, int* year)
void MyRTC_GetTime(MyRTC_Struct_TypeDef * rtc)
{
MyI2C_RecSendData_Typedef data;
char regCopy = 0;
@ -20,18 +20,18 @@ void MyRTC_GetTime(int* sec, int* min, int* hour, int* day, int* date, int* mont
data.Ptr_Data = &regCopy;
data.Nb_Data = 1;
MyI2C_GetString(I2C1, 0x00, &data);
*sec = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C1, 0x01, &data);
*min = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C1, 0x02, &data);
*hour = 0;
MyI2C_GetString(I2C1, 0x03, &data);
*day = (regCopy & 0x07);
MyI2C_GetString(I2C1, 0x04, &data);
*date = ((regCopy >> 4) & 0x03) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C1, 0x05, &data);
*month = ((regCopy >> 4) & 0x01) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C1, 0x06, &data);
*year = ((regCopy >> 4) & 0xF0) * 10 + (regCopy & 0x0F) + 2000;
MyI2C_GetString(I2C2, 0x00, &data);
rtc->seconds = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C2, 0x01, &data);
rtc->minutes = ((regCopy >> 4) & 0x07) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C2, 0x02, &data);
rtc->hours = ((regCopy>>4)&0x01)*10 + (regCopy & 0x0F);
MyI2C_GetString(I2C2, 0x03, &data);
rtc->day = (regCopy & 0x07);
MyI2C_GetString(I2C2, 0x04, &data);
rtc->date = ((regCopy >> 4) & 0x03) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C2, 0x05, &data);
rtc->month = ((regCopy >> 4) & 0x01) * 10 + (regCopy & 0x0F);
MyI2C_GetString(I2C2, 0x06, &data);
rtc->year = ((regCopy >> 4) & 0xF0) * 10 + (regCopy & 0x0F) + 2000;
}

View file

@ -3,7 +3,17 @@
#include "stm32f10x.h"
#include "MyI2C.h"
typedef struct{
int seconds;
int minutes;
int hours;
int day;
int date;
int month;
int year;
} MyRTC_Struct_TypeDef;
void MyRTC_Init(void);
void MyRTC_GetTime(int* sec, int* min, int* hour, int* day, int* date, int* month, int* year);
void MyRTC_GetTime(MyRTC_Struct_TypeDef * rtc);
#endif

View file

@ -13,8 +13,8 @@ void MyServo_Init(void)
MyTimer_Base_Init(&Timer);
//Pin Timer 2 Channel 1 PA0
MyTimer_PWM(TIM2, 1);
MyTimer_DutyCycle(TIM2, 1, 750);
MyTimer_PWM(TIM2, 2);
MyTimer_DutyCycle(TIM2, 2, 750);
MyTimer_Base_Start(Timer);
}
@ -26,5 +26,5 @@ void MyServo_ChangeAngle(uint8_t Angle)
int DC = 500 + (Angle * 500 / 180);
MyTimer_DutyCycle(TIM2, 1, DC);
MyTimer_DutyCycle(TIM2, 2, DC);
}

View file

@ -4,22 +4,50 @@
#include "motoreducteur.h"
#include "rtc.h"
#include "remote.h"
#include "accelerometer.h"
#include "battery.h"
#include "timer.h"
#include "girouette.h"
void initImplementation(void);
float GX, GY, GZ;
int Angle_Girouette=0;
int actualMinutes=-1;
uint32_t oldAdc=0;
int main (void)
{
//MyGPIO_Struct_TypeDef led = {GPIOA,5,Out_PullUp}; //led
//MyGPIO_Init(&led); //test des leds pour ignorer les contraintes li<6C>es aux diff<66>rents ports
initImplementation();
MyServo_ChangeAngle(90);
//MyRTC_GetTime(&sec, &min, &hour, &day, &date, &month, &year);
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)
{
initRemote();
MyServo_Init();
MyServo_ChangeAngle(179);
MyGPIO_Struct_TypeDef led = {GPIOA,5,Out_PullUp}; //led
MyGPIO_Init(&led); //test des leds pour ignorer les contraintes liées aux différents ports
//MyMotor_Init();
//MyMotor_ChangeSpeed(2000);
//MyMotor_ChangeDirection(HORAIRE);
initRemote();
testRemote();
Init_accelerometre();
MyGirouette_Init(TIM4);
MyGirouette_Init_IT_Z(0);
MyMotor_Init();
MyMotor_ChangeSpeed(0);
MyMotor_ChangeDirection(HORAIRE);
MyRTC_Init();
// MyRTC_GetTime();
while(1){};
initBattery();
}

View file

@ -26,9 +26,9 @@
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<TargetOption>
<CLKADS>12000000</CLKADS>
<CLKADS>8000000</CLKADS>
<OPTTT>
<gFlags>0</gFlags>
<gFlags>1</gFlags>
<BeepAtEnd>1</BeepAtEnd>
<RunSim>0</RunSim>
<RunTarget>1</RunTarget>
@ -79,8 +79,8 @@
</OPTFL>
<CpuCode>18</CpuCode>
<DebugOpt>
<uSim>0</uSim>
<uTrg>1</uTrg>
<uSim>1</uSim>
<uTrg>0</uTrg>
<sLdApp>1</sLdApp>
<sGomain>1</sGomain>
<sRbreak>1</sRbreak>
@ -117,6 +117,21 @@
<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>
@ -124,18 +139,35 @@
</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>0</periodic>
<aLwin>0</aLwin>
<periodic>1</periodic>
<aLwin>1</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
<aPa>0</aPa>
<viewmode>0</viewmode>
<viewmode>1</viewmode>
<vrSel>0</vrSel>
<aSym>0</aSym>
<aTbox>0</aTbox>
@ -181,12 +213,12 @@
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<TargetOption>
<CLKADS>12000000</CLKADS>
<CLKADS>8000000</CLKADS>
<OPTTT>
<gFlags>0</gFlags>
<gFlags>1</gFlags>
<BeepAtEnd>1</BeepAtEnd>
<RunSim>1</RunSim>
<RunTarget>0</RunTarget>
<RunSim>0</RunSim>
<RunTarget>1</RunTarget>
<RunAbUc>0</RunAbUc>
</OPTTT>
<OPTHX>
@ -228,14 +260,14 @@
<LExpSel>0</LExpSel>
</OPTXL>
<OPTFL>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>0</IsCurrentTarget>
</OPTFL>
<CpuCode>18</CpuCode>
<DebugOpt>
<uSim>1</uSim>
<uTrg>0</uTrg>
<uSim>0</uSim>
<uTrg>1</uTrg>
<sLdApp>1</sLdApp>
<sGomain>1</sGomain>
<sRbreak>1</sRbreak>
@ -244,7 +276,7 @@
<sRfunc>1</sRfunc>
<sRbox>1</sRbox>
<tLdApp>1</tLdApp>
<tGomain>0</tGomain>
<tGomain>1</tGomain>
<tRbreak>1</tRbreak>
<tRwatch>1</tRwatch>
<tRmem>1</tRmem>
@ -258,7 +290,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>-1</nTsel>
<nTsel>6</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
@ -269,21 +301,75 @@
<tDlgDll></tDlgDll>
<tDlgPa></tDlgPa>
<tIfile></tIfile>
<pMon></pMon>
<pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
</DebugOpt>
<TargetDriverDllRegistry>
<SetRegEntry>
<Number>0</Number>
<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>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGUARM</Key>
<Name>(105=-1,-1,-1,-1,0)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<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>
</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>
<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>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>
<THDelay>0</THDelay>
</Tracepoint>
<DebugFlag>
<trace>0</trace>
<periodic>0</periodic>
<aLwin>0</aLwin>
<periodic>1</periodic>
<aLwin>1</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
<aPa>0</aPa>
<viewmode>0</viewmode>
<viewmode>1</viewmode>
<vrSel>0</vrSel>
<aSym>0</aSym>
<aTbox>0</aTbox>
@ -314,6 +400,19 @@
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
<SystemViewers>
<Entry>
<Name>System Viewer\ADC1</Name>
<WinId>35905</WinId>
</Entry>
</SystemViewers>
<DebugDescription>
<Enable>1</Enable>
<EnableFlashSeq>0</EnableFlashSeq>
<EnableLog>0</EnableLog>
<Protocol>2</Protocol>
<DbgClock>10000000</DbgClock>
</DebugDescription>
</TargetOption>
</Target>
@ -359,7 +458,19 @@
<GroupNumber>2</GroupNumber>
<FileNumber>3</FileNumber>
<FileType>1</FileType>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<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>
@ -369,7 +480,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>4</FileNumber>
<FileNumber>5</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -381,7 +492,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>5</FileNumber>
<FileNumber>6</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -393,13 +504,25 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>6</FileNumber>
<FileType>1</FileType>
<FileNumber>7</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\driver\adc.c</PathWithFileName>
<FilenameWithoutPath>adc.c</FilenameWithoutPath>
<PathWithFileName>..\driver\MyI2C.h</PathWithFileName>
<FilenameWithoutPath>MyI2C.h</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>
<bShared>0</bShared>
</File>
@ -413,19 +536,19 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>7</FileNumber>
<FileNumber>9</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\implementation\servo.c</PathWithFileName>
<FilenameWithoutPath>servo.c</FilenameWithoutPath>
<PathWithFileName>..\implementation\accelerometer.c</PathWithFileName>
<FilenameWithoutPath>accelerometer.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>8</FileNumber>
<FileNumber>10</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -437,9 +560,21 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>9</FileNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>1</tvExp>
<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>
@ -449,13 +584,37 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>10</FileNumber>
<FileNumber>13</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\implementation\remote.c</PathWithFileName>
<FilenameWithoutPath>remote.c</FilenameWithoutPath>
<PathWithFileName>..\implementation\servo.c</PathWithFileName>
<FilenameWithoutPath>servo.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>14</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\implementation\battery.c</PathWithFileName>
<FilenameWithoutPath>battery.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>15</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\implementation\girouette.c</PathWithFileName>
<FilenameWithoutPath>girouette.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@ -471,7 +630,7 @@
<Group>
<GroupName>::Device</GroupName>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>1</RteFlg>

View file

@ -134,11 +134,11 @@
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>-1</DriverSelection>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
@ -313,7 +313,7 @@
</ArmAdsMisc>
<Cads>
<interw>1</interw>
<Optim>1</Optim>
<Optim>2</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
@ -398,6 +398,11 @@
<FileType>4</FileType>
<FilePath>..\driver\Lib_Com_Periph_2022.lib</FilePath>
</File>
<File>
<FileName>adc.c</FileName>
<FileType>1</FileType>
<FilePath>..\driver\adc.c</FilePath>
</File>
<File>
<FileName>gpio.c</FileName>
<FileType>1</FileType>
@ -414,9 +419,14 @@
<FilePath>..\driver\uart.c</FilePath>
</File>
<File>
<FileName>adc.c</FileName>
<FileType>1</FileType>
<FilePath>..\driver\adc.c</FilePath>
<FileName>MyI2C.h</FileName>
<FileType>5</FileType>
<FilePath>..\driver\MyI2C.h</FilePath>
</File>
<File>
<FileName>MySPI.h</FileName>
<FileType>5</FileType>
<FilePath>..\driver\MySPI.h</FilePath>
</File>
</Files>
</Group>
@ -424,24 +434,39 @@
<GroupName>MesImplementations</GroupName>
<Files>
<File>
<FileName>servo.c</FileName>
<FileName>accelerometer.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\servo.c</FilePath>
<FilePath>..\implementation\accelerometer.c</FilePath>
</File>
<File>
<FileName>motoreducteur.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\motoreducteur.c</FilePath>
</File>
<File>
<FileName>remote.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\remote.c</FilePath>
</File>
<File>
<FileName>rtc.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\rtc.c</FilePath>
</File>
<File>
<FileName>remote.c</FileName>
<FileName>servo.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\remote.c</FilePath>
<FilePath>..\implementation\servo.c</FilePath>
</File>
<File>
<FileName>battery.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\battery.c</FilePath>
</File>
<File>
<FileName>girouette.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\girouette.c</FilePath>
</File>
</Files>
</Group>
@ -845,6 +870,11 @@
<FileType>4</FileType>
<FilePath>..\driver\Lib_Com_Periph_2022.lib</FilePath>
</File>
<File>
<FileName>adc.c</FileName>
<FileType>1</FileType>
<FilePath>..\driver\adc.c</FilePath>
</File>
<File>
<FileName>gpio.c</FileName>
<FileType>1</FileType>
@ -861,9 +891,14 @@
<FilePath>..\driver\uart.c</FilePath>
</File>
<File>
<FileName>adc.c</FileName>
<FileType>1</FileType>
<FilePath>..\driver\adc.c</FilePath>
<FileName>MyI2C.h</FileName>
<FileType>5</FileType>
<FilePath>..\driver\MyI2C.h</FilePath>
</File>
<File>
<FileName>MySPI.h</FileName>
<FileType>5</FileType>
<FilePath>..\driver\MySPI.h</FilePath>
</File>
</Files>
</Group>
@ -871,24 +906,39 @@
<GroupName>MesImplementations</GroupName>
<Files>
<File>
<FileName>servo.c</FileName>
<FileName>accelerometer.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\servo.c</FilePath>
<FilePath>..\implementation\accelerometer.c</FilePath>
</File>
<File>
<FileName>motoreducteur.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\motoreducteur.c</FilePath>
</File>
<File>
<FileName>remote.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\remote.c</FilePath>
</File>
<File>
<FileName>rtc.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\rtc.c</FilePath>
</File>
<File>
<FileName>remote.c</FileName>
<FileName>servo.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\remote.c</FilePath>
<FilePath>..\implementation\servo.c</FilePath>
</File>
<File>
<FileName>battery.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\battery.c</FilePath>
</File>
<File>
<FileName>girouette.c</FileName>
<FileType>1</FileType>
<FilePath>..\implementation\girouette.c</FilePath>
</File>
</Files>
</Group>
@ -905,15 +955,15 @@
<RTE>
<apis/>
<components>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.4.0" condition="ARMv6_7_8-M Device">
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="5.7.0"/>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.6.0" condition="ARMv6_7_8-M Device">
<package name="CMSIS" schemaVersion="1.7.7" url="http://www.keil.com/pack/" vendor="ARM" version="5.9.0"/>
<targetInfos>
<targetInfo name="Réel"/>
<targetInfo name="Simulé"/>
</targetInfos>
</component>
<component Cclass="Device" Cgroup="Startup" Cvendor="Keil" Cversion="1.0.0" condition="STM32F1xx CMSIS">
<package name="STM32F1xx_DFP" schemaVersion="1.4.0" url="http://www.keil.com/pack/" vendor="Keil" version="2.3.0"/>
<package name="STM32F1xx_DFP" schemaVersion="1.7.2" url="http://www.keil.com/pack/" vendor="Keil" version="2.4.0"/>
<targetInfos>
<targetInfo name="Réel"/>
<targetInfo name="Simulé"/>