// 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; imessage[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; }