Compare commits
16 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1858fa0ef0 | |||
| 7c51dd43cf | |||
| b24d9812b4 | |||
| 8b95eeb0a5 | |||
| 1fbbaacfea | |||
| af0aedc34b | |||
| 663bef108a | |||
| 5175474912 | |||
| 277a18fd56 | |||
| 4b20cbfb0e | |||
| 6561c9942e | |||
| 6c9bdde0f8 | |||
| 714d75c245 | |||
| 2683401db9 | |||
| c9d55d565e | |||
| cf93972521 |
18 changed files with 646 additions and 10 deletions
8
Pilotes/Include/Accelerometre.h
Executable file
8
Pilotes/Include/Accelerometre.h
Executable file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void initAccelo(void);
|
||||||
|
uint16_t * RecupAccelo(void);
|
||||||
|
void LacheVoile(uint16_t * DATA);
|
||||||
|
void initLacheur(void);
|
||||||
|
uint16_t * KattRecupAccelo(void);
|
||||||
17
Pilotes/Include/DriverGPIO.h
Executable file
17
Pilotes/Include/DriverGPIO.h
Executable file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef DRIVERGPIO_H_
|
||||||
|
#define DRIVERGPIO_H_
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#define In_Floating 0x4
|
||||||
|
#define In_PullDown 0x8
|
||||||
|
#define In_PullUp 0x8
|
||||||
|
#define In_Analog 0x0
|
||||||
|
#define Out_Ppull 0x3
|
||||||
|
#define Out_OD 0x7
|
||||||
|
#define AltOut_Ppull 0xB
|
||||||
|
#define AltOut_OD 0xF
|
||||||
|
extern void MyGPIO_Init(GPIO_TypeDef * GPIO, char pin, char conf );
|
||||||
|
extern int MyGPIO_Read(GPIO_TypeDef * GPIO, char GPIO_Pin); // renvoie 0 ou autre chose different de 0
|
||||||
|
extern void MyGPIO_Set(GPIO_TypeDef * GPIO, char GPIO_Pin);
|
||||||
|
extern void MyGPIO_Reset(GPIO_TypeDef * GPIO, char GPIO_Pin);
|
||||||
|
extern void MyGPIO_Toggle(GPIO_TypeDef * GPIO, char GPIO_Pin);
|
||||||
|
#endif
|
||||||
8
Pilotes/Include/Girouette.h
Executable file
8
Pilotes/Include/Girouette.h
Executable file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef _GIROUETTE_H
|
||||||
|
#define _GIROUETTE_H
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
extern void configEncoder(TIM_TypeDef * Timer);
|
||||||
|
extern int angleVent (TIM_TypeDef * Timer);
|
||||||
|
extern int vent2voile(int angle);
|
||||||
|
extern void LocaliserZero(void);
|
||||||
|
#endif
|
||||||
16
Pilotes/Include/Horloge.h
Executable file
16
Pilotes/Include/Horloge.h
Executable file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
#define PSC_VAL 624
|
||||||
|
#define ARR_VAL 0xE0FF
|
||||||
|
|
||||||
|
//DUTY CYCLE
|
||||||
|
#define DUTYC 70 //Chiffre entre 0 et 100, où 100 est 100% duty cycle
|
||||||
|
#define POWERMODE 1 // 1 vaut powermode 1, 0 vaut powermode 2 (Powermode pour le config de dutycycle)
|
||||||
|
//Powermode 1 reste sur la bonne polarité: cad. si DUTY_CYCLE vaut 60 alors le signal reste HIGH pour 60% du periode, inverse pour pwmd2
|
||||||
|
//Timer
|
||||||
|
void Timer_Init(TIM_TypeDef *Timer, unsigned short Autoreload, unsigned short Prescaler);
|
||||||
|
void MyTimer_ActiveIT(TIM_TypeDef * Timer, char Prio, void(*Interrupt_fonc)(void));
|
||||||
|
void TIM2_IRQHandler(void);
|
||||||
|
|
||||||
|
//PWM
|
||||||
|
void MyTimer_PWM(TIM_TypeDef * Timer , int Channel);
|
||||||
|
int Set_DutyCycle_PWM(TIM_TypeDef *Timer, int Channel, int DutyC);
|
||||||
11
Pilotes/Include/IT.h
Executable file
11
Pilotes/Include/IT.h
Executable file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef IT_H_
|
||||||
|
#define IT_H_
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
static void (*p_IT_functions[4])(void);
|
||||||
|
void MyTimer_ActiveIT(TIM_TypeDef *Timer, char Prio,void(*IT_function)(void));
|
||||||
|
void TIM1_CC_IRQHandler(void);
|
||||||
|
void TIM1_UP_IRQHandler(void);
|
||||||
|
void TIM2_IRQHandler(void);
|
||||||
|
void TIM3_IRQHandler(void);
|
||||||
|
void TIM4_IRQHandler(void);
|
||||||
|
#endif // IT_H_
|
||||||
9
Pilotes/Include/PWM.h
Executable file
9
Pilotes/Include/PWM.h
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef PWM_H_
|
||||||
|
#define PWM_H_
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
//Variables
|
||||||
|
#define POWERMODE 2 // 1 vaut powermode 1, 0 vaut powermode 2 (Powermode pour le config de dutycycle)
|
||||||
|
// Config
|
||||||
|
extern void MyTimer_PWM(TIM_TypeDef * Timer , int Channel);
|
||||||
|
extern int Set_DutyCycle_PWM(TIM_TypeDef *Timer, int Channel, int DutyC);
|
||||||
|
#endif
|
||||||
7
Pilotes/Include/Servo.h
Executable file
7
Pilotes/Include/Servo.h
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef SERVO_H_
|
||||||
|
#define SERVO_H_
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
void Servo_Moteur(int angle, TIM_TypeDef * Timer, int Channel);
|
||||||
|
extern void initServo(TIM_TypeDef * Timer, int Channel);
|
||||||
|
|
||||||
|
#endif // SERVO_H_
|
||||||
8
Pilotes/Include/Timer.h
Executable file
8
Pilotes/Include/Timer.h
Executable file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef TIMER_H_
|
||||||
|
#define TIMER_H_
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
// Config de timer
|
||||||
|
extern void MyTimer_Base_Init(TIM_TypeDef *Timer , unsigned short ValARR , unsigned short ValPSC );
|
||||||
|
// Enable timers
|
||||||
|
void EnableTimer(TIM_TypeDef *Timer);
|
||||||
|
#endif
|
||||||
31
Pilotes/Source/Accelerometre.c
Executable file
31
Pilotes/Source/Accelerometre.c
Executable file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
#include <Horloge.h>
|
||||||
|
//#include <MYGPIO.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
void initLacheur(void){
|
||||||
|
GPIOB->CRH &= ~(0xF << (0 * 4));
|
||||||
|
GPIOB->CRH |= (0xA << (0 * 4)); //On met GPIOB.8 en mode output 2Mhz, alternate pp
|
||||||
|
Timer_Init(TIM4, 20000 - 1, 71); //Claire m'a aidé
|
||||||
|
}
|
||||||
|
|
||||||
|
//Recuperer le DATA en X, Z, Y
|
||||||
|
void LacheVoile(uint16_t * DATA){
|
||||||
|
//uint16_t X = DATA[0]; //Z le longe du mât (masten)
|
||||||
|
//uint16_t Z = DATA[2];// //X le long du sense de voilier
|
||||||
|
uint16_t Y = DATA[1]; ////Y vers les bords (Tribord/Babord)
|
||||||
|
if (Y>=0x007B){// exatement à 40 degrés, on lache le 40%. 0xFF*(40deg/90deg)
|
||||||
|
//Le PWM du moteur est gère par PB7
|
||||||
|
MyTimer_PWM(TIM4, 3); //TIM4 CH3 pour PB8
|
||||||
|
Set_DutyCycle_PWM(TIM4, 3, 2); //On met Duty cycle à 2% et il reste autour de 90 deg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
74
Pilotes/Source/DriverGPIO.c
Executable file
74
Pilotes/Source/DriverGPIO.c
Executable file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#include "DriverGPIO.h"
|
||||||
|
#define In_Floating 0x4
|
||||||
|
#define In_PullDown 0x8
|
||||||
|
#define In_PullUp 0x8
|
||||||
|
#define In_Analog 0x0
|
||||||
|
#define Out_Ppull 0x3
|
||||||
|
#define Out_OD 0x7
|
||||||
|
#define AltOut_Ppull 0xB
|
||||||
|
#define AltOut_OD 0xF
|
||||||
|
|
||||||
|
void MyGPIO_Init(GPIO_TypeDef * GPIO, char pin, char conf ){
|
||||||
|
int shift_pin;
|
||||||
|
//Start clock for relevant GPIO
|
||||||
|
if(GPIO == GPIOA){
|
||||||
|
RCC -> APB2ENR |= RCC_APB2ENR_IOPAEN;
|
||||||
|
}
|
||||||
|
else if(GPIO == GPIOB){
|
||||||
|
RCC -> APB2ENR |= RCC_APB2ENR_IOPBEN;
|
||||||
|
}
|
||||||
|
else if(GPIO == GPIOC){
|
||||||
|
RCC -> APB2ENR |= RCC_APB2ENR_IOPCEN;
|
||||||
|
}
|
||||||
|
else if(GPIO == GPIOD){
|
||||||
|
RCC -> APB2ENR |= RCC_APB2ENR_IOPDEN;
|
||||||
|
}
|
||||||
|
if(pin < 8){//CRL zone
|
||||||
|
shift_pin = pin*4;
|
||||||
|
GPIO -> CRL &= ~(0xF << shift_pin);
|
||||||
|
//PullUp and PullDown have the same conf number, so we need to change the ODR to diferenciate them both
|
||||||
|
if(conf == In_PullUp){
|
||||||
|
GPIO -> CRL |= ( In_PullUp << shift_pin);
|
||||||
|
GPIO -> ODR |= (1<<pin);
|
||||||
|
}
|
||||||
|
else if(conf == In_PullDown){
|
||||||
|
GPIO -> CRL |= ( In_PullDown << shift_pin);
|
||||||
|
GPIO -> ODR &= ~(1<<pin);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
GPIO -> CRL |= ( conf << shift_pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{//CRH zone
|
||||||
|
shift_pin = (pin-8)*4;
|
||||||
|
GPIO -> CRH &= ~(0xF << shift_pin);
|
||||||
|
if(conf == In_PullUp){
|
||||||
|
GPIO -> CRH |= ( In_PullUp << shift_pin);
|
||||||
|
GPIO -> ODR |= (1<<pin);
|
||||||
|
}
|
||||||
|
else if(conf == In_PullDown){
|
||||||
|
GPIO -> CRH |= ( In_PullDown << shift_pin);
|
||||||
|
GPIO -> ODR &= ~(1<<pin);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
GPIO -> CRH |= ( conf << shift_pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MyGPIO_Read(GPIO_TypeDef * GPIO, char GPIO_Pin){
|
||||||
|
return(GPIO -> IDR & (1 << GPIO_Pin));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGPIO_Set(GPIO_TypeDef * GPIO, char GPIO_Pin){
|
||||||
|
GPIO -> BSRR = (1<<GPIO_Pin);//1 on set zone
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGPIO_Reset(GPIO_TypeDef * GPIO, char GPIO_Pin){
|
||||||
|
GPIO -> BSRR = (1<<(GPIO_Pin+16));//1 on reset zone
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGPIO_Toggle(GPIO_TypeDef * GPIO, char GPIO_Pin){
|
||||||
|
GPIO -> ODR = GPIO -> ODR ^ (0x1 << GPIO_Pin);
|
||||||
|
}
|
||||||
61
Pilotes/Source/Girouette.c
Executable file
61
Pilotes/Source/Girouette.c
Executable file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
#include "DriverGPIO.h"
|
||||||
|
#include "Girouette.h"
|
||||||
|
#include "PWM.h"
|
||||||
|
|
||||||
|
#include <stdlib.h> // Pour abs()
|
||||||
|
|
||||||
|
#define POSITIONS (360*4) //0x5A0
|
||||||
|
|
||||||
|
void configEncoder(TIM_TypeDef * Timer){
|
||||||
|
// Timer
|
||||||
|
EnableTimer(Timer);
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
Timer -> CCMR1 |= TIM_CCMR1_CC1S; // TI1FP1 mapped on TI1
|
||||||
|
Timer -> CCMR1 |= TIM_CCMR1_CC2S; // TI1FP2 mapped on TI2
|
||||||
|
Timer -> CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP); // TI1FP1 output non-inverted
|
||||||
|
Timer -> CCMR1 &= ~(TIM_CCMR1_IC1F); // Input capture 1 filter, no filter
|
||||||
|
Timer -> CCER &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP); // TI1FP2 output non-inverted
|
||||||
|
Timer -> CCMR2 &= ~(TIM_CCMR1_IC2F); // Input capture 2 filter, no filter
|
||||||
|
Timer -> SMCR &= ~TIM_SMCR_SMS; // Reset SMS-bits
|
||||||
|
Timer -> SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;// SMS = "011"
|
||||||
|
Timer -> CR1 |= TIM_CR1_CEN; // Enable counter
|
||||||
|
Timer -> ARR = 0x5A0; // Setting ARR as 1440
|
||||||
|
|
||||||
|
// GPIO
|
||||||
|
MyGPIO_Init(GPIOA,0,In_Floating ); // GPIOA pin 0 in mode floating TIM2_CH1
|
||||||
|
MyGPIO_Init(GPIOA,1,In_Floating ); // GPIOA pin 1 in mode floating TIM2_CH2
|
||||||
|
MyGPIO_Init(GPIOA,8,In_PullDown ); // GPIOA pin 8 in mode floating Index
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int angleVent (TIM_TypeDef * Timer){ // Returner l'angle du vent
|
||||||
|
int angle =(((Timer -> CNT*360)/POSITIONS ));
|
||||||
|
if (angle > 180){
|
||||||
|
angle = 360 - angle; // Pour que l'angle soit entre 0 et 180
|
||||||
|
}
|
||||||
|
return(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vent2voile(int angle){ // Conversion angle vent à angle voile
|
||||||
|
if(angle < 45){
|
||||||
|
return 0; // Les voiles restent immobiles
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return(2*(angle-45)/3); // Augmentation linéaire
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Localisation de z
|
||||||
|
void LocaliserZero(void){
|
||||||
|
int Z_trouve = 0;
|
||||||
|
while (Z_trouve != 1){
|
||||||
|
if(MyGPIO_Read(GPIOA,8)){ // Index
|
||||||
|
TIM2 -> CNT = 0x0; // Remet angle à zero
|
||||||
|
Z_trouve = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
136
Pilotes/Source/Horloge.c
Executable file
136
Pilotes/Source/Horloge.c
Executable file
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Horloge.h>
|
||||||
|
|
||||||
|
|
||||||
|
//Il faut trouver le signal
|
||||||
|
//On est à Timer 2
|
||||||
|
|
||||||
|
static void (*TIM2_Appel)(void) = 0;
|
||||||
|
|
||||||
|
void Timer_Init(TIM_TypeDef *Timer, unsigned short Autoreload, unsigned short Prescaler){
|
||||||
|
if (Timer == TIM1) {
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; //L'horloge est enabléd
|
||||||
|
} else if (Timer == TIM2) {
|
||||||
|
TIM2->CR1 |= TIM_CR1_CEN; //On enable l'horloge interne
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||||
|
} else if (Timer == TIM3) {
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||||
|
} else if (Timer == TIM4) {
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||||
|
}
|
||||||
|
Timer->ARR |= Autoreload;
|
||||||
|
Timer->PSC |= Prescaler;
|
||||||
|
}
|
||||||
|
|
||||||
|
//La fonction TIM2_IRQHandler s'utilise dans le processeur, on l'a juste redifint, tel qu'à chaque overflow on met un bit 1 dans GPIOA_ODR
|
||||||
|
void TIM2_IRQHandler(void) { //On redefinit le IRQHandler qui est déjà ecrit dans le code source
|
||||||
|
if (TIM2->SR & TIM_SR_UIF) { //On met le bit de overflow à un dès qu'on a overflow
|
||||||
|
TIM2->SR &= ~TIM_SR_UIF; //Remise à zero
|
||||||
|
|
||||||
|
if (TIM2_Appel){TIM2_Appel();}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MyTimer_ActiveIT(TIM_TypeDef * Timer, char Prio, void(*Interrupt_fonc)(void)){ //On veut créer une fonction qui envoie un signal au cas où il y a debordement, avec une prioritaire, 0 plus importante 15 moins importante
|
||||||
|
if (Timer == TIM2){
|
||||||
|
|
||||||
|
TIM2_Appel = Interrupt_fonc;
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(TIM2_IRQn);
|
||||||
|
NVIC_SetPriority(TIM2_IRQn, Prio);
|
||||||
|
TIM2->DIER |= TIM_DIER_UIE; //Le registre DIER(Interrupt Enable Register) est mis au bit Update Interrupt, qui se commute lors d'un overflow
|
||||||
|
TIM2->CR1 |= TIM_CR1_CEN; //Clock Enable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Fonction qui permet de clignoter le DEL à un pulse volue (Sinusoïdale)
|
||||||
|
//Si le sinus est haut(haute tension) le Duty Cicle est proche de 100%,
|
||||||
|
//si le sinus est bas (vers la tension la plus basse) le Duty Cycle est vers 0%
|
||||||
|
//On s'applique sur un plage de [0V; 3.3V]
|
||||||
|
|
||||||
|
|
||||||
|
void MyTimer_PWM(TIM_TypeDef * Timer , int Channel){
|
||||||
|
int pwrmd;
|
||||||
|
#if POWERMODE //Powermode 1
|
||||||
|
pwrmd = 0b110;
|
||||||
|
#else
|
||||||
|
pwrmd = 0b111; //Powermode 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (Channel == 1){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<4); //On clear les trois bits qui sont de pwm
|
||||||
|
Timer->CCMR1 |= (pwrmd<<4); //On affecte le powermode au bits de lecture pour le µ-controlleur
|
||||||
|
Timer->CCMR1 |= TIM_CCMR1_OC1PE; //Update preload, il n'affecte pas le valeur avant que la prochaine cycle
|
||||||
|
Timer->CCER = TIM_CCER_CC1E; //Enable le pin voulu basculer
|
||||||
|
}
|
||||||
|
else if (Channel == 2){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<12); //Le TIMx_CCMR1 configure deux channels, de bit [6:4] CH1, [14:12] CH2 (OC2M = Output Channel 2 )
|
||||||
|
Timer->CCMR1 |= (pwrmd<<12);
|
||||||
|
Timer->CCMR1 |= TIM_CCMR1_OC2PE;
|
||||||
|
Timer->CCER |= TIM_CCER_CC2E;
|
||||||
|
}
|
||||||
|
else if (Channel == 3){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<4);
|
||||||
|
Timer->CCMR2 |= (pwrmd<<4);
|
||||||
|
Timer->CCMR2 |= TIM_CCMR2_OC3PE;
|
||||||
|
Timer->CCER |= TIM_CCER_CC3E;
|
||||||
|
}
|
||||||
|
else if (Channel == 4){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<12);
|
||||||
|
Timer->CCMR2 |= (pwrmd<<12);
|
||||||
|
Timer->CCMR2 |= TIM_CCMR2_OC4PE;
|
||||||
|
Timer->CCER |= TIM_CCER_CC4E;
|
||||||
|
}
|
||||||
|
|
||||||
|
//En dessous d'ici, on a l'aide du plus gentil chat que je connais
|
||||||
|
// Enable auto-reload preload -- //Ensures that your initial configuration — PWM mode, duty cycle, period — actually takes effect before the timer starts counting.
|
||||||
|
Timer->CR1 |= TIM_CR1_ARPE;
|
||||||
|
// Force update event to load ARR and CCR values immediately
|
||||||
|
Timer->EGR |= TIM_EGR_UG;
|
||||||
|
// Start the timer
|
||||||
|
Timer->CR1 |= TIM_CR1_CEN;
|
||||||
|
|
||||||
|
switch (Channel) {
|
||||||
|
case 1:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<0*4); GPIOA->CRH |= (0xA<<0*4); TIM1->BDTR |= 1<<15; }
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<0*4); GPIOA->CRL |= (0xA<<0*4);}
|
||||||
|
if (Timer == TIM3){GPIOA->CRL &= ~(0xF<<6*4); GPIOA->CRL |= (0xA<<6*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRL &= ~(0xF<<5*4); GPIOB->CRL |= (0xA<<5*4);}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<1*4); GPIOA->CRL |= (0xA<<1*4); TIM1->BDTR |= 1<<15;}
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<1*4); GPIOA->CRL |= (0xA<<1*4);}
|
||||||
|
if (Timer == TIM3){GPIOA->CRL &= ~(0xF<<7*4); GPIOA->CRL |= (0xA<<7*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRL &= ~(0xF<<7*4); GPIOB->CRL |= (0xA<<7*4);}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<2*4); GPIOA->CRH |= (0xA<<2*4); TIM1->BDTR |= 1<<15;}
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<2*4); GPIOA->CRL |= (0xA<<2*4);}
|
||||||
|
if (Timer == TIM3){GPIOB->CRL &= ~(0xF<<0*4); GPIOB->CRL |= (0xA<<0*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRH &= ~(0xF<<0*4); GPIOB->CRH |= (0xA<<0*4);}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<3*4); GPIOA->CRH |= (0xA<<3*4); TIM1->BDTR |= 1<<15;}
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<3*4); GPIOA->CRL |= (0xA<<3*4);}
|
||||||
|
if (Timer == TIM3){GPIOB->CRL &= ~(0xF<<1*4); GPIOB->CRL |= (0xA<<1*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRH &= ~(0xF<<1*4); GPIOB->CRH |= (0xA<<1*4);}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Une fonction qui met le bon PWM volue
|
||||||
|
int Set_DutyCycle_PWM(TIM_TypeDef *Timer, int Channel, int DutyC){
|
||||||
|
int CCR_VAL = (ARR_VAL + 1) * DutyC / 100; //ARR_VAL déjà definie
|
||||||
|
switch (Channel){
|
||||||
|
case 1: Timer->CCR1 = CCR_VAL;
|
||||||
|
case 2: Timer->CCR2 = CCR_VAL;
|
||||||
|
case 3: Timer->CCR3 = CCR_VAL;
|
||||||
|
case 4: Timer->CCR4 = CCR_VAL;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
Timer->EGR |= TIM_EGR_UG;
|
||||||
|
}
|
||||||
73
Pilotes/Source/IT.c
Executable file
73
Pilotes/Source/IT.c
Executable file
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include "IT.h"
|
||||||
|
|
||||||
|
static void (*p_IT_functions[4])(void); // Pour créer l'array des fonctions
|
||||||
|
|
||||||
|
void MyTimer_ActiveIT(TIM_TypeDef *Timer, char Prio,void(*IT_function)(void)) {
|
||||||
|
//Enable interruption requisition
|
||||||
|
Timer->DIER |= TIM_DIER_UIE; // Update interrupt enable
|
||||||
|
|
||||||
|
//Id the interruption timer routine
|
||||||
|
IRQn_Type IRQn;
|
||||||
|
|
||||||
|
int timer_index = -1; // Indice pour notre array des pointeurs
|
||||||
|
if (Timer == TIM2) {
|
||||||
|
IRQn = TIM2_IRQn;
|
||||||
|
timer_index = 0;
|
||||||
|
} else if (Timer == TIM3) {
|
||||||
|
IRQn = TIM3_IRQn;
|
||||||
|
timer_index = 1;
|
||||||
|
} else if (Timer == TIM4) {
|
||||||
|
IRQn = TIM4_IRQn;
|
||||||
|
timer_index = 2;
|
||||||
|
}
|
||||||
|
// Keep the pointer of the valid timer function
|
||||||
|
if (timer_index != -1) {
|
||||||
|
p_IT_functions[timer_index] = IT_function; // index the function
|
||||||
|
} else {
|
||||||
|
return; // Timer invalid
|
||||||
|
}
|
||||||
|
// set interruption priority
|
||||||
|
NVIC_SetPriority(IRQn, Prio);
|
||||||
|
// Enable routine
|
||||||
|
NVIC_EnableIRQ(IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TIM2_IRQHandler(void) {
|
||||||
|
// Clean flag
|
||||||
|
TIM2->SR &= ~TIM_SR_UIF; // Drapeau d'interuption
|
||||||
|
//Call function
|
||||||
|
if (p_IT_functions[0] != 0) {
|
||||||
|
p_IT_functions[0](); // Execute fonction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void TIM3_IRQHandler(void) {
|
||||||
|
// Clean flag
|
||||||
|
TIM3->SR &= ~TIM_SR_UIF;
|
||||||
|
//Call function
|
||||||
|
if (p_IT_functions[1] != 0) {
|
||||||
|
p_IT_functions[1](); // Execute function
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void TIM4_IRQHandler(void) {
|
||||||
|
// Clean flag
|
||||||
|
TIM4->SR &= ~TIM_SR_UIF;
|
||||||
|
//Call function
|
||||||
|
if (p_IT_functions[2] != 0) {
|
||||||
|
p_IT_functions[2](); // Execute function
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// IT PWM
|
||||||
|
void TIM1_CC_IRQHandler(void) {
|
||||||
|
// Clean flag
|
||||||
|
TIM1 -> DIER &= ~TIM_DIER_CC1IE;
|
||||||
|
//Set bit
|
||||||
|
GPIOA -> ODR |= (0x1 << 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TIM1_UP_IRQHandler(void) {
|
||||||
|
// Clean flag
|
||||||
|
TIM1-> DIER &= ~TIM_DIER_TIE;
|
||||||
|
//Reset bit
|
||||||
|
GPIOA -> ODR &= ~(0x1 << 8);
|
||||||
|
};
|
||||||
85
Pilotes/Source/PWM.c
Executable file
85
Pilotes/Source/PWM.c
Executable file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#include "PWM.h"
|
||||||
|
|
||||||
|
void MyTimer_PWM(TIM_TypeDef * Timer , int Channel){
|
||||||
|
int pwrmd;
|
||||||
|
#if POWERMODE //Powermode 1
|
||||||
|
pwrmd = 0b110;
|
||||||
|
#else
|
||||||
|
pwrmd = 0b111; //Powermode 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (Channel == 1){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<4); //On clear les trois bits qui sont de pwm
|
||||||
|
Timer->CCMR1 |= (pwrmd<<4); //On affecte le powermode au bits de lecture pour le µ-controlleur
|
||||||
|
Timer->CCMR1 |= TIM_CCMR1_OC1PE; //Update preload, il n'affecte pas le valeur avant que la prochaine cycle
|
||||||
|
Timer->CCER = TIM_CCER_CC1E; //Enable le pin voulu basculer
|
||||||
|
}
|
||||||
|
else if (Channel == 2){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<12); //Le TIMx_CCMR1 configure deux channels, de bit [6:4] CH1, [14:12] CH2 (OC2M = Output Channel 2 )
|
||||||
|
Timer->CCMR1 |= (pwrmd<<12);
|
||||||
|
Timer->CCMR1 |= TIM_CCMR1_OC2PE;
|
||||||
|
Timer->CCER |= TIM_CCER_CC2E;
|
||||||
|
}
|
||||||
|
else if (Channel == 3){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<4);
|
||||||
|
Timer->CCMR2 |= (pwrmd<<4);
|
||||||
|
Timer->CCMR2 |= TIM_CCMR2_OC3PE;
|
||||||
|
Timer->CCER |= TIM_CCER_CC3E;
|
||||||
|
}
|
||||||
|
else if (Channel == 4){
|
||||||
|
Timer->CCMR1 &= ~(0b111<<12);
|
||||||
|
Timer->CCMR2 |= (pwrmd<<12);
|
||||||
|
Timer->CCMR2 |= TIM_CCMR2_OC4PE;
|
||||||
|
Timer->CCER |= TIM_CCER_CC4E;
|
||||||
|
}
|
||||||
|
|
||||||
|
//En dessous d'ici, on a l'aide du plus gentil chat que je connais
|
||||||
|
// Enable auto-reload preload -- //Ensures that your initial configuration — PWM mode, duty cycle, period — actually takes effect before the timer starts counting.
|
||||||
|
Timer->CR1 |= TIM_CR1_ARPE;
|
||||||
|
// Force update event to load ARR and CCR values immediately
|
||||||
|
Timer->EGR |= TIM_EGR_UG;
|
||||||
|
// Start the timer
|
||||||
|
Timer->CR1 |= TIM_CR1_CEN;
|
||||||
|
|
||||||
|
switch (Channel) {
|
||||||
|
case 1:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<0*4); GPIOA->CRH |= (0xA<<0*4); TIM1->BDTR |= 1<<15; }
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<0*4); GPIOA->CRL |= (0xA<<0*4);}
|
||||||
|
if (Timer == TIM3){GPIOA->CRL &= ~(0xF<<6*4); GPIOA->CRL |= (0xA<<6*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRL &= ~(0xF<<5*4); GPIOB->CRL |= (0xA<<5*4);}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<1*4); GPIOA->CRL |= (0xA<<1*4); TIM1->BDTR |= 1<<15;}
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<1*4); GPIOA->CRL |= (0xA<<1*4);}
|
||||||
|
if (Timer == TIM3){GPIOA->CRL &= ~(0xF<<7*4); GPIOA->CRL |= (0xA<<7*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRL &= ~(0xF<<7*4); GPIOB->CRL |= (0xA<<7*4);}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<2*4); GPIOA->CRH |= (0xA<<2*4); TIM1->BDTR |= 1<<15;}
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<2*4); GPIOA->CRL |= (0xA<<2*4);}
|
||||||
|
if (Timer == TIM3){GPIOB->CRL &= ~(0xF<<0*4); GPIOB->CRL |= (0xA<<0*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRH &= ~(0xF<<0*4); GPIOB->CRH |= (0xA<<0*4);}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (Timer == TIM1){GPIOA->CRH &= ~(0xF<<3*4); GPIOA->CRH |= (0xA<<3*4); TIM1->BDTR |= 1<<15;}
|
||||||
|
if (Timer == TIM2){GPIOA->CRL &= ~(0xF<<3*4); GPIOA->CRL |= (0xA<<3*4);}
|
||||||
|
if (Timer == TIM3){GPIOB->CRL &= ~(0xF<<1*4); GPIOB->CRL |= (0xA<<1*4);}
|
||||||
|
if (Timer == TIM4){GPIOB->CRH &= ~(0xF<<1*4); GPIOB->CRH |= (0xA<<1*4);}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Une fonction qui met le bon PWM voulu
|
||||||
|
int Set_DutyCycle_PWM(TIM_TypeDef *Timer, int Channel, int DutyC){
|
||||||
|
int CCR_VAL = (Timer -> ARR + 1) * DutyC / 100;
|
||||||
|
switch (Channel){
|
||||||
|
case 1: Timer->CCR1 = CCR_VAL;
|
||||||
|
case 2: Timer->CCR2 = CCR_VAL;
|
||||||
|
case 3: Timer->CCR3 = CCR_VAL;
|
||||||
|
case 4: Timer->CCR4 = CCR_VAL;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
Timer->EGR |= TIM_EGR_UG;
|
||||||
|
}
|
||||||
29
Pilotes/Source/Servo.c
Executable file
29
Pilotes/Source/Servo.c
Executable file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "Servo.h"
|
||||||
|
#include "DriverGPIO.h"
|
||||||
|
#include "PWM.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
void Servo_Moteur(int angle, TIM_TypeDef * Timer, int Channel){ // Controle du moteur
|
||||||
|
int dutyCycle = (5* angle + 5*90)/90; // 5-10 % Duty Cycle
|
||||||
|
Set_DutyCycle_PWM(Timer, Channel, dutyCycle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initServo(TIM_TypeDef * Timer, int Channel){ // Config du moteur servo
|
||||||
|
if (Timer == TIM4) {
|
||||||
|
EnableTimer(TIM4);
|
||||||
|
//MyTimer_Base_Init(TIM4, 20000 - 1, 71);
|
||||||
|
MyTimer_Base_Init(TIM4, 0xFFFF, 22); // Pour obtenir un période de 20 ms
|
||||||
|
|
||||||
|
if (Channel == 3){
|
||||||
|
MyGPIO_Init(GPIOB, 8, AltOut_Ppull); // Outut push pull alternate
|
||||||
|
MyTimer_PWM(TIM4, 3); //TIM4 CH3 pour PB8
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//printf("Cet pilôte n'existe pas");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//printf("Cet pilôte n'existe pas");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
27
Pilotes/Source/Timer.c
Executable file
27
Pilotes/Source/Timer.c
Executable file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
void MyTimer_Base_Init( TIM_TypeDef * Timer , unsigned short ValARR , unsigned short ValPSC ) { // Configuration du timer
|
||||||
|
Timer -> PSC=(ValPSC);
|
||||||
|
Timer-> ARR = (ValARR);
|
||||||
|
Timer->EGR |= TIM_EGR_UG;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void EnableTimer(TIM_TypeDef *Timer){
|
||||||
|
if(Timer == TIM2){
|
||||||
|
RCC -> APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||||
|
}
|
||||||
|
else if(Timer == TIM3){
|
||||||
|
RCC -> APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||||
|
}
|
||||||
|
else if(Timer == TIM4){
|
||||||
|
RCC -> APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||||
|
}
|
||||||
|
else if(Timer == TIM1){
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
}
|
||||||
|
}
|
||||||
30
README.md
30
README.md
|
|
@ -8,19 +8,29 @@ Bem vindo ao projeto veleiro de µcontroladores 4AE-SE 2025.
|
||||||
|
|
||||||
Welkom bij het microcontroller zeilbootproject 4AE-SE 2025.
|
Welkom bij het microcontroller zeilbootproject 4AE-SE 2025.
|
||||||
|
|
||||||
##Les groupes et résponsabilités sont :
|
## Partie girouette
|
||||||
>>Nicolas et Jarno : Envoi de UART et PWM dans la bonne fréquence (canal), pour relier le voilier à l'ecran.
|
Par Tiago et Oskar
|
||||||
|
|
||||||
>>Aleksander et Brage : Acceleromètre par I2C. La chûte du voilier envoie la commande de faire lâcher les voiles.
|
Cette branche contient la couche girouette et eventuellement une couche pilote.
|
||||||
|
|
||||||
>>Oskar et Tiago : Controler les voiles avec les données de la girouette.
|
## Tâches et pseudocode
|
||||||
|
|
||||||
>>En commun : Géstion de la pile avec l'ADC et clock interne avec CMOS.
|
Mesurer l'angle de girouette.
|
||||||
|
- EnableTimer
|
||||||
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fc2.staticflickr.com%2F6%2F5229%2F5681377563_4d4e274d51_b.jpg&f=1&nofb=1&ipt=cbe9495133b91e29c85ebc218df03cb9e58fc50148b045a8933418eb060146ad" alt="Le voilier Sørlandet au large des côtes canadiennes">
|
- Mesurer le delta cap
|
||||||
|
Fonctions à coder :
|
||||||
|
ConfigGironde
|
||||||
License : CC-BY-NC-SA 4.0
|
IcrementerTimer
|
||||||
|
EnableCounter (TIMx_CR1_CEN)
|
||||||
|
|
||||||
|
|
||||||
|
Contrôler les voiles
|
||||||
|
- Avec le PWM pour réaligner le bateau
|
||||||
|
|
||||||
|
1. Timer 1 (ref. 15.3.12 Manual STM32)
|
||||||
|
- Alimentation de la girouette
|
||||||
|
- Enable timer 2
|
||||||
|
- Créer 2 variables de GPIO input pour voie A et B
|
||||||
|
- Comparateur channel 1 et 2
|
||||||
|
- Mettre à disposistion un compteur avec un registre ou avec un variable
|
||||||
|
-
|
||||||
26
principal.c
Executable file
26
principal.c
Executable file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
#include <stdio.h> // Pour print
|
||||||
|
|
||||||
|
#include "Girouette.h"
|
||||||
|
#include "Servo.h"
|
||||||
|
|
||||||
|
|
||||||
|
//Variables
|
||||||
|
int angleVentVar;
|
||||||
|
int angleVoileVar;
|
||||||
|
|
||||||
|
int main ( void ){
|
||||||
|
// ---- Setup ------
|
||||||
|
//Servo.c
|
||||||
|
initServo(TIM4, 3);
|
||||||
|
// Giroutte.c
|
||||||
|
configEncoder(TIM2);
|
||||||
|
|
||||||
|
LocaliserZero();
|
||||||
|
// ----- Opération -----
|
||||||
|
while (1){
|
||||||
|
angleVentVar = angleVent(TIM2); // Récupérer l'angle de girouette
|
||||||
|
angleVoileVar = vent2voile(angleVentVar); // Transformer l'angle de girouette au l'angle des voiles souhaités
|
||||||
|
Servo_Moteur(angleVoileVar, TIM4, 3); // Faire bouger le moteur servo
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue