Présentation du système
Cet article détaille la mise en œuvre d'une fonctionnalité de communication série dans un projet embarqué, similaire à un défi technique. Le système gère l'entrée et la sortie de véhicules dans un parking via des messages UART, incluant la validation des données, l'extraction d'informaitons, et le calcul des frais.
Analyse des exigences
Les composants clés tels que les LED, les boutons et l'affichage LCD sont gérés avec des modèles standards. L'accent est mis sur le traitement de l'interface série :
- Validation du format des données reçues.
- Vérification de la logique des opérations.
- Décodage des chaînes pour l'enregistrement ou la recherche de véhicules.
- Gestion des entrées et sorties, incluant le calcul du temps et des frais.
Les fonctions de manipulation de chaînes utilisées comprennent strstr, strcpy, strcmp, et sprintf pour rechercher, copier, comparer et foramter des chaînes.
Implémentation du code
Structure de données pour le parking
#define MAX_SLOTS 8
typedef struct {
char vehicle_id[5];
uint8_t entry_year;
uint8_t entry_month;
uint8_t entry_day;
uint8_t entry_hour;
uint8_t entry_minute;
uint8_t entry_second;
uint8_t occupied;
} ParkingSlot;
ParkingSlot parking_slots[MAX_SLOTS];
// Initialisation des emplacements
for (int index = 0; index < MAX_SLOTS; index++) {
memset(&parking_slots[index], 0, sizeof(ParkingSlot));
}
Validation du format des messages
uint8_t ValidateMessageFormat(const char *message) {
if (strlen(message) != 24) {
return 0;
}
char *type_ptr = strstr(message, "CNBR");
char *alt_type_ptr = strstr(message, "VNBR");
if (type_ptr == NULL && alt_type_ptr == NULL) {
return 0;
}
char *first_colon = strstr(message, ":");
char *second_colon = strstr(first_colon + 1, ":");
if (second_colon - first_colon != 5) {
return 0;
}
return 1;
}
Extraction des informations du message
void ParseMessageData(const char *message, char *vehicle_id, uint8_t *year, uint8_t *month,
uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second, char *vehicle_type) {
*year = (message[10] - '0') * 10 + (message[11] - '0');
*month = (message[12] - '0') * 10 + (message[13] - '0');
*day = (message[14] - '0') * 10 + (message[15] - '0');
*hour = (message[16] - '0') * 10 + (message[17] - '0');
*minute = (message[18] - '0') * 10 + (message[19] - '0');
*second = (message[20] - '0') * 10 + (message[21] - '0');
char *first_colon = strstr(message, ":");
char *second_colon = strstr(first_colon + 1, ":");
*second_colon = '\0';
strcpy(vehicle_id, first_colon + 1);
*first_colon = '\0';
strcpy(vehicle_type, message);
}
Traitement des entrées et sorties
extern const float cnbr_rate;
extern const float vnbr_rate;
void ProcessVehicleOperation(const char *message) {
uint8_t year, month, day, hour, minute, second;
char vehicle_id[5], vehicle_type[5];
char response_buffer[50];
float total_fee;
int duration_seconds;
ParseMessageData(message, vehicle_id, &year, &month, &day, &hour, &minute, &second, vehicle_type);
for (int slot = 0; slot < MAX_SLOTS; slot++) {
if (strcmp(vehicle_id, parking_slots[slot].vehicle_id) == 0) {
int time_diff = (year - parking_slots[slot].entry_year) * 365 * 24 * 3600 +
(month - parking_slots[slot].entry_month) * 30 * 24 * 3600 +
(day - parking_slots[slot].entry_day) * 24 * 3600 +
(hour - parking_slots[slot].entry_hour) * 3600 +
(minute - parking_slots[slot].entry_minute) * 60 +
(second - parking_slots[slot].entry_second);
if (time_diff < 0) {
sprintf(response_buffer, "Error\r\n");
} else {
duration_seconds = (time_diff + 3599) / 3600;
if (vehicle_type[0] == 'C') {
total_fee = duration_seconds * cnbr_rate;
} else {
total_fee = duration_seconds * vnbr_rate;
}
sprintf(response_buffer, "%s:%s:%d:%.2f\r\n", vehicle_type, vehicle_id, duration_seconds, total_fee);
memset(&parking_slots[slot], 0, sizeof(ParkingSlot));
}
HAL_UART_Transmit(&huart1, (uint8_t *)response_buffer, strlen(response_buffer), 0xFFFF);
return;
}
}
for (int slot = 0; slot < MAX_SLOTS; slot++) {
if (parking_slots[slot].occupied == 0) {
strcpy(parking_slots[slot].vehicle_id, vehicle_id);
parking_slots[slot].entry_year = year;
parking_slots[slot].entry_month = month;
parking_slots[slot].entry_day = day;
parking_slots[slot].entry_hour = hour;
parking_slots[slot].entry_minute = minute;
parking_slots[slot].entry_second = second;
parking_slots[slot].occupied = 1;
break;
}
}
}
Programme principle de l'interface série
extern volatile uint8_t uart_rx_flag;
extern uint8_t uart_rx_buffer[32];
void UART_ProcessReceivedData(void) {
if (uart_rx_flag == 1) {
if (!ValidateMessageFormat((const char *)uart_rx_buffer)) {
HAL_UART_Transmit(&huart1, (uint8_t *)"Error\r\n", 7, 0xFFFF);
} else {
ProcessVehicleOperation((const char *)uart_rx_buffer);
}
memset(uart_rx_buffer, 0, sizeof(uart_rx_buffer));
uart_rx_flag = 0;
}
}