Nicollo

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

31 сообщение в этой теме

Nicollo    1

Добрый день.

Пишу программу под 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

Поделиться сообщением


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

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
BARS_    529

Зачем такие извращения? Закинуть их в define и не париться:

#define BUTTON (GPIOA->IDR & GPIO_IDR_IDR0)

Опрашиваем состояние BUTTON, получаем 0 или 1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nicollo    1

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

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

#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 ;
	}
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    529

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nicollo    1

Я в таймере и опрашиваю, но время для антидребезга отслеживаю по BUTTON_DELAY.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nicollo    1

Добрый день, а еще хотел спросить, есть ли в 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 фильтр?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gindul    3
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    1 163

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    529

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 163

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gindul    3

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    529
Только что, gindul сказал:

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 163

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gindul    3
21 hours ago, BARS_ said:

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    529
Только что, gindul сказал:

А я говорю об одной прошивке на все устройства

Опять же, как в этом помогают структуры?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    529
Только что, IMXO сказал:

как то так

Ровно тоже самое делается без структур...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 051

таки да, но сними удобней...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    529

Лично я никакого удобства там не вижу...

Поделиться сообщением


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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    529

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

Поделиться сообщением


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

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

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

  Разрешено не более 75 смайлов.

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

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

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

Загрузка...

  • Сообщения

    • К цифровому, еще хотите добавить шум ДС/ДС? Если уж так не можете отфильтровать. Если принципиально двухполярка, примените низковольтный ОУ и поделите  5 В банальным делителем пополам.  
    • Можно добавить УЗИП на вводе и по желанию на группы в щиток. В некоторых поселениях без такой штуки в ВУ не подключат к ЛЭП . Говорят в нутре у них мощные варисторы и даже от попадания молнии защищают.
    • @Pont 007 Я, признаться, не знаю зачем автору темы это нужно, ну уж коли спросил..., а питание с аудиокарт не видел ни разу, разумеется брать +5 вольт с материнки просто так нельзя, помехи будут жуть. @pips Конечно я работал и с этими микросхемами ещё в советской реинкарнации, названия уж не помню. Что касается тактовой частоты ещё раз говорю она здесь особой роли не играет, все равно по питанию как с +5 так и с -5 надо ставить фильтры. На мой взгляд лучше это LC фильтры, индуктивность типа такой или такой выводом от источника напряжения, а другим выводом на  питание ОУ и конденсатор на землю микрофарад 220 + керамика 0,1 мкФ. Просто рисовать неохота, просто ведь.
    • В "Моделисте-конструкторе" нечто подобное делали - трансформатор для сварочника из электродвижка:   МК 8-1992, стр. 19 МК 1-1996, стр. 11 МК 9-2000, стр. 11
    • wm5102e где стоит: Lenovo Yoga Tablet 2 10-51; Samsung Galaxy S4 GT-I9500; Meizu MX3;
    • @o_l_e_g  Спасибо. Но это вам в соседнюю мою тему, я там с этим вопросом уже обсуждал. )))) Если кратко, то весь цифровой бред (шум питания) который по USB питанию попадает на вход усилителя. А я не знаю как его фильтровать нормально. Да и вообще костыль всё это.   В общем эту тему средней точки, пожалуйста тут не развивайте, если хотите помочь молости прошу, Тема моя ниже по ссылке:   Спасибо за совет, но я что буду приходить к каждому с паяльником со словами "давайте мы сейчас ваш комп разберем, попаяем, а потом продолжим".  В общем ваши предлоложения касательно зачем мне это нужно были не верны, спасибо.