• Объявления

    • admin

      Просьба всем принять участие!   24.11.2017

      На форуме разыгрывается спектроанализатор Arinst SSA-TG LC (цена 18500 руб). Просьба всем перейти по ссылке ниже и принять участие!
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_    573

Зачем такие извращения? Закинуть их в 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_    573

Опрашивать кнопки в таймере с интервалом 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 199

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

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

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

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


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

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

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


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

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

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


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

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

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

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


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

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

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

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


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

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

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


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

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

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

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

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


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

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

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

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


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

как то так

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

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


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

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

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


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

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

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


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

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

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


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

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

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


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

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

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

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

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

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

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

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

Загрузка...