Перейти к содержанию

Инициализация структуры кнопки в STM32 - C (СИ)


Nicollo

Рекомендуемые сообщения

Добрый день.

Пишу программу под STM32f103, в девайсе есть 2 кнопки, подключены напрямую к ваходам GPIOA (0 и 1);

Хочу сделать по красоте, написал структуру для кнопок: 

typedef struct {
	GPIO_TypeDef* GPIOx;
	uint16_t GPIO_Pin;
	uint8_t isPressed;
	uint8_t ttl;
} Button;

И глобальную структуру:

typedef struct {
	...
	Button* ModeButton; // mode button status
	...
} GlobalRegister;

GlobalRegister Register;

Пример инициализации 1 кнопки:

void main() {
	...
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    Button ModeButton;
    ModeButton.GPIOx = GPIOA;
    ModeButton.GPIO_Pin = GPIO_Pin_0;
    ModeButton.ttl = 0x00;
    ModeButton.isPressed = RESET;

    Register.ModeButton = &ModeButton;
	...
}

После, в обработчике прерываний по таймеру, я пытаюсь проверить нажатие кнопки:

void BUTTON_Check(Button *Button){ ... }


void SysTick_Handler(void){
	BUTTON_Check(Register.ModeButton);
	....
}

Но указатель уже битый, не могу получить объект кнопки.

Изменено пользователем Nicollo
Ссылка на комментарий
Поделиться на другие сайты

Извращяюсь - делаю защиту от антидребезга, для каждой кнопки:

т.е. после того как обнаружилось нажатие выжидаю некоторое время и если после него кнопка осталась нажатой - засчитываю нажатие.

#define BUTTON_DELAY 0x0F

void BUTTON_Check(Button *Button) {
	/**
	 * Check if button is pressed
	 */
	if ((Button->GPIOx->IDR & Button->GPIO_Pin) == (uint32_t) Bit_RESET && Button->ttl == 0x00) {
		Button->ttl ++;

		return;
	}

	/**
	 * Wait for a while to skip button rattling
	 */
	if (Button->ttl > 0x00 && Button->ttl < BUTTON_DELAY) {
		Button->ttl ++;

		return ;
	}

	if (Button->ttl == BUTTON_DELAY) {
		if ((Button->GPIOx->IDR & Button->GPIO_Pin) == (uint32_t) Bit_RESET) {
			Button->ttl ++;
		} else {
			Button->ttl = 0x00;
		}

		return ;
	}
	if ((Button->GPIOx->IDR & Button->GPIO_Pin) == (uint32_t) Bit_SET && Button->ttl == (BUTTON_DELAY + 1)) {
		Button->isPressed = SET;

		return ;
	}
}
Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Опрашивать кнопки в таймере с интервалом 100мс, либо в таймере крутить счетчик и опрашивать в главном цикле, либо сделать функцию delay на SysTick и опять же опрашивать в главном цикле. Никакие структуры там даром не нужны. 

Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Добрый день, а еще хотел спросить, есть ли в STM32F103  защита от дребезга энкодера?

Использую входы 3го таймера

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    //Channels TIM3_CH1, TIM3_CH2 as pull up inputs
    GPIO_InitTypeDef GPIO_InitDef;
    GPIO_InitDef.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitDef.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitDef.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &GPIO_InitDef);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    /* TIM3 tunning*/
    TIM_TimeBaseInitTypeDef TIMER_InitStructure;
    TIM_TimeBaseStructInit(&TIMER_InitStructure);
    // set TIM_Period - encoder rotate count reset
    TIMER_InitStructure.TIM_Period = 4;
    // backward and forward count
    TIMER_InitStructure.TIM_CounterMode = TIM_CounterMode_Up | TIM_CounterMode_Down;
    TIM_TimeBaseInit(TIM3, &TIMER_InitStructure);

    /* Tuning Encoder Interface */
    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM3, ENABLE);

    NVIC_EnableIRQ(TIM3_IRQn);

Направление определяю вот так:

(TIM3->CR1 & TIM_CR1_DIR ? -1 : 1)

Иногда детектится противоположное направление.

Можно ли как-то это решить программно? Или вешать RC фильтр?

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...
On 5/29/2017 at 5:13 PM, Nicollo said:

Button ModeButton;

Register.ModeButton = &ModeButton;

Вы делаете объект (экземпляр) структуры в функцию main, т.е. в стэк-е, а после адрес этой структуры присваиваете глобальному указателю. После выхода из функции (или переключение контекста, если у вас ОСРВ = переключение стэка) этот объект стирается, и у вас в глобальной структуре (Register) висячий указатель.

Если хотите исправить это, либо сделайте в структуре Register не указатель "Button* ModeButton;", а структуру "Button ModeButton;", и инициализацию делайте как "Register.ModeButton.GPIOx = GPIOA;" ...
Второй вариант это оставить ModeButton как указатель, а в функции инициализации выделить Button через malloc/calloc/.. присвоить все необходимые поля этому указателю, а его адрес записать в структуру Register.ModeButton (и по окончанию работы с этим полем освободить память).

Для примера:

void init_buttons(void)
{
	Button *ModeButton = malloc(sizeof(Button));
	ModeButton->GPIOx = GPIOA;
	ModeButton->GPIO_Pin = GPIO_Pin_0;
	ModeButton->ttl = 0x00;
	ModeButton->isPressed = RESET;
	...
	Register->ModeButton = ModeButton;
}

void deinit_buttons(void)
{
	free(Register->ModeButton);
}

 

Ссылка на комментарий
Поделиться на другие сайты

единственное но, юзать динамику во встройке очень затратно по ресурсам

да и нужно ли вообще, если количество источников и исполнителей всегда заранее известно?

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

Не понятен вообще смысл использования таких структур. Особенно, если учесть то, что большая часть настройки производится один раз при старте МК...

Ссылка на комментарий
Поделиться на другие сайты

ну я о том же. Эмбедед системы практически всегда имеют однозначную и известную конфигурацию

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

Бывают случаю когда на одном и том-же железе могут быть две и более софтовых конфигураций (для примера по настройкам из еепром-а).
Для примера: у вас есть 2 порта (UART, или SPI, или ...), и 3 возможных датчика которые могут подключатся к этим портам, и для каждого варианта подключения у вас будет разная конфигурация (скажем для настройки под заказчик).

Но соглашусь с вами, что в контроллерах редко используют динамически выделенную память, так как ее в любой момент может не хватить а это может привести к непредсказуемым последствиям.

Ссылка на комментарий
Поделиться на другие сайты

Только что, gindul сказал:

Для примера: у вас есть 2 порта (UART, или SPI, или ...), и 3 возможных датчика которые могут подключатся к этим портам, и для каждого варианта подключения у вас будет разная конфигурация (скажем для настройки под заказчик).

Можно заюзать дефайны и не париться. В том же UART вряд ли понадобится изменить что-то кроме скорости, а это всего один регистр.

Ссылка на комментарий
Поделиться на другие сайты

при возможности выбора, я бы использовал любой доступный способ программирования конфигурации периферии, но динамику в последнюю очередь

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

21 hours ago, BARS_ said:

Можно заюзать дефайны и не париться.

Вы предлагаете разные прошивки для разных целей. А я говорю об одной прошивке на все устройства, но настраивать вид устройства при установке у заказчика. Установку устройства проводят не программисты, а прошивку не роздают направо и налево :)
В динамической выделении памяти нет ничего плохого, но я соглашусь с тем что это надо использовать ее в последнюю очередь.

Иногда проделывают и такое: выделяют большой статический масив, и по мере необходимости используют из него куски как динамическую память. Это позволяет узнать во время компиляции сколько память у тебя есть свободной, а работать как с динамической :)

Ссылка на комментарий
Поделиться на другие сайты

я для кнопок и медленной фигни делаю так: беру uint8_t где старшие 4 бита это номер порта, ладшие - номер пина, и не надо тратить память на всякие структуры, при этом динамически можно переприсваивать их, в отличии от дефайнов полезно для применения в классах, С++ намного лучше обычного С как по мне (без динамики конечно и прочих радостей).  

Ссылка на комментарий
Поделиться на другие сайты

Так а в чем проблема тоже самое сделать для дефайнов? Что либо поменять занимает несколько секунд. Один фиг надо лезть и менять настройку портов, хоть так, хоть эдак.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...