Страница 1 из 6
включение нагрузки 1 кнопкой без фиксации, на МК
Добавлено: Ср апр 08, 2020 10:00:13
sergo80zxc
приветствую, не работает код в протеусе, может я что то сделал не так?
Код: Выделить всё
// ---------- Проверка разряда на наличие логической единицы (установки) с if------------------
//
//
// кнопка на PB0 , а светодиоды на PB1
//
// переключение нагрузки при нажатии кнопки, не проверена в железе,
// в протеусе через раз работает
//
//
//
//
#include <avr/io.h>
#define F_CPU 1200000UL
#include <util/delay.h>
//===================
int main(void)
{
DDRB = 0b00000010; // настраиваем бит в1 на выход, остальные на вход
PORTB = 0b11111101; // подтягиваем резистороми биты которые на вход
int i=0; // объявляем переменную счетчик и обнуляем ее
//===============
while (PINB & (1<<PB0)) // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
// При сбросе его начнет выполняться Код2.
{
}
_delay_ms(1000); // Код1; задержка 10 мс
i++; // Код2; кнопка нажата, добавляем 1 к переменной
//===============
while (PINB & (1<<PB0)) // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
// При сбросе его начнет выполняться Код2.
{
}
_delay_ms(1000); // Код1; задержка 10 мс
i++; // Код2; кнопка нажата, добавляем 1 к переменной
//===============
while (PINB & (1<<PB0)) // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
// При сбросе его начнет выполняться Код2.
{
}
_delay_ms(1000); // Код1; задержка 10 мс
i++; // Код2; кнопка нажата, добавляем 1 к переменной
//===============
if (i==3) //если i =3 ( при траекратном опросе кнопки было обнаружено нажатое состояние)
{
PORTB ^= (1<<PB1); // инвертируем состояние пина PB1
i=0; // сбросим счетчик
}
}
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 11:59:53
ARV
sergo80zxc писал(а):может я что то сделал не так?
всё

Код: Выделить всё
while (PINB & (1<<PB0)) // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
// При сбросе его начнет выполняться Код2.
{
}
код для оператора while, который должен выполняться, должен находиться внутри фигурных скобок.
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 12:01:15
BOB51
DDRB = 0b00000010;
PORTB = 0b11111101;
т.е.
PINB = 0b11111101
Ждем пока истина (true)
while (PINB & (1<<PB0))
НО....
никогда истиной не станет

Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 12:06:18
ARV
BOB51 писал(а):никогда истиной не станет
фигню изволили сморозить

1<<PB0 =
0b00000001кроме того состояние PINx определяется кнопкой или чем-то подобным
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 12:11:53
BOB51
согласен...
Зевнул
Но результат даже при Вашем варианте = FALSE

(см. выше исправленное)
У нас же по условию топикстартера PB1 есть выход в состоянии 0.
А я просмотрел только ситуацию в самом начале текста.

Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 12:20:50
ARV
BOB51 писал(а):Но результат даже при Вашем варианте = FALSE
кiк тiк?!
настроили PB0 в режим входа с подтяжкой. если там кнопка на общий - то при ненажатой кнопке в PB0 будет 1
0b11111101 & 0b00000001 == 0b00000001 - не равно 0, значит, TRUE

Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 13:49:46
NStorm
_delay_ms(1000); // Код1; задержка 10 мс - это не 10 мс, а 1 с )
EDIT: и не код1 это у вас, а уже код, т.к. за скобкой.
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 13:52:11
BOB51
ОЙ, МЛИН!...
"все что не нуль - true"...
А мня чегось заклинило на "все единицы"!...
Довел Вирь подлый...(и "меры противодействия")...

Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 13:58:33
NStorm
Вот как надо примерно:
Код: Выделить всё
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1200000UL
int main(void) {
DDRB = 0b00000010;
PORTB = 0b11111101;
int i = 0;
while (1) { // не забываем делать всё в цикле, иначе прога отработет один раз
while (PINB & (1 << PB0)) {} // ждем бесконечно пока пин в высоком уровне
while (!(PINB & (1 << PB0))) { // пока пин в низком, начинаем считать антидребезг
i++;
delay_ms(1); // ждем 1 мс
if (i > 30) // если насчитали 30 мс,
break; // выходим из цикла антидребезга
}
if (i >= 30) { // если ранее дождались антидребезга в 30 мс,
PORTB ^= (1 << PB1); // то переключаем порт
i = 0; // и сбрасываем счетчик
} else
i = 0; // а если не дожались, всё-равно надо обнулить переменную,
// иначе дребезг рано или поздно переключит нагрузку
}
}
И не забывайте, что в протеусе дребезга не бывает.
Вообще это реализация обычного Т-триггера. Тут и МК не нужен, а примеров реализаций тонна на чем угодно.
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 16:24:28
sergo80zxc
Код: Выделить всё
//
//включение и отключение нагрузки тактовой кнопкой
//
//
#include <avr/io.h>
#define F_CPU 1200000UL
#include <util/delay.h>
int main(void)
{
DDRB = 0b00000010;
PORTB = 0b11111101;
int i = 0;
while (1) // не забываем делать всё в цикле, иначе прога отработет один раз
{
while (PINB & (1 << PB0)) {} // ждем бесконечно пока пин в высоком уровне
while (!(PINB & (1 << PB0))) // пока пин в низком, начинаем считать антидребезг
{
i++;
_delay_ms(10); // ждем 1 мс
if (i > 30) // если насчитали 30 мс,
break; // выходим из цикла антидребезга
}
if (i >= 30) // если ранее дождались антидребезга в 30 мс,
{
PORTB ^= (1 << PB1); // то переключаем порт
i = 0; // и сбрасываем счетчик
}
else
i = 0; // а если не дожались, всё-равно надо обнулить переменную,
// иначе дребезг рано или поздно переключит нагрузку
}
}
код работает в протеусе если вовремя руку от кнопки убирать, если держать ее нажатой, то лед моргает, по ходу надо организовывать отслеживание отпускания кнопки?
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 08, 2020 16:26:13
NStorm
Добавьте после переключения порта и i = 0 код ожидания отпускания кнопки тогда:
while (!(PINB & (1 << PB0)));
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Чт апр 09, 2020 08:23:31
sergo80zxc
Код: Выделить всё
//
//включение и отключение нагрузки тактовой кнопкой
//
//
#include <avr/io.h>
#define F_CPU 1200000UL
#include <util/delay.h>
int main(void)
{
DDRB = 0b00000010;
PORTB = 0b11111101;
int i = 0;
while (1) // не забываем делать всё в цикле, иначе прога отработет один раз
{
// ----------
while (PINB & (1 << PB0)) {} // ------Ожидание сброса бита с while. ждем бесконечно пока пин в высоком уровне
// Код1 будет выполняться пока 0-й разряд регистра PINВ установлен. При сбросе его начнет выполняться Код2.
// Код1 пустой цикл, Код2 в данном случае переход к следующему оператору
while (!(PINB & (1 << PB0))) // ------Ожидание установки бита с while. пока пин в низком, начинаем считать антидребезг
{ //
i++;
_delay_ms(1); // ждем 1 мс
if (i > 30) // если насчитали 30 мс,
break; // выходим из цикла антидребезга
}
if (i >= 30) // если ранее дождались антидребезга в 30 мс,
{
i = 0; // сбрасываем счетчик
while (!(PINB & (1 << PB0))); // и ждем когда кнопку отпустят крутясь в пустом цикле
{
}
PORTB ^= (1 << PB1); // дождались отпускания кнопки и переключаем порт
}
// ---------- // иначе дребезг рано или поздно переключит нагрузку
}
}
заработало) спасибо
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Чт апр 09, 2020 08:56:23
NStorm
Незначительный нюанс - скобки { } после while ... ; лишние.
Либо while (!(PINB & (1 << PB0)));, либо while (!(PINB & (1 << PB0))) { }.
Это в общем-то одно и тоже в данном случае, но в других случаях сами себя запутаете.
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Чт апр 09, 2020 09:05:23
OKF
)) Либо while (!(PINB & 1<<0));
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Чт апр 09, 2020 09:14:19
NStorm
OKF, плохой пример использовать магические числа.
А вообще есть специальные макросы loop_until_bit_is_set(PINB, PB0);
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Чт апр 09, 2020 09:16:00
sergo80zxc
да, спасибо, исправил, пытаюсь освоить си) говорят намного проще, чем ассемблер, по мне так в ассемблере все гораздо проще и читабельнее, какие куда что в какие регистры все видно, все последовательно) . а ассемблере джампы и ркалы позволяют совершать переходы или вызывать функции, а в си как? если надо перепрыгнуть в другой участок?(без гото) или повторяющийся код вставить?(без библиотек)
Код: Выделить всё
//
//включение и отключение нагрузки тактовой кнопкой
//
//
#include <avr/io.h>
#define F_CPU 1200000UL
#include <util/delay.h>
int main(void)
{
DDRB = 0b00000010;
PORTB = 0b11111101;
int i = 0;
while (1) // не забываем делать всё в цикле, иначе прога отработет один раз
{
// ----------
while (PINB & (1 << PB0)) {} // ------Ожидание сброса бита с while. ждем бесконечно пока пин в высоком уровне
// Код1 будет выполняться пока 0-й разряд регистра PINВ установлен. При сбросе его начнет выполняться Код2.
// Код1 пустой цикл, Код2 в данном случае переход к следующему оператору
while (!(PINB & (1 << PB0))) // ------Ожидание установки бита с while. пока пин в низком, начинаем считать антидребезг
{ //
i++;
_delay_ms(1); // ждем 1 мс
if (i > 30) // если насчитали 30 мс,
break; // выходим из цикла антидребезга
}
if (i >= 30) // если ранее дождались антидребезга в 30 мс,
{
i = 0; // сбрасываем счетчик
while (!(PINB & (1 << PB0))) // и ждем когда кнопку отпустят крутясь в пустом цикле
{
}
PORTB ^= (1 << PB1); // дождались отпускания кнопки и переключаем порт
}
// ---------- // иначе дребезг рано или поздно переключит нагрузку
}
}
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Чт апр 09, 2020 09:48:28
OKF
[uquote="NStorm",url="/forum/viewtopic.php?p=3823829#p3823829"]OKF, плохой пример использовать магические числа.
А вообще есть специальные макросы loop_until_bit_is_set(PINB, PB0);[/uquote]
Да, но PB0 ничем не лучше.) Тогда уж нужно было обозвать логичным именем.
Макросы libc иногда более долгочитаемы, как этом например.) И для таких простых вещей лишние.
Добавлено after 2 minutes 48 seconds:
Тогда уж лучше свои: while (!pin(KEY));
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Чт апр 09, 2020 10:11:17
NStorm
[uquote="sergo80zxc",url="/forum/viewtopic.php?p=3823831#p3823831"]да, спасибо, исправил, пытаюсь освоить си) говорят намного проще, чем ассемблер, по мне так в ассемблере все гораздо проще и читабельнее, какие куда что в какие регистры все видно, все последовательно) . а ассемблере джампы и ркалы позволяют совершать переходы или вызывать функции, а в си как? если надо перепрыгнуть в другой участок?(без гото) или повторяющийся код вставить?(без библиотек)[/uquote]
Функции и циклы. В общем-то это у вас и так используется уже. Вызов _delay_ms(1); и есть вызов функции, которая встроена в библиотеку AVR просто. Можете свою функцию написать и вызывать её.
Циклы - у вас while (...) используется. Он зацикливает действия внутри { } пока выполняется условие в ( ).
Код: Выделить всё
while (!(PINB & (1 << PB0))) // ------Ожидание установки бита с while. пока пин в низком, начинаем считать антидребезг
{ //
i++;
_delay_ms(1); // ждем 1 мс
if (i > 30) // если насчитали 30 мс,
break; // выходим из цикла антидребезга
}
Соб-но участок внутри { } повторяется пока соблюдается условие (!(PINB & (1 << PB0))), т.е. на пине низкий уровень. Или же пока i не станет больше 30, тогда оператор break прерывает цикл.
Почитайте про циклы на C - for, do, while. Вот, например:
https://prog-cpp.ru/c-cycles/PS: Несмотря на то, что в C тоже есть goto - использовать его в большинстве случаев моветон. Почти ни в одной готовой программе вы его не найдете. Написать всегда можно без него, а реально он почти никогда не нужен.
Добавлено after 5 minutes 31 second:Да, но PB0 ничем не лучше.) Тогда уж нужно было обозвать логичным именем.
В данном случае понятно дело мало значимо. Просто дурную привычку так можно привить и потом я вижу тут кучу кода, когда народ во регистры периферии пишет HEX-магию, вместо читаемых сдвигов с макросами.
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Вт апр 14, 2020 21:13:09
sergo80zxc
попробовал на таймере это же сделать, что то не полуучается, не работает код, вроде все логично, товарищи пушистые есть мысли?
Код: Выделить всё
/*
*
* АТИНИ13
*пример настройки прерывания по таймеру Т0
*
*
*
*грамотно организована программа мигания светодиода на прерывании, не расходует основные ресурсы МК в
*
*
*
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1200000UL
int main(void)
{
DDRB = 0b11111110; // бит РВ0 конфигурируем как вход
PORTB = 0b00000001; // входы подтянем
TIMSK0 = 0b00000010; //бит РВ1(TOIE0) устанавливаем в 1, разрешения прерывания по переполнению таймера /счетчика Т0
TCCR0A = 0b00000000; //биты РВ0(WGM00) и РВ1(WGM01) сбрасываем в 0, настройка режима Normal
TCCR0B = 0b00000011; //настраиваем предделитель на 64 (биты CS02=0,CS01=1,CS00=1) , бит В3(WGM02) сбрасываем в 0,настройка режима Normal
GTCCR = 0b00000001; //бит РВ0(PSR10) устанавливаем в 1, Сброс предделителя TO (сбрасываем пред. в конце настроек)
sei(); //Разрешить прерывания
while(1)
{
//Основной цикл программы, он пуст, так как вся работа в прерывании
}
}
//----------
ISR(TIM0_OVF_vect) //обработчик прерывания по таймеру Т0
{
volatile int i = 0; // объявляем переменную счетчик и обнуляем ее
volatile int k = 0; // объявляем переменную счетчик и обнуляем ее
if (PINB & (1<<PB0)) // Если нулевой разряд порта D установлен, то выполняется (Код1). В противном случае, выполняется (Код2).
{
k++; // (Код1) пин PB0 установлен(кнопка не нажата) прибавим 1 к переменной счетчику
}
else
{
i++; // (Код2) пин PB0 сброшен(кнопка нажата) прибавим 1 к переменной счетчику
}
//----------
if (i>=3 ) // если счетчик больше или равен 3 то, кнопка нажата была при всех опросах,
{
if (k>=3 )
{
PORTB ^= (1<<PB1); // инвертируем состояние пина PB1
i = 0; //
k = 0; //
}
}
}
Re: включение нагрузки 1 кнопкой без фиксаци
Добавлено: Ср апр 15, 2020 04:04:23
OKF
[uquote="NStorm",url="/forum/viewtopic.php?p=3823858#p3823858"]В данном случае понятно дело мало значимо. Просто дурную привычку так можно привить и потом я вижу тут кучу кода, когда народ во регистры периферии пишет HEX-магию, вместо читаемых сдвигов с макросами.[/uquote]
Да, согласен. Я даже стараюсь на машине при манёвре ВСЕГДА включать поворот. Пусть даже рядом никого нет, ну или я заезжаю там во двор. Вроде бы ерунда, но рефлексы должны присутствовать.)))