rusyska55011
@rusyska55011

Почему передается некорректный адрес указателя в функцию?

Разрабатываю для STM32 на Visual Studio, отладку произвожу при помощи плагина VisualGDB. Компилятор MInGW 12.3, отладчик OpenOCD.

Упрощенная структура моего проекта:
66114182ce940903216819.png

Суть проблемы: Когда я вызываю функцию "ModesInit()" (там она инициализирует струкру "button s1", исходники ниже) в main функции, в SimpleButton_Check(&s1) влетает левый адрес, а не адрес указателя переменной s1. ОДНАКО, когда я просто копирую код внутри "ModesInit()" и всталяю его в main функцию, все работает нормально.

661143d02366e000224326.png
Ниже приведены исходники в упрощенном варианте (без настроек тактирования и т.п.)

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; // Данные не готовы или не обработаны
}
  • Вопрос задан
  • 62 просмотра
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Потому что переменная со спецификатором static локальна для единицы трансляции. Ты написал static button s1; в заголовочном файле, а это значит, что каждая единица трансляции в которую ты подключил этот файл получит свой собственный, независимый экземпляр переменной s1. Функция ModesInit инициализирует s1 из ModeDriver.o, а s1 из main.o останется неинициализированным.

Исправить это можно заменив static на extern в заголовочном файле, а в одном из исходников добавив определение для переменной -- button s1;.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы