• Объявления

    • 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_    574

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

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

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

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

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

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


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

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

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


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

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

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


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

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

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

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


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

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

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

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


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

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

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


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

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

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

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

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


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

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

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

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


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

как то так

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

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


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

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

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


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

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

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


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

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

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


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

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

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


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

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

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

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

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

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

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

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

Загрузка...

  • Сообщения

    • 1. Насчет LAT - не знаю, т.к. при таком коде на экран заданная заранее строчка выдается, а вот содержимое переменной - нет. 2. Это как-то влияет на работу МК? Я могу это игнорировать? Если нет, то как устранить?
    • Ну в общем то попробовал показать физические замеры, так как акустических проводов пока нет, сравню межблочники и так имеем генератор прямоугольных импульсов выходное сопротивление 600ом как у моего цапа,  подключено по очереди два кабеля, длина кабелей одинаковая 1метр, один сигнал записан в память что бы сравнивать было удобно, смотрим переходную характеристику ,угадайте какой из кабелей звучит лучше.
    •   Дальше то что ? @Николай Горячев -у  нужно расположение элементов схемы с их обозначениями. Что бы помогающим было проще, руководствуясь схемными обозначениями контуров,  давать советы. Каким местом тут ваши претензии к скану (это не я рисовал) .       
    • Может немного не в тему или кому пригодится. Нужно было регулировать давление в автомобильном, поршневом компрессоре Хундай в пределах 0,1-1 атм. Мошность моторчика около 120-150вт. По паспорту пусковой ток около 15-16а, рабочая мах  до 10а. Собрал проверенную  схему, Частота около 430гц. Моторчик не свистит и не гудит, но сильно греется защитный диод и немного ключ. Поставил сдвоенный диод с БП ПК (по-моему 25а), греется. Собрал новую плату с другой мс 555, не помогло. Пробовал менять частоту емкостью и сопротивлением, не помогло. Ток не мерил,  но слышно, моторчик работает необычно....с натугой. Думал, внутри шланг перегнут.  Разобрал компрессор, а он сухой и горячий. Смазки нет обсалютно (новый!) !!! все трется в сухую!!! Брызнул во все труще-пихующие части ВДшкой, звук моторчика стал мягче и тише ,  диод перестал греться! Моторчик регулируется от 5 до 50%, как и задумано по настройкам. Полностью разобрал компрессор, промыл в бензе и смазал все трущиеся узлы ШРУСом. Полет нормальный! Ох уж эти китайцы...смазки пожалели... ЗЫ Проверьте смазку в своих 12в автокомпрессорах.  
    • Я не понимаю твоей проблемы. Тебе нужно три этапа пройти: 1. Берём шунт на нужный ток. В простом случае - резисторы по 0.1-0.2Ом 2Вт, в ещё более простом - кусок нихрома или манганина нужной длины под нужный ток(что бы не раскалялась и не отпаивалась). Подобрать по сопротивлению нужно. (для этого нужно знать, какой ток какому напряжению соответствует, а там по закону Ома считать) 2. Устанавливаем ток 1-10 ампер. (любой источник с амперметром и нагрузкой) 3. Подстраиваем амперметр. (крутим резистор тока) Подстроечники полюбому нужно крутить, имея заведомо точный прибор для измерения напряжения\тока. Так как они обычно плюс-минус километр показывают, или вообще не настроены. Или настроив на 10 вольт, на 20 вольт и на 5 вольт будет погрешность, а на 10В точно показывать.
    • На коллекторе 316 какое напряжение? Звоните его на обрыв.
    • @LA5 А какие там токи рабочие через R8 ?   МОСФЕТ, как бы в линейном режиме, в классе "А" находится. И  эмиттерный повторитель,.. он же самый широкополосный.   Заодно, а нужна ли вольтодобавка? Прикрутил к выходу корректора идеальный повторитель вместо паралельника. Поскольку идеальный повторитель не вносит искажений, то на нагрузке останется что-то от корректора при бутстрипе и без: С бутстрипом покрасивше выглядит.