Страница на этапе разработки
Сегодня мы рассмотрим работу структуры, что это такое и как ее можно использовать.
Описание структуры:
struct имя_типа{
тип_1 элемент_1;
тип_2 элемент_2;
…
тип_n элемент_n;
};
Смотря на описание тяжело понять что с ней делать и как ее можно использовать.
Для понимания структуры мы рассмотрим несколько примеров как ее можно использовать. Сам алгоритм программы для нас не важен, мы рассматриваем пример использования. И так, рассмотрим на примере светодиодов: допустим у нас есть два светодиода которыми мы хотим управлять один находится на PC13 второй на PA5. Для переключения их состояния мы используем функцию:
HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET/SET);
Для переключения состояния светодиодов нам надо явно указывать порт и номер ножки и логическое состояние. Если у Вас большой программный код, можно допустить ошибку в указании данных, и тут на помощь нам приходит структура. Создадим нужную структуру нам:
typedef struct {
GPIO_TypeDef *port; // указатель на порт (GPIOA, GPIOB, …)
uint16_t pin; // номер пина (GPIO_PIN_5, …)
uint8_t state; // логическое состояние (0/1)
} Led_t;
Теперь используем нашу структуру:
Led_t led1 = {GPIOC, GPIO_PIN_13, 0}; // светодиод на PC13
Led_t led2 = {GPIOA, GPIO_PIN_5, 0}; //светодиод на PA5
Функции для работы со структурой:
void Led_On(Led_t *led) {
HAL_GPIO_WritePin(led->port, led->pin, GPIO_PIN_SET);
led->state = 1;
}
void Led_Off(Led_t *led) {
HAL_GPIO_WritePin(led->port, led->pin, GPIO_PIN_RESET);
led->state = 0;
}
void Led_Toggle(Led_t *led) {
HAL_GPIO_TogglePin(led->port, led->pin);
led->state = !led->state;
}
Теперь напишем основной программный код, где мы будем использовать структуру:
//объявим структуру
Led_t led1 = {GPIOC, GPIO_PIN_13, 0};
Led_t led2 = {GPIOA, GPIO_PIN_5, 0};
И в рабочем цикле опишем работу наших функций:
Led_Toggle(&led1);
HAL_Delay(500);
Led_On(&led2);
HAL_Delay(200);
Led_Off(&led2);
HAL_Delay(200);
Тоже самое мы можем сделать например для чтения данных с кнопки:
typedef struct {
GPIO_TypeDef *port; // порт кнопки
uint16_t pin; // пин кнопки
uint8_t state; // текущее устойчивое состояние (0 или 1)
uint8_t lastState; // последнее прочитанное состояние
uint32_t lastDebounceTime; // время последнего изменения
uint32_t debounceDelay; // задержка для антидребезга (мс)
} Button_t;
Функция для работы с нашей кнопкой:
uint8_t Button_Read(Button_t *btn){
uint8_t reading = HAL_GPIO_ReadPin(btn->port, btn->pin);
if (reading != btn->lastState) {
btn->lastDebounceTime = HAL_GetTick(); // запоминаем время
}
if ((HAL_GetTick() — btn->lastDebounceTime) > btn->debounceDelay) {
if (reading != btn->state) {
btn->state = reading;
}
}
btn->lastState = reading;
return btn->state;
}
Инициализация нашей кнопки:
Button_t button1 = {GPIOA, GPIO_PIN_0, 0, 0, 0, 50};// PA0, 50 мс антидребезг
Использование в программном коде:
Button_t button1 = {GPIOA, GPIO_PIN_0, 0, 0, 0, 50}; // кнопка на PA0
Led_t led1 = {GPIOC, GPIO_PIN_13, 0}; // LED на PC13
while (1) {
if (Button_Read(&button1)) {
Led_On(&led1);
} else {
Led_Off(&led1);
}
}
Кроме удобства в использовании структуры когда у Вас много однотипных параметров, структуру можно использовать в подпрограммах когда нужно вернуть больше одного значения без использования массивов.