Обсуждаем контроллеры компании Atmel.
Ответить

Программирование ATtiny13

Вт ноя 05, 2019 16:42:54

Здравствуйте, помогите пожалуйста разобраться с задержкой, пишу прогу для тини13, у меня две кнопки пин3 и пин4 и один выход порт 0. Нужно при нажатом пин3 горит светодиод на порту0 а при отпускании гаснет, следующий алгоритм при нажатом пине3 нажимаем пин4 и светодиод на порту 0 через 20сек должен погаснуть, использовал функцию иф и вайл задержку ставил в вайл но она работает ка при нажатии и при отпускании пин4 а надо только при нажатии,

Re: Программирование ATtiny13

Вт ноя 05, 2019 17:41:43

Хорошо, делайте. Мы не против.
Вопрос-то в чем? https://www.opennet.ru/docs/RUS/smart_question/

Re: Программирование ATtiny13

Вт ноя 05, 2019 20:01:03

Хорошо, делайте. Мы не против.
Вопрос-то в чем? https://www.opennet.ru/docs/RUS/smart_question/

как поставить задержку выключения светодиода на порте 0 при нажатой кнопке пин4 а при отпускании он должен снова сразу включиться т,к, пин 3 кнопка нажата постоянно а она отвечает за порт 0 (нажата то =лог-1 если нет то лог-0), сам не могу осилить уже пять дней мучаюсь, я файл атмел студио прикрепил!

Добавлено after 5 minutes 5 seconds:
https://drive.google.com/drive/folders/ ... sp=sharing Вот мой исходник.

Re: Программирование ATtiny13

Вт ноя 05, 2019 21:44:47

Такое впечатление, что цифры 07 в нике - год рождения.

PS: Файл atsln никому не нужен, там нет "исходника".

Re: Программирование ATtiny13

Ср ноя 06, 2019 11:11:41

Одни умники смотрю собрались, а помочь некому!

Re: Программирование ATtiny13

Ср ноя 06, 2019 11:21:47

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

Добавлено after 5 minutes 50 seconds:
хотя, если честно, ответ NStormа мне понравился... :)

Re: Программирование ATtiny13

Ср ноя 06, 2019 11:58:55

Ни схемы ни прожки...
:sleep:
Адуринья что-ли?
8)

Re: Программирование ATtiny13

Ср ноя 06, 2019 16:14:09

Евгений07 писал(а):я файл атмел студио прикрепил!
Спойлер
Код:
#include <avr/io.h>
#include <util/delay.h>

#define Bit(bit)  (1<<(bit))

#define ClearBit(reg, bit)       reg &= (~(1<<(bit)))
#define SetBit(reg, bit)          reg |= (1<<(bit))   
#define BitIsClear(reg, bit)    ((reg & (1<<(bit))) == 0)


#define PAUZA 200   // 200 * 100ms =20 000ms

int main()
 {
static uint8_t a;
    
   SetBit(DDRB, DDB0) ;   ClearBit(PORTB, PB0);
   
   ClearBit(DDRB ,DDB4); ClearBit(DDRB, DDB3);  SetBit(PORTB, PB4); SetBit(PORTB, PB3);
   
   

   while (1) {

      if (BitIsClear(PINB,PINB3)) {
      
      if ( a== PAUZA )  { ClearBit(PORTB, PB0);
      } else  { SetBit(PORTB, PB0); }
         
            if (BitIsClear(PINB,PINB4)) {
               if( ++a > PAUZA) { a=PAUZA; }
               _delay_ms (100); 
            } else { a = 0; }
         
      } else { ClearBit(PORTB, PB0); a = 0; }


      };

 }

Re: Программирование ATtiny13

Ср ноя 06, 2019 20:07:53

<# define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>


int main(void)
{

DDRB |= (1<<0);
PORTB &= ~ (1<<0);
DDRB &= ~((1<<3) | (1<<4));
PORTB &= ~ ((1<<3) | (1<<4));

while (1)
{
if (PINB & (1<<3))
{
PORTB |= (1<<0);
}
else
{
PORTB &= ~ (1<<0);
}

while (PINB & (1<<4))
{
PORTB &= ~ (1<<0);
_delay_ms(2000);
}




}



}>

Добавлено after 6 minutes 11 seconds:
Вы меня извините, но я только начал во всем этом разбираться и как тут правильно просить о помощи еще не знаю!
По этому коду пин 4 гасит сразу порт 0 а при отпускании пина 4 через 2 сек зажигает а надо наоборот!

Добавлено after 1 minute 16 seconds:
Пин 4 нажимаю только тогда когда зажат пин3

Re: Программирование ATtiny13

Ср ноя 06, 2019 20:52:25

как поставить задержку выключения светодиода на порте 0 при нажатой кнопке пин4 а при отпускании он должен снова сразу включиться т,к, пин 3 кнопка нажата постоянно а она отвечает за порт


Спойлерif(!((PORTB & (1<<PB3)) && (PORTB & (1<<PB4)))) // проверка на нажатие двух кнопок
{
unsigned int count = 1000; // us delay - количество микросекунд задержки
while(count)
{
delay_us(1);
if(1<<PB4) // как только отпущена - включим светодиод
{
PORTB |=(1<<PB0);
count=1; // и установим счетчик для выхода из задержки
}
count--; // или тупо ждем в цикле положенное время
}
}

код не отлаживал, писал прямо тут, поэтому за мелкие баги прошу прощения

Re: Программирование ATtiny13

Пн ноя 11, 2019 19:52:17

У меня такая проблема. Я хочу на тиньке 13 (сабж) сделать небольшую программулю, наподобии той что хотел ТС, но даже проще.

Я взял готовую прогу с Атмеги 8 с этого сайта https://radioparty.ru/programming/avr/c/225-lesson2

Т.е нажимаю на кнопку, загорается диод, нажимаю еще раз - диод гаснет. Все.

С зажиганеим диодом я разобрался. А вот с кнопками нет.

Я взял ПРОТЕУС 8.5 и загрузил туда этого код для Атмеги8 что бы проверить его, а затем переложить на Тиньку13
Код:
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRD = 0x00; // Порт D вход
PORTD = 0xFF; // Подключаем подтягивающие резисторы
DDRB = 0xFF; // Порт B выход
PORTB = 0x00; // Лог. 0 на выходе
while(1)
{
while ((PIND&(1 << PD0)) == 1){} // Ждем пока на выводе PDO лог. 1
_delay_ms(200); // Задержка 200мс
if ((PINB&(1 << PB0)) == 0) // Если на выводе PB0 лог. 0
{
PORTB |= (1 << PB0); // Лог. 1 на выводе PB0
}
else
{
PORTB &= ~(1 << PB0); // Лог. 0 на выводе PB0
}
while ((PIND&(1 << PD0)) == 0){} // Ждем пока на выводе PDO лог. 0
_delay_ms(200); // Задержка 200мс
}
}


Добавлено after 25 minutes 26 seconds:
Я начал перекладывать код на Тинку, с сохранением логики
Самое главное это отличие в портах

это код из Атмега 8
DDRD = 0x00; // Порт D вход
PORTD = 0xFF; // Подключаем подтягивающие резисторы
DDRB = 0xFF; // Порт B выход
PORTB = 0x00; // Лог. 0 на выходе

У меня на тиньке столько портов нету поэтому все приходится делать на порте PORTB
к PB0 я подключу светодиод через резистор 220 ом и сделаю этот порт выходом
к PB1 я подключу кнопку сразу на массу и сделаю этот порт входом

DDRB = 0x00000001 (последний бит установил в единицу - это будет выход, т.е на PB0 будет светодиод)
PORTB= 0x11111110 (по аналогии с атмегой PB1=1 (подключен подтягивающий резистор), а PB0 - установлен логический 0 на входе)


Теперь там где ((PIND&(1 << PD0)) == 1) меняю на PINB и PB1

те. вот так
Код:
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
//DDRD = 0x00; // Порт D вход
//PORTD = 0xFF; // Подключаем подтягивающие резисторы
//DDRB = 0xFF; // Порт B выход
//PORTB = 0x00; // Лог. 0 на выходе

DDRB = 0x00000001;  //(последний бит установил в единицу - это будет выход, т.е на PB0 будет светодиод)
PORTB= 0x11111110; //(по аналогии с атмегой PB1=1 (подключен подтягивающий резистор), а PB0 - установлен логический 0 на входе)

while(1)
{
while ((PINB&(1 << PB1)) == 1){} // Ждем пока на выводе PDO лог. 1
_delay_ms(200); // Задержка 200мс
if ((PINB&(1 << PB0)) == 0) // Если на выводе PB0 лог. 0
{
PORTB |= (1 << PB0); // Лог. 1 на выводе PB0
}
else
{
PORTB &= ~(1 << PB0); // Лог. 0 на выводе PB0
}
while ((PINB&(1 << PB1)) == 0){} // Ждем пока на выводе PDO лог. 0
_delay_ms(200); // Задержка 200мс
}
}



Ошибки компилятор не дает, но именно на цикле while не сработки. Цикл while (ожидание нажатие) просто пролетает до следующий строки

Что у меня тут не так?

Добавлено after 23 minutes 52 seconds:
т. е сейчас так: я нажимаю на кнопку - начинается миганием светодиода, нажимаю другой раз и третий и тд мигание продолжается.
Должно быть: нажал - светодиод вспыхнул, нажал еще раз - погас.

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

Re: Программирование ATtiny13

Пн ноя 11, 2019 20:00:16

Не надо магических цифр. Особенно писать в биты регистра, которые помечены как read-only. Не надо сравнивать с 1 результат AND (&). 1<<PB1 равно 2, а никак не 1. А в исходном работало, потому что там были PD0/PB0, которые = 1. Но это изначально убогий код был.
Код:
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
//DDRD = 0x00; // Порт D вход
//PORTD = 0xFF; // Подключаем подтягивающие резисторы
//DDRB = 0xFF; // Порт B выход
//PORTB = 0x00; // Лог. 0 на выходе

DDRB = (1 << PB0);  //(последний бит установил в единицу - это будет выход, т.е на PB0 будет светодиод)
PORTB= (1 << PB1); //(по аналогии с атмегой PB1=1 (подключен подтягивающий резистор), а PB0 - установлен логический 0 на входе)

while(1)
{
while ((PINB&(1 << PB1))); // Ждем пока на выводе PDO лог. 1
_delay_ms(200); // Задержка 200мс
if ((PINB&(1 << PB0)) == 0) // Если на выводе PB0 лог. 0
{
PORTB |= (1 << PB0); // Лог. 1 на выводе PB0
}
else
{
PORTB &= ~(1 << PB0); // Лог. 0 на выводе PB0
}
while (!(PINB&(1 << PB1))); // Ждем пока на выводе PDO лог. 0
_delay_ms(200); // Задержка 200мс
}
}

PS: Чисто для этого тинька не нужна, это обычный триггер.

Re: Программирование ATtiny13

Пн ноя 11, 2019 20:18:49

Да, все работает как часы. Спасибо. Теперь есть хороший пример.
Полдня провозился. Может и еще бы неделю.

NStorm писал(а):Особенно писать в биты регистра, которые помечены как read-only

а что вы здесь имели ввиду. Биты pb6 и pb7, которым ног не досталось?

NStorm писал(а):Не надо сравнивать с 1 результат AND (&). 1<<PB1 равно 2, а никак не 1


здесь тоже не понял, если честно

NStorm писал(а):Но это изначально убогий код был.

это Вы про использование прерываений намекаете?

Re: Программирование ATtiny13

Пн ноя 11, 2019 20:53:09

а что вы здесь имели ввиду. Биты pb6 и pb7, которым ног не досталось?

Вроде того. Только таких бит нет. В ДШ загляните, там написано что их просто нет, они RESERVED и только для чтения. Проблема была не в этом, но в целом подобного надо избегать. Где-нибудь, в другом месте, на другом МК это можно вызвать проблему.

NStorm писал(а):Не надо сравнивать с 1 результат AND (&). 1<<PB1 равно 2, а никак не 1

здесь тоже не понял, если честно

((PIND&(1 << PD0)) == 1) - конструкция плохая. Нельзя так писать. Потому что в случае с
((PIND&(1 << PD1)) == 1) - она уже никогда не будет равна 1. Она будет равна 0 или 2. Поэтому нет смысла сравнивать с цифрой. Просто if/while ([!](PIND&(1 << PD0))) - если 0, оно и так НЕТ, если отличное от нуля, оно ДА.
На пальцах - 1 << PD1 = 0b00000010, это понятно? Потому что PD1 = 1, но сдвинув 1 на 1 позицию влево получаем 2. Операция лог. И (&) с PIND в данном случае ну никак не может дать нам 1. Если на PD1 высокий уровень, в PIND будет 0bxxxxxx1x, где x - любое значение. В этом случае PIND & (1 << PD1) будет равен тому же 0b00000010 = 2.
Надеюсь понятно, такие вещи тыщу раз уже описаны везде.

это Вы про использование прерываений намекаете?

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

EDIT: Ну и плюс вместо всего этого:
Код:
if ((PINB&(1 << PB0)) == 0) // Если на выводе PB0 лог. 0
{
PORTB |= (1 << PB0); // Лог. 1 на выводе PB0
}
else
{
PORTB &= ~(1 << PB0); // Лог. 0 на выводе PB0
}

Пишется просто
PORTB ^= (1 << PB0);

Ну и форматировании я молчу )

Добавлено after 9 minutes 53 seconds:
В итоге хотя бы так должен выглядеть этот код:
Код:
#include <avr/io.h>
#include <util/delay.h>

int main(void) {
  DDRB = (1 << PB0); //(последний бит установил в единицу - это будет выход, т.е на PB0 будет светодиод)
  PORTB = (1 << PB1); //(по аналогии с атмегой PB1=1 (подключен подтягивающий резистор), а PB0 - установлен логический 0 на входе)

  while (1) {
    while ((PINB & (1 << PB1))); // Ждем пока на выводе PB1 лог. 1
    _delay_ms(200); // Задержка 200мс
    PORTB ^= (1 << PB0);
    while (!(PINB & (1 << PB1))); // Ждем пока на выводе PB1 лог. 0
    _delay_ms(200); // Задержка 200мс
  }
}

Только в реално железе скорее всего не помешают еще и внешние подтяжки посильнее, чем в аврке.

Re: Программирование ATtiny13

Пн ноя 11, 2019 22:35:39

NStorm писал(а):Пишется просто
PORTB ^= (1 << PB0);


ну это вообще хит.

Добавлено after 36 seconds:
Не сегодня думаю хватит открытий.

Добавлено after 1 minute 31 second:
Счас думаю, как включить мигание и выключить мигание. Только дайте мне сначала самому подумать.

Добавлено after 1 hour 29 minutes 40 seconds:
Максимум что удалось придумать это включение мигания, Выключение не получается. Не знаю как из цикла мигания выйти

захожу в цикл мигания

while (1){
PORTB ^= (1 << PB0);
_delay_ms(200);
}

Код:
while(1)
{
while ((PINB&(1 << PB1))){} // Ждем пока на выводе PDO лог. 1 (Жднем нажатия)
_delay_ms(200); // Задержка 200мс

while (1){
     PORTB ^= (1 << PB0);
   _delay_ms(200);
}

while ((PINB&(1 << PB1)))   {}
_delay_ms(200); // Задержка 200мс
}

Re: Программирование ATtiny13

Пн ноя 11, 2019 22:43:57

olegue, варианты на выбор для размышления:
1. Прерывание на кнопку для "выхода из цикла". Она как раз на INT0 висит.
2. Таймер вместо delay.
3. Проверка кнопки в цикле мигания, выход по нажатию. Чтобы снизить время реакции, можно ждать "шагами":
Код:
while (1){
  uint8_t i = 0, btn_flag = 0;
  PORTB ^= (1 << PB0);
  while (i <= 10) {
    i++;
    _delay_ms(20);
    if (!((PINB & (1 << PB1)))) {
      btn_flag = 1;
      PORTB &= ~(1 << PB0);
      break;
    }
  }
  if (btn_flag) break;
}

Не супер точно 200 мс будет, потому что на i++ и if будут такты расходоваться, но думаю не принципиально в данном случае. Если принципиально, то это вар. 1 и 2.

Re: Программирование ATtiny13

Вт ноя 12, 2019 02:44:50

olegue, если не секрет, ты пишешь эту программу для того что-бы разобраться с МК или для практической задачи? Если второе, то тебе для включения\выключения достаточно взять к561тм2 или её аналог и с минимум обвеса добиться результата. Для мигания просто добавить генератор на к561ла7 например.
А если хочешь разобраться с МК, то предусмотри или в коде или аппаратное подавление дребезга от кнопки.

Re: Программирование ATtiny13

Вт ноя 12, 2019 08:58:24

radteh писал(а):если не секрет, ты пишешь эту программу для того что-бы разобраться с МК или для практической задачи?


какие уж тут секреты. Хочу разобраться с МК. И если дело пойдет, но наверняка гдето в далеке может замаячить что-то практическое.
Но, вот на данном уровне мигания диодов говорить об этом сильно преждевременно.
Пару дней вожусь, вижу,ч то элементарные, казалось бы задачи уже вызывают затруднения
Допустим, что бы просто зажечь диоды, тут с помощью интернета, кое как получилсь
А с кнопкой вообще беда. Тут еще и дребез нужно учитывать


с помощью NStorm продвинулся может на месяц вперед.
Вот пример, казалось бы, на мой розум, должно все работать как надо

Вот код, в нем я жду нажатия кнопки.
Код:
while ((PINB & (1 << PB1))){};

Кнопка нажата, т.е PB стало 0, я вхожу в следующий цикл, где мигаю диодом, пока не нажму кнопку
Код:
while ((PINB & (1 << PB1))){
PORTB^=(1<<PB0);
_ms_delay(200);
};

После нажатия я должне опять перейти к строке первого цикла ожидания нажатия, но этого не происходит.

Добавлено after 2 minutes 4 seconds:
Код:
while(1)
{
while ((PINB&(1 << PB1))){} // Ждем пока на выводе PDO лог. 1 (Жднем нажатия)
_delay_ms(200); // Задержка 200мс

while ((PINB&(1 << PB1))){  /// Вот в этом цикле, как я полагаю должно быть мигание, которое выключится по нажатию кнопки.

     PORTB ^= (1 << PB0);
   _delay_ms(200);
}

}


вот полный код.

Добавлено after 1 minute 56 seconds:
т.е мигания нет. Происходит просто включения и выключения светодиода.

Добавлено after 11 minutes 43 seconds:
Такое впечатление, что этот цикл не крутиться

Код:
while ((PINB & (1 << PB1))){
PORTB^=(1<<PB0);
_ms_delay(200);
};

Re: Программирование ATtiny13

Вт ноя 12, 2019 09:07:19

Ежли охота Си освоить - то тинька 13я не самое лучшее из имеющегося.
Другое дело - на чистом ассемблере в АВР студии 4.19 - там и симулятор работает
и места будет в достатке, и понятнее на уровне "железа".
8)

Re: Программирование ATtiny13

Вт ноя 12, 2019 09:20:02

а что должно это делать? это генератор случайного состояния?
пока кнопка нажата у тебя по очереди быстро быстро проверяются оба условия, какой из циклов будет исполняться при отпускании кнопки - воля случая...
если хочешь стабильности, между циклами ожидающими отпускания кнопки вставь циклы, ожидающие нажатия...
пока(1){
пока (нажата){};
немного ждем; // антидребезг
пока (отпущена){};
немного ждем;
пока (нажата){};
немного ждем;
пока (отпущена){мигаем;};
гасим светодиод;
немного ждем;
}

примерно так...
Ответить