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

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 4
Зарегистрирован: Вт ноя 05, 2019 13:20:20

Сообщение Евгений07 »

Здравствуйте, помогите пожалуйста разобраться с задержкой, пишу прогу для тини13, у меня две кнопки пин3 и пин4 и один выход порт 0. Нужно при нажатом пин3 горит светодиод на порту0 а при отпускании гаснет, следующий алгоритм при нажатом пине3 нажимаем пин4 и светодиод на порту 0 через 20сек должен погаснуть, использовал функцию иф и вайл задержку ставил в вайл но она работает ка при нажатии и при отпускании пин4 а надо только при нажатии,
Реклама
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Хорошо, делайте. Мы не против.
Вопрос-то в чем? https://www.opennet.ru/docs/RUS/smart_question/
Реклама
Родился
Сообщения: 4
Зарегистрирован: Вт ноя 05, 2019 13:20:20

Сообщение Евгений07 »

[uquote="NStorm",url="/forum/viewtopic.php?p=3731184#p3731184"]Хорошо, делайте. Мы не против.
Вопрос-то в чем? https://www.opennet.ru/docs/RUS/smart_question/[/uquote]
как поставить задержку выключения светодиода на порте 0 при нажатой кнопке пин4 а при отпускании он должен снова сразу включиться т,к, пин 3 кнопка нажата постоянно а она отвечает за порт 0 (нажата то =лог-1 если нет то лог-0), сам не могу осилить уже пять дней мучаюсь, я файл атмел студио прикрепил!

Добавлено after 5 minutes 5 seconds:
https://drive.google.com/drive/folders/ ... sp=sharing Вот мой исходник.
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

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

PS: Файл atsln никому не нужен, там нет "исходника".
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 4
Зарегистрирован: Вт ноя 05, 2019 13:20:20

Сообщение Евгений07 »

Одни умники смотрю собрались, а помочь некому!
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

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

Добавлено after 5 minutes 50 seconds:
хотя, если честно, ответ NStormа мне понравился... :)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15592
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Ни схемы ни прожки...
:sleep:
Адуринья что-ли?
8)
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Евгений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; }


      };

 }
Родился
Сообщения: 4
Зарегистрирован: Вт ноя 05, 2019 13:20:20

Сообщение Евгений07 »

<# 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
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Сообщение dr.doc »

как поставить задержку выключения светодиода на порте 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--; // или тупо ждем в цикле положенное время
}
}
код не отлаживал, писал прямо тут, поэтому за мелкие баги прошу прощения
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

У меня такая проблема. Я хочу на тиньке 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:
т. е сейчас так: я нажимаю на кнопку - начинается миганием светодиода, нажимаю другой раз и третий и тд мигание продолжается.
Должно быть: нажал - светодиод вспыхнул, нажал еще раз - погас.

Сейчас задержка которая для устранения дребезга фактически является причиной мигания светодиода.
Непонятненько.
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Не надо магических цифр. Особенно писать в биты регистра, которые помечены как 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: Чисто для этого тинька не нужна, это обычный триггер.
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

Да, все работает как часы. Спасибо. Теперь есть хороший пример.
Полдня провозился. Может и еще бы неделю.
NStorm писал(а):Особенно писать в биты регистра, которые помечены как read-only
а что вы здесь имели ввиду. Биты pb6 и pb7, которым ног не досталось?
NStorm писал(а):Не надо сравнивать с 1 результат AND (&). 1<<PB1 равно 2, а никак не 1
здесь тоже не понял, если честно
NStorm писал(а):Но это изначально убогий код был.
это Вы про использование прерываений намекаете?
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

[uquote="olegue",url="/forum/viewtopic.php?p=3734954#p3734954"]а что вы здесь имели ввиду. Биты pb6 и pb7, которым ног не досталось?[/uquote]
Вроде того. Только таких бит нет. В ДШ загляните, там написано что их просто нет, они RESERVED и только для чтения. Проблема была не в этом, но в целом подобного надо избегать. Где-нибудь, в другом месте, на другом МК это можно вызвать проблему.

[uquote="olegue",url="/forum/viewtopic.php?p=3734954#p3734954"]
NStorm писал(а):Не надо сравнивать с 1 результат AND (&). 1<<PB1 равно 2, а никак не 1
здесь тоже не понял, если честно[/uquote]
((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.
Надеюсь понятно, такие вещи тыщу раз уже описаны везде.

[uquote="olegue",url="/forum/viewtopic.php?p=3734954#p3734954"]это Вы про использование прерываений намекаете?[/uquote]
Нет, в данном случае они не обязательны (разве что если нет желания экономить энергию и переводить МК в сон), см. выше.

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мс
  }
}
Только в реално железе скорее всего не помешают еще и внешние подтяжки посильнее, чем в аврке.
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

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мс
}
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

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.
Друг Кота
Аватара пользователя
Сообщения: 3087
Зарегистрирован: Пт мар 09, 2007 15:01:52
Откуда: Биробиджан

Сообщение radteh »

olegue, если не секрет, ты пишешь эту программу для того что-бы разобраться с МК или для практической задачи? Если второе, то тебе для включения\выключения достаточно взять к561тм2 или её аналог и с минимум обвеса добиться результата. Для мигания просто добавить генератор на к561ла7 например.
А если хочешь разобраться с МК, то предусмотри или в коде или аппаратное подавление дребезга от кнопки.
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

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);
};
Друг Кота
Аватара пользователя
Сообщения: 15592
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Ежли охота Си освоить - то тинька 13я не самое лучшее из имеющегося.
Другое дело - на чистом ассемблере в АВР студии 4.19 - там и симулятор работает
и места будет в достатке, и понятнее на уровне "железа".
8)
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

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

примерно так...
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Ответить

Вернуться в «AVR»