331 lines
8.8 KiB
C
331 lines
8.8 KiB
C
// A COMPLETER
|
|
|
|
/*
|
|
Service permettant de chornométrer jusqu'à 59mn 59s 99 1/100
|
|
Utilise un timer au choix (TIMER1 à TIMER4).
|
|
Utilise la lib MyTimers.h /.c
|
|
*/
|
|
|
|
/* GSM -> SMS
|
|
driver*/
|
|
|
|
|
|
#include "Chrono.h" //header du chrono
|
|
#include "MyTimer.h" //header du timer
|
|
#include "stm32f1xx_ll_gpio.h" // GPIO
|
|
#include "stm32f1xx_ll_bus.h" // CLock
|
|
#include "stm32f1xx_ll_utils.h" //Pour la fonction mDelay
|
|
#include "stm32f1xx_ll_usart.h" //USART
|
|
#define TAILLE_MESSAGE 9 //Taille de chaques messages envoyé (xx:xx:xx: => 9 digits)
|
|
|
|
// variable privée de type Time qui mémorise la durée mesurée
|
|
static Time Chrono_Time; // rem : static rend la visibilité de la variable Chrono_Time limitée à ce fichier
|
|
|
|
// variable privée qui mémorise pour le module le timer utilisé par le module
|
|
static TIM_TypeDef * Chrono_Timer=TIM1; // init par défaut au cas où l'utilisateur ne lance pas Chrono_Conf avant toute autre fct.
|
|
|
|
// Variable globale qui sert de drapeau de communication entre le BG et chronoTask10ms (et reset)
|
|
static char drapeau = 0;
|
|
|
|
// Structure pour gérer la transmission du message
|
|
struct t_transmission {
|
|
char message[TAILLE_MESSAGE];// Le message lui même
|
|
char end_of_message;// le caractère de fin (Retour Chariot)
|
|
int position;// La position du caractere a envoyer
|
|
char first_appel;// Booléen sur le premier appel (si true, lire l'heure et construire le message)
|
|
};
|
|
|
|
/**
|
|
* @brief Initialise une structure t_transmission.
|
|
* @note Structure initialisée : (message -> 00:00:00:, end_of_message -> 0x0D, position -> 0, first_appel -> 1)
|
|
* @param @ de la structure a initialiser
|
|
* @retval None
|
|
*/
|
|
void init_t_transmission(struct t_transmission * transmission) {
|
|
int i;
|
|
for (i=0; i<TAILLE_MESSAGE; i++) {
|
|
if (!((i+1) % 3)){
|
|
transmission->message[i] = ':';
|
|
} else {
|
|
transmission->message[i] = 0;
|
|
}
|
|
}
|
|
transmission->end_of_message = 0x0D;
|
|
transmission->position = 0;
|
|
transmission->first_appel = 1;
|
|
}
|
|
|
|
/**
|
|
* @brief Convertir un entier de 2 chiffres en un string.
|
|
* @note UNIQUEMENT DES ENTIERS DE 2 DIGITS (eventuellement 1 digit).
|
|
* @param n : l'entier a convertir
|
|
* buffer : @ du buffer ou stocker la conversion
|
|
* @retval None
|
|
*/
|
|
void itoa(int n, char * buffer) {
|
|
buffer[0] = (n/10) + 0x30;
|
|
buffer[1] = (n % 10) + 0x30;
|
|
}
|
|
|
|
/**
|
|
* @brief Ecrit l'heure dans une t_transmission.
|
|
* @note L'heure est inscrite dans le champs message de la structure
|
|
* @param @ de la structure dont on souhaite modifier le message
|
|
* @retval None
|
|
*/
|
|
void recuperer_heure(struct t_transmission * transmission) {
|
|
itoa(Chrono_Time.Min, transmission->message);
|
|
itoa(Chrono_Time.Sec, &(transmission->message[3]));
|
|
itoa(Chrono_Time.Hund, &(transmission->message[6]));
|
|
}
|
|
|
|
// déclaration callback appelé toute les 10ms
|
|
void Chrono_Task_10ms(void);
|
|
|
|
/**
|
|
* @brief Configure les IOs utiles pour les boutons et la LED.
|
|
* @note Bouton Reset : PinC13 -> floating input
|
|
Bouton Start/Stop : PinC8 -> floating input
|
|
LED : PinC10 -> Opendrain 2MHz
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
void Chrono_Conf_io(void) {
|
|
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
|
|
|
|
LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_8, LL_GPIO_MODE_FLOATING);
|
|
LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_13, LL_GPIO_MODE_FLOATING);
|
|
LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_10, LL_GPIO_MODE_OUTPUT_2MHz);
|
|
LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_10, LL_GPIO_OUTPUT_OPENDRAIN);
|
|
LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_10); // Car logique négative
|
|
}
|
|
|
|
/**
|
|
* @brief Configure les USARTs
|
|
* @note Data : 8bits
|
|
Vitesse : 19200Bd
|
|
Parity : None
|
|
Stop Bit : 1
|
|
Sens : Tx only
|
|
GPIOs relatif a TX initialisés
|
|
* @param USARTx : USART a configurer
|
|
* @retval None
|
|
*/
|
|
void Chrono_Conf_UART(USART_TypeDef * USARTx) {
|
|
if (USARTx == USART1) {
|
|
LL_APB2_GRP1_EnableClock(RCC_APB2ENR_USART1EN);// ON la clock
|
|
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); //ON la clock du port de TX
|
|
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE); //ConfigTX
|
|
} else if (USARTx == USART2) {
|
|
LL_APB1_GRP1_EnableClock(RCC_APB1ENR_USART2EN); // ON la clock
|
|
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); //ON la clock du port de TX
|
|
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_2, LL_GPIO_MODE_ALTERNATE); //ConfigTX
|
|
} else if (USARTx == USART3) {
|
|
LL_APB1_GRP1_EnableClock(RCC_APB1ENR_USART3EN);// ON la clock
|
|
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB); //ON la clock du port de TX
|
|
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_10, LL_GPIO_MODE_ALTERNATE); //ConfigTX
|
|
}
|
|
|
|
LL_USART_InitTypeDef USART_InitStruct;
|
|
LL_USART_StructInit(&USART_InitStruct);
|
|
USART_InitStruct.BaudRate = 19200; //Set Baud rate -> 19200Bd
|
|
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; //Set data width -> 8bits
|
|
USART_InitStruct.Parity = LL_USART_PARITY_NONE;// Disable Parity
|
|
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;// Set stop bit -> 1
|
|
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX;//Set sens -> TX Only
|
|
LL_USART_Init(USARTx, &USART_InitStruct);// Applique les modifs
|
|
LL_USART_Enable(USARTx);// Rend l'USART enable A FAIRE EN DERNIER
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Gere les taches de fond : USART et Boutons
|
|
* @param USARTx : USART sur laquelle on souhaite discuter (doit avoir été initialisée)
|
|
* @retval None
|
|
*/
|
|
void Chrono_Background(USART_TypeDef * USARTx) {
|
|
|
|
// GESTION DES BOUTONS
|
|
static int isAllume = 1;
|
|
static int Start_Stop_Button_Last_State = 0;
|
|
static int Reset_Button_Last_State = 1;
|
|
|
|
if (LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_8)) {
|
|
Start_Stop_Button_Last_State = 1;
|
|
}
|
|
|
|
if (!LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_8) && Start_Stop_Button_Last_State) {
|
|
Start_Stop_Button_Last_State = 0;
|
|
if (isAllume) {
|
|
isAllume = 0;
|
|
Chrono_Stop();
|
|
} else {
|
|
isAllume = 1;
|
|
Chrono_Start();
|
|
}
|
|
LL_mDelay(1);
|
|
}
|
|
|
|
if (!LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_13)) {
|
|
Reset_Button_Last_State = 0;
|
|
}
|
|
|
|
if (LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_13) && !Reset_Button_Last_State) {
|
|
Reset_Button_Last_State = 1;
|
|
Chrono_Reset();
|
|
if (isAllume) {
|
|
Chrono_Start();
|
|
}
|
|
}
|
|
|
|
//GESTION DE L'AFFICHAGE
|
|
static struct t_transmission transmission = {"", 0x0D, 0, 1};
|
|
|
|
if (drapeau) {
|
|
if (transmission.first_appel) {
|
|
recuperer_heure(&transmission);
|
|
transmission.first_appel = 0;
|
|
}
|
|
if (LL_USART_IsActiveFlag_TXE(USARTx)) {
|
|
if (transmission.position < TAILLE_MESSAGE) {
|
|
LL_USART_TransmitData8(USARTx, (uint8_t)(transmission.message[transmission.position]));
|
|
transmission.position += 1;
|
|
} else {
|
|
LL_USART_TransmitData8(USARTx, (uint8_t)(transmission.end_of_message));
|
|
init_t_transmission(&transmission);
|
|
drapeau = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Configure le chronomètre (Timer, IO, USART).
|
|
* @note A lancer avant toute autre fonction.
|
|
* @param Timer : indique le timer à utiliser par le chronomètre, TIM1, TIM2, TIM3 ou TIM4
|
|
* USARTx : indique l'USART a utiliser pour communiquer avec le PC
|
|
* @retval None
|
|
*/
|
|
void Chrono_Conf(TIM_TypeDef * Timer, USART_TypeDef * USARTx)
|
|
{
|
|
// Reset Time
|
|
Chrono_Time.Hund=0;
|
|
Chrono_Time.Sec=0;
|
|
Chrono_Time.Min=0;
|
|
|
|
// Fixation du Timer
|
|
Chrono_Timer=Timer;
|
|
|
|
// Réglage Timer pour un débordement à 10ms
|
|
MyTimer_Conf(Chrono_Timer,999, 719);
|
|
|
|
// Configuration des IO
|
|
Chrono_Conf_io();
|
|
|
|
// Config du UART
|
|
Chrono_Conf_UART(USARTx);
|
|
|
|
// LES IT TOUJOURS A LA FIN
|
|
// Réglage interruption du Timer avec callback : Chrono_Task_10ms()
|
|
MyTimer_IT_Conf(Chrono_Timer, Chrono_Task_10ms,3);
|
|
|
|
// Validation IT
|
|
MyTimer_IT_Enable(Chrono_Timer);
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Démarre le chronomètre.
|
|
* @note si la durée dépasse 59mn 59sec 99 Hund, elle est remise à zéro et repart
|
|
* @param Aucun
|
|
* @retval Aucun
|
|
*/
|
|
void Chrono_Start(void)
|
|
{
|
|
MyTimer_Start(Chrono_Timer);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Arrête le chronomètre.
|
|
* @note
|
|
* @param Aucun
|
|
* @retval Aucun
|
|
*/
|
|
void Chrono_Stop(void)
|
|
{
|
|
MyTimer_Stop(Chrono_Timer);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Remet le chronomètre à 0
|
|
* @note
|
|
* @param Aucun
|
|
* @retval Aucun
|
|
*/
|
|
void Chrono_Reset(void)
|
|
{
|
|
// Arrêt Chrono
|
|
MyTimer_Stop(Chrono_Timer);
|
|
|
|
// Reset Time
|
|
Chrono_Time.Hund=0;
|
|
Chrono_Time.Sec=0;
|
|
Chrono_Time.Min=0;
|
|
|
|
// Previens transimition OK
|
|
drapeau = 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Renvoie l'adresse de la variable Time privée gérée dans le module Chrono.c
|
|
* @note
|
|
* @param Aucun
|
|
* @retval adresse de la variable Time
|
|
*/
|
|
Time * Chrono_Read(void)
|
|
{
|
|
return &Chrono_Time;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* @brief incrémente la variable privée Chron_Time modulo 60mn
|
|
* @note
|
|
* @param Aucun
|
|
* @retval Aucun
|
|
*/
|
|
void Chrono_Task_10ms(void)
|
|
{
|
|
static int LED_OFF = 1;
|
|
Chrono_Time.Hund++;
|
|
if (Chrono_Time.Hund==100)
|
|
{
|
|
Chrono_Time.Sec++;
|
|
Chrono_Time.Hund=0;
|
|
if (LED_OFF) {
|
|
LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_10);
|
|
LED_OFF = 0;
|
|
} else {
|
|
LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_10);
|
|
LED_OFF = 1;
|
|
}
|
|
}
|
|
if (Chrono_Time.Sec==60)
|
|
{
|
|
Chrono_Time.Min++;
|
|
Chrono_Time.Sec=0;
|
|
}
|
|
if (Chrono_Time.Min==60)
|
|
{
|
|
Chrono_Time.Hund=0;
|
|
}
|
|
drapeau = 1;
|
|
}
|
|
|
|
|