• Объявления

    • admin

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

      На форуме разыгрывается спектроанализатор Arinst SSA-TG LC (цена 18500 руб). Просьба всем перейти по ссылке ниже и принять участие!
Alex

Подключение Кнопок К Микроконтроллерам

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

Как уловить нажатие кнопки на Attiny13A ? Кнопка одним концом подключена к 5, другим к PB4. Но нажатие не фиксируется. Как зафиксировать подачу сигнала на PB4 ?

	DDRB = 0b01111;
	PORTB = 0b10000;

while (1)
	{
		
		if ((PINB & ( 1 << 4 )) == 1){ // пробовал PINB4 == 1
			
			PORTB = 0b1001;
			_delay_ms(500);
			
			PORTB = 0b1010;
			_delay_ms(500);

			PORTB = 0b1100;
			_delay_ms(500);

			// order ended...
			
			_delay_ms(1000);
			
		}
		else {
			
			PORTB = 0b0000;
			
		}

 

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


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

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

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

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

5 это наверное +5в? А порт резистором  1-10к подтянут к земле? Иначе будет ВСЕГДА считываться 1 или мусор

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


Ссылка на сообщение
Поделиться на других сайтах
On 6/16/2017 at 7:23 AM, KomSoft said:

5 это наверное +5в? А порт резистором  1-10к подтянут к земле? Иначе будет ВСЕГДА считываться 1 или мусор

да, это 5V.

Резистор >6 kOm подтянут к земле. При подаче питания диодики мигают, а по кнопке нет.

Spoiler

#define F_CPU 1200000UL

#include <avr/io.h>
#include <util/delay.h>


void DoubleLedOrder(){
	
	PORTB = 0b001;
	_delay_ms(500);
	
	PORTB = 0b010;
	_delay_ms(500);

	PORTB = 0b100;
	_delay_ms(500);
	
	PORTB = 0b010;
	_delay_ms(500);
	
	PORTB = 0b001;
	_delay_ms(500);
	
	PORTB = 0b000;
	
}

int main(void)
{
	
	DDRB = 0b01111;
	PORTB = 0b10000;

	
	_delay_ms(1000);
	
	DoubleLedOrder(); // test
	
	while (1)
	{
		
		if ((PINB & ( 1 << 4 )) == 1){
			
			DoubleLedOrder();
			
		}
		
	}
	
	return 0;
	
}

 

 

0b332368ee584b2db62c1deb502d1068.png

Условие срабатывает при == 0, то есть всегда мигает, а при нажатие нет. Но а как логическую 1 получить ?

 

Изменено пользователем Евгений Надточий

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


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

if (PINB4 == 1)

27 минут назад, Евгений Надточий сказал:

Условие не срабатывает

а и не должно срабатывать, потому что PINB4 может быть только = 4. А единице  - никогда.

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

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


Ссылка на сообщение
Поделиться на других сайтах
Just now, Yurkin2015 said:

PINB4 может быть только или =0 или =16. А единице  - никогда.

(PINB & ( 1 << 4 )) == 1

это условие тоже не работет

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


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

Я поправил свой пост. Видимо константа PINB4 всегда = 4.

Типа, надо проверять неравенство нулю:

if(PINB & ( 1 << PINB4 ) !=  0)

Изменено пользователем Yurkin2015
  • Одобряю 1

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


Ссылка на сообщение
Поделиться на других сайтах
8 minutes ago, Yurkin2015 said:

if(PINB & ( 1 << PINB4 ) !=  0)

Спасибо, работает.

А условие == 1 представляет из себя конкретное значение напряжения / тока ?

Изменено пользователем Евгений Надточий

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


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

Вероятно, надо было сравнивать с 0b10000, а не с 1.

Так как выражение PINB & ( 1 << 4 ) при нажатой кнопке даст как раз число 0b10000, а просто 1 это 0b00001.

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


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    274
4 минуты назад, Евгений Надточий сказал:

А условие == 1 представляет из себя конкретное значение напряжения ?

1 - это просто число. Сравнение двух чисел. Когда кнопка не нажата, что PINB = 00000000 в двоичном виде. Когда кнопка нажата, что PINB = 00010000, отличие в четвёртом бите. Поэтому операция

PINB & ( 1 << 4 )

проверяет только четвёртый бит, остальные биты игнорирует.

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


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

Не знаю был такой вариант или нет , но напишу его. Пример очень простой и эффективный в принципе:

Скрытый текст
Цитата

while(1)

{

if(KEY1==0 && flg&0x01)

{

// Что то делаем

flg&=~0x01; // сбросили флаг

}

if(KEY1)flg|=0x01; 

delay_(50);

}

С телефона плохо пример писать .. но думаю понятно.

 

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


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

может запишем поровнее?

Quote

while(1)

{

if(!KEY10 && flg) flg = !flg; // сбросили флаг

if(KEY1) flg = 1; 

delay_(50);

}

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

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


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

подобное решение может красиво работать только в случае использования ОС. Там логика работы позволяет (и даже рекомендует) использовать задержки. Правда не все так просто, но в целом именно так.

вот пример опроса группы кнопок с использованием ОС. Каждая может работать независимо от остальных или вместе с ними, одновременно или раздельно. В общем как угодно и все будет корректно

typedef struct
{
	GPIO_PinState New_state;
	GPIO_PinState Old_state;	
} Button_state;

typedef struct
{
	uint8_t event; // событие кнопки (кнопка нажата)
	Key_status ctrl; // контроль кнопки (запрет/разрешение считывания состояния)
} _key;

typedef struct
{
	_key Up;
	_key Down;
} Keyboard_state;

Keyboard_state Keyboard; // глобальное обьявление структуры клавиатуры

/* Start_Keyboard_Task function */
void Start_Keyboard_Task(void const * argument)
{
	
  // init Keyboard
  Button_state Up_key;
  Button_state Down_key;
	
	Keyboard.Down.event = 0;
	Keyboard.Up.event =0;
	
	Keyboard.Down.ctrl = kbENABLE;
	Keyboard.Up.ctrl =kbENABLE;
  
  const uint8_t Debounce_time = 10;
  
  // start key scan
  for(;;)
  {
			
		Up_key.New_state = HAL_GPIO_ReadPin(RSRV_1_GPIO_Port, RSRV_1_Pin);
		Down_key.New_state = HAL_GPIO_ReadPin(RSRV_2_GPIO_Port, RSRV_2_Pin);
		
		if (Up_key.New_state != Up_key.Old_state && Keyboard.Up.ctrl)
		{
			if (Up_key.New_state == GPIO_PIN_RESET) Keyboard.Up.event = 1;
			osDelay(Debounce_time);
			Up_key.Old_state = Up_key.New_state;
		}
		if (Down_key.New_state != Down_key.Old_state && Keyboard.Down.ctrl)
		{
			if (Down_key.New_state == GPIO_PIN_RESET) Keyboard.Down.event = 1;
			osDelay(Debounce_time);
			Down_key.Old_state = Down_key.New_state;
		}
	}
}

для краткости я оставил только пару кнопок, но их можно делать сколько угодно, добавляя поле в структуру и накопипастив блоков if. Да в лоб, зато предельно понятно.

чисто пример и можно переписать посимпатичнее

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

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


Ссылка на сообщение
Поделиться на других сайтах
artos5    285
4 часа назад, mail_robot сказал:

может запишем поровнее?

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

Если программа критична к времени (если нужно обслуживать динамическую индикацию в основном цикле) , то можно сделать так:

Скрытый текст

while(1)

{

if((++tmr>DELAY) && !KEY10 && flg) flg = !flg; // сбросили флаг

if(KEY1) flg = 1; 

}

PS: с телефона по ровнее не получается :) а пк лень включать :)

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


Ссылка на сообщение
Поделиться на других сайтах
Alex    513
8 часов назад, mail_robot сказал:

вот пример опроса группы кнопок с использованием ОС. Каждая может работать независимо от остальных или вместе с ними, одновременно или раздельно. В общем как угодно и все будет корректно

Можно немного сократить цикл задачи :
 

  for(;;)
  {
		Up_key.Old_state = Up_key.New_state;
		Down_key.Old_state = Down_key.New_state;
    
		osDelay(Debounce_time);
    
		Up_key.New_state = HAL_GPIO_ReadPin(RSRV_1_GPIO_Port, RSRV_1_Pin);
		Down_key.New_state = HAL_GPIO_ReadPin(RSRV_2_GPIO_Port, RSRV_2_Pin);
		
		if (Up_key.New_state != Up_key.Old_state && Keyboard.Up.ctrl)
		{
			Keyboard.Up.event = 1;
		}
		if (Down_key.New_state != Down_key.Old_state && Keyboard.Down.ctrl)
		{
			Keyboard.Down.event = 1;
		}
	}

 

  • Одобряю 1

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


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

неа, не пойдет. Новое состояние должно запоминаться только для сработавшей кнопки, а не для всех подряд. Поэтому задержка именно внутри иф-а

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


Ссылка на сообщение
Поделиться на других сайтах
Alex    513
1 минуту назад, mail_robot сказал:

Новое состояние должно запоминаться только для сработавшей кнопки

А оно так и будет. Если состояние кнопки не изменится, оно и не запомнится. Точнее останется прежней.

Всё пойдёт... Попробуйте, и всё заработает :)

  • Одобряю 1

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


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

еще раз внимательно пробежался. Ну в принципе да, так тоже будет работать. Немножко экономии получится по коду

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

Ось вообще классная штука в плане администрирования ресурсов и диспетчеризации процессов. И по моему совсем не тормозит, а гдето даже экономит ресурсы проца

Изменено пользователем mail_robot
  • Одобряю 1

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


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

Я тоже такой способ опроса кнопок применяю, практически один в один.
И, также, без ОСи уже "жить" не могу :D

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


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

Я на PIC-ах специализируюсь. Для "мелких" (16, 18) - OSA. Под PIC32 - FreeRtos.

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


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

я чисто из спортивного интереса. Но в целом удивлен, что люди даже на довольно слабых камнях осью не брезгуют уже. Я так то с пиками уже завязал и скорее всего навсегда. Смысла нет ни по деньгам ни по ресурсам ни по гибкости применения. STM за 3 копейки убивает эту нишу под корень. А так мне пики нравились больше авров. Какие то они более душевные чтоли. Последний камень F886-ой зашил. До сих пор лежит еще штук 80 тел разных из той жизни (16, 18). 

Остался ICD3 и кит второй. Кит жалко, а вот ICD-шку думаю куда деть

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

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


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

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас