Разрабатываю для STM32 на Visual Studio, отладку произвожу при помощи плагина VisualGDB. Компилятор MInGW 12.3, отладчик OpenOCD.
Упрощенная структура моего проекта:
Суть проблемы: Когда я вызываю функцию "ModesInit()"
(там она инициализирует струкру "button s1", исходники ниже) в main функции, в SimpleButton_Check(&s1) влетает левый адрес, а не адрес указателя переменной s1. ОДНАКО, когда я просто копирую код внутри "ModesInit()" и всталяю его в main функцию, все работает нормально.
Ниже приведены исходники в упрощенном варианте (без настроек тактирования и т.п.)
main.c
#include "main.h"
int main(void) {
ModesInit();
while(true) {
if (SimpleButton_Check(&s1) == true) {
modeSelector++;
}
}
}
main.h
#pragma once
#include <stdbool.h>
#include "ModeDriver.h"
ModeDriver.h
#pragma once
#include <stdint.h>
#include "SimpleButton.h"
#define S1_BUS GPIOA
#define S1_PIN 9
#define S1_MODE 0 // 1 - Считается что кнопка нажата по повышению напряжения, 0 - по понижению
static uint8_t modeSelector;
static button s1;
void ModesInit(void);
ModeDriver.c
#include "ModeDriver.h"
void ModesInit(void) {
modeSelector = 0;
SimpleButton_Init(&s1, S1_BUS, S1_PIN, S1_MODE);
}
SimpleButton.h
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "stm32f10x_gpio.h"
// ============================= НАСТРОЙКИ =============================
#define Sn_TRIGGER_DELAY 20000 // ~60к = 1 мс. Сколько кнопка должна поймать нажатий чтобы активироваться (Защита от дребезга)
// =====================================================================
typedef struct button {
const GPIO_TypeDef *GPIO_home; // Шина
uint16_t pinBit; // Пин с учетом смещения // TODO: Надо бы сделать конст (он мешает в функции инита)?
bool modeUp; // 1 - Считается что кнопка нажата по повышению напряжения, 0 - по понижению // TODO: Надо бы сделать конст (он мешает в функции инита)?
uint16_t triggerConter; // Счетчик триггеров
uint16_t successCounter; // Счетчик сколько раз счетчик триггеров переполнился
uint16_t successInputs; // Сколько успешных циклов отсчета нажатий прошла кнопка (результат successCounter после отжатия)
} button;
void SimpleButton_Init(button *b, const GPIO_TypeDef *GPIO_home, const uint16_t pinNum, const bool modeUp);
bool SimpleButton_Check(button *b); // 1 - Данные можно забирать
#define SimpleButton_GetResult(b) b.successInputs // Макрос-функция для забора результата
SimpleButton.c
#include "SimpleButton.h"
void SimpleButton_Init(button *b, const GPIO_TypeDef *GPIO_home, const uint16_t pinNum, const bool modeUp) {
memset(b, 0x0, sizeof(button)); // Очищаем от лишнего
b->GPIO_home = GPIO_home;
b->pinBit = (uint16_t)(0b1 << pinNum);
b->modeUp = modeUp;
}
bool SimpleButton_Check(button *b) {
bool isPortActive = b->GPIO_home->IDR & b->pinBit; // Напряжение на порту есть?
if ((isPortActive && b->modeUp) || (!isPortActive && !(b->modeUp))) { // Если есть напряжение на порт, а режим выбран "срабатывание по возрастанию", ИЛИ нет напряжения, а режим "по понижению"
if (++b->triggerConter > Sn_TRIGGER_DELAY) { // Если число тактов достаточное
b->triggerConter = 0;
b->successCounter++; // То это не залипание, а нажатие
}
} else {
if (b->successCounter > 0) { // Ты отжал кнопку, и это не дребезг?
b->successInputs = b->successCounter;
b->successCounter = 0;
return true; // Можно забирать
}
b->triggerConter = 0;
}
return false; // Данные не готовы или не обработаны
}