Перейти к содержанию

Отладка ATTiny13A


Рекомендуемые сообщения

Всем доброго дня.

Пишется программа для ATTiny13A. Есть проблема при отладке в AVR Studio 7 и симуляции в Proteus 8.9.

В в AVR Studio 7:

1) после команды

"ADMUX |= 0b01100010;"

отладчик показывает, что ADMUX == 0b01100000, пришлось после добавить

"ADMUX |= (1 << 1);"

почему не с первого раза?

2) команда

"ADCSRA |= 0b01000000;"

не стартует АЦП, при замене на

"ADCSRA |= 0b11000000;" или "ADCSRA |= (1 << ADSC);"

тоже самое.

Что я делаю не так?

3) Функцию задержки пришлось закомментировать, иначе наглухо виснет при входе в неё.

Можно ли как-то иначе решить такую проблему?

В Proteus 8.9:

После нажатия кнопки на выходе снимается 2,5 В - это вообще как? При переключении нагрузки это происходит на обоих выходах, чего по программе быть никак не должно...

02.jpg.d7da26a6a391f19225d7c345c810e283.jpg

Код программы:

#define F_CPU 9600000UL

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

#define D1_ON() PORTB |= (0x01 << PB1)			// Direction 1
#define D1_OFF() PORTB &= ~(0x01 << PB1)		//

#define D2_ON() PORTB |= (0x01 << PB2)			// Direction 2
#define D2_OFF() PORTB &= ~(0x01 << PB2)		//

int max_current=5000;							// max current (mA)
int action_delay=3000;							// max time for openning/closing (ms)

void delay200(void)								// delay function
{
	_delay_ms(200);								// delay of checking (ms)
	ADCSRA |= 0b01000000;						//ADSC=1;                   // start conversion
	ADCSRA |= (1 << ADSC);
	while ((0b00010000 & ADCSRA) == 0)			//(ADIF==0)					// check for end of conversion
	{
	}
	ADCSRA |= 0b00010000;						//ADIF=1;				    // reset flag of end of conversion
}

void action(void)								// waiting for ending of action
{
	int i;
	for (i = 0; ((ADCH*1000) < max_current) & (i < action_delay); i += 200)	// check for actual current and time
	{
		delay200();
	}
}

int main(void)
{
	DDRB=0b00000001;
	ADMUX |= 0b01100010;						// bit5 = "left adjusting"
	ADMUX |= (1 << 1); 
	ADCSRA=0b10000011;							// bit6 = "start"  (ADSC)   bit0..2 = "divider"
	while (1)
	{
		while ((0x01 & PINB) == 0x00)			// check for a positive input signal
		{
		}
		_delay_ms(300);							// signal length (ms)
		if ((0x01 & PINB) == 0x01)				// check for a true input signal
		{
			D1_ON();							//PINB.1=1;                    // start opening
			delay200();
			if ((ADCH*1000) < max_current)		// check for direction
			{
				action();						// continue opening
				D1_OFF();						//PINB.1=0;					   // end opening
			}
			else
			{
				D1_OFF();						//PINB.1=0;                   // end opening
				D2_ON();						//PINB.2=1;                   // start closing
				action();						// continue closing
				D2_OFF();						//PINB.2=0;                   // end closing
			}
			while ((0x01 & PINB) == 0x01)		// check for a negative input signal
			{
			}
			_delay_ms(300);						// signal length (ms)
			while ((0x01 & PINB) == 0x01)		// check for a true input signal
			{
			}
		}
	}
}

 

Изменено пользователем Jalui
опечатка
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

20 часов назад, aitras сказал:

Почему вход для кнопки не вход, а выход? И D1, D2 наверное должны быть выходами?

DDRB |= (1 << PB1) | (1 << PB2);

Рукалицо... Спасибо :)

20 часов назад, aitras сказал:

И почему бы не задействовать прерывание по окончании преобразования АЦП?

Потому что не умеем)
Просто смотреть флаг ADIF такое себе?


И чисто в справочных целях, если не затруднит. Не нашлось путного.
Правильно ли я чищу ADIF просто записывая в него единицу? Даташит говорит "Alternatively, ADIF is cleared by writing a logical one to the flag" при программном отслеживании этого флага... То есть это нормально, что он выставился единицей при завершении конвертации и я в него пишу единицу же?

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

1 час назад, Jalui сказал:

Правильно ли я чищу ADIF просто записывая в него единицу?

Да, правильно. Рассматривайте это как подачу сигнала на вход сброса.

Я не раздаю удочки. Я продаю рыбу.

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

9 hours ago, Jalui said:

Потому что не умеем)

Надо разрешить прерывание от АЦП

ADCSRA |= (1 << ADIE);

Запустить преобразование установкой бита ADSC и описать обработчик прерывания где-нибудь перед main:

volatile unsigned int data;

ISR(ADC_vect)
{
	data = ADC;
	// do something
}

И да, нужно не забыть перед бесконечным циклом глобально разрешить прерывания макросом sei();

С уважением, Михаил, EEP Lab

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

Не стоит браться за прерывания, если не умеете пока.

Смотреть ADIF - так себе идея, поскольку его надо чистить вручную. Куда логичнее и удобнее следить за ADSC - он сам падает после завершения одиночного преобразования.

Избавьтесь от вот этого всего 0b00011100 - используйте именованные константы. Например, запуск АЦП делается так: ADCSRA |= _BV(ADSC); - просто и понятно. Если смущает _BV(), то пишите (1<<ADSC) - это то же самое будет. Ожидание завершения преобразования делается так: while(ADCSRA & _BV(ADSC));

Каждому пину уже назначено имя, например, PB0 - это номер бита в порту B микроконтроллера, используйте не вот это 0b00000001, а PB0 или PB1 вместе с макросом _BV(), как показано выше.

Думаю, после этого "рефакторинга" вы или увидите, где ошиблись, или ошибки просто пропадут сами по себе, поскольку в общем код производит впечатление логичного - значит, где-то в битовой константе битик ошибочно не на том месте поставили. Замените число на буквы - и битик станет на свое место сам, ошибки пропадут.

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

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

@aitras попробую пока более простое для понимания, но вашу информацию забрал в заметки, спасибо!)

@солар спасибо!)

 

21.05.2020 в 08:59, ARV сказал:

логичнее и удобнее следить за ADSC

И то верно)

 

21.05.2020 в 08:59, ARV сказал:

Каждому пину уже назначено имя, например, PB0 - это номер бита в порту B микроконтроллера

Похоже, что компилятор не в курсе, кто такие PB0...PB4 (например, "PB2 = Unknown identifier"). Библиотеки <avr/io.h> недостаточно или что не так?

Виснет при попытке входа в "while (1)" же.

 

И чисто в справочных целях:

MUX1 пишется только в таком порядке:

ADMUX |= (1 << REFS0) | (1 << ADLAR) | (1 << MUX1);
ADMUX |= (1 << MUX1);

Если в коде:

ADMUX |= (1 << REFS0) | (1 << ADLAR);
ADMUX |= (1 << MUX1);

то MUX1 == 0. Это нормально?

 

Актуальный код:

#define F_CPU 9600000UL

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

#define D1_ON() PORTB |= (1 << PB1)							// Direction 1
#define D1_OFF() PORTB &= ~(1 << PB1)						//

#define D2_ON() PORTB |= (1 << PB2)							// Direction 2
#define D2_OFF() PORTB &= ~(1 << PB2)						//

int max_current=5000;										// max current (mA)
int action_delay=3000;										// max time for openning/closing (ms)


void delay200(void)											// delay function
{
	_delay_ms(200);											// delay of checking (ms)
	ADCSRA |= (1 << ADSC);									// start conversion
	while (ADCSRA & (1 << ADSC));							// check for end of conversion
}

void action(void)											// waiting for ending of action
{
	int i;
	for (i = 0; ((ADCH*1000) < max_current) & (i < action_delay); i += 200)	// check for actual current and time
	{
		delay200();
	}
}

int main(void)
{
	DDRB |= (1 << PB1) | (1 << PB2);				
	ADMUX |= (1 << REFS0) | (1 << ADLAR) | (1 << MUX1);		// Internal Voltage Reference, Left Adjust, Selected Channel is PB4
	ADMUX |= (1 << MUX1);
	ADCSRA |= (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);	// ADC Enabled, Division Factor is 8									
	while (1)
	{
		while ((1 & PB0) == 0);								// check for a positive input signal
		_delay_ms(300);										// signal length (ms)
		if ((1 & PB0) == 1)									// check for a true input signal
		{
			D1_ON();										// start opening
			delay200();
			if ((ADCH*1000) < max_current)					// check for direction
			{
				action();									// continue opening
				D1_OFF();									// end opening
			}
			else
			{
				D1_OFF();									// end opening
				D2_ON();									// start closing
				action();									// continue closing
				D2_OFF();									// end closing
			}
			while ((1 & PB0) == 1);							// check for a negative input signal
			_delay_ms(300);									// delay before new signal (ms)
		}
	}
}

 

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

13 минут назад, Jalui сказал:

Библиотеки <avr/io.h> недостаточно или что не так?

Похоже, что что-то не так. Вы уверены, что проект именно для attiny13 создан? 

13 минут назад, Jalui сказал:

Это нормально?

Не нормально. Всегда делал одной командой запись в ADMUX без всяких |= и никогда проблем не было.

DDRB = (1 << PB1) | (1 << PB2);				
ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX1);
ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);

 

А вот это что такое у вас:

if ((1 & PB0) == 1)

Вот что вы ожидаете этим добиться? проверить, будет ли 1 равно 1?

Но ранее у вас вдруг 

while ((1 & PB0) == 0);

Здесь вы надеетесь, что 1 станет почему-то равно 0?!

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

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

22.05.2020 в 16:27, ARV сказал:

Вы уверены, что проект именно для attiny13 создан?

Создал новый проект - предлагает включить только <avr/io.h>

Даже пробовал включить руками <avr/iotn13a.h>  - ошибки.

22.05.2020 в 16:27, ARV сказал:

Всегда делал одной командой запись в ADMUX без всяких |= и никогда проблем не было

Сделал по примеру - без изменений. :(
Похоже надо менять среду разработки... Никакой логики.
 

22.05.2020 в 16:27, ARV сказал:

if ((1 & PB0) == 1)

Вот что вы ожидаете этим добиться? проверить, будет ли 1 равно 1?

Я так понимаю:

если на PB0 приходит 5 вольт, то для контроллера это 1.

Если это так, то результатом "(1 & PB0)" будет "1" - мы это проверяем оператором сравнения же.

Или это не так работает?

22.05.2020 в 16:27, ARV сказал:

while ((1 & PB0) == 0);

Здесь вы надеетесь, что 1 станет почему-то равно 0?!

Исходя из вышенаписанного, тут наоборот: пока на входе 0 В - простаиваем.

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

3 часа назад, Jalui сказал:

Похоже надо менять среду разработки...

Точно. Если вместо музыки вы слышите ерунду, то надо менять консерваторию :)

Вам надо изучать язык Си, а не среду разработки менять.

3 часа назад, Jalui сказал:

Или это не так работает?

См. выше - почитайте учебник Си... PB0 это всего лишь "синоним" числа 1. То есть запись

if ((1 & PB0) == 1)

и запись

if ((1 & 1) == 1)

абсолютно идентичны. В итоге это все иденично такой записи

if(1)

То есть всегда истинное условие. Ну и далее while аналогично... всегда ложное.

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

Вкратце, не в порядке выполнения:

  •  вернулся к записям типа
(PINB & 0b00000001) == 0
  •  исправил переполнение переменной по типу (логика проверки условия АЦП);
  •  установил непортативный Proteus (это оказалось важно);
  •  код скомпилировал прямо в Proteus с подключением WinAVR.

Заработало.

Интереса ради создал новый проект в Atmel Studio и он выдал ошибку

recipe for target 'main.o' failed

Да ну его :)

Всем спасибо!

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

5 минут назад, Jalui сказал:
  • вернулся к записям типа

(PINB & 0b00000001) == 0

Ну и зря. Запись (PINB & _BV(PB0)) намного информативнее. Ну или так (PINB & (1<<PB0))

А вообще в WinAVR (и, разумеется, avr-gcc вообще) есть удобные стандартные макросы проверки битов bit_is_set и bit_is_clear, которыми могу порекомендовать пользоваться, если у вас проблемы с битовыми операциями. Эквивалент процитированной строчки будет тогда таким: bit_is_set(PINB, PB0)

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

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

  Разрешено использовать не более 75 эмодзи.

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • Начнем с того, что это НЕ предУСИЛИТЕЛЬ, а тупо повторитель, да еще и с регулировкой уровня выходного сигнала. Скорее всего, данная схема предназначалась для наушников.  А закончим тем, что в изображении схемы дебильная ошибка во входных цепях. Если сделаете точно так, как на схеме, то предвижу вопль: "Спаял, а не работает!"
    • Припой не ложится потому-что флюс (хотя бы канифоль) нужен... 
    • По версии 5 действительно есть ощущение что не хватает мощи, хотя громко музыку в квартире я не слушаю, всегда остаётся запас. Трансформаторы у меня 16,8В 3А 2 шт. Конденсаторы 4 шт по 10000 (по факту около 8500) мкФ. Этого недостаточно?  После праздников попробую подобрать колонки на 4ом, доложу о впечатлениях. Может быть поменяю БП. Хотя вчера вечером послушал Pink Floyd на виниле и басы были.  По версии 6 ток покоя около 100мА. Радиаторы около 800 см2 на канал. На выходе "сладкая парочка".  С ОРА134 ток покоя и температура стабильна, с КР574УД1 температура и ток покоя скакали. Осциллограф не подключал, но наверное это возбуд. После праздников посмотрю. Заказал ещё LM318N. Дальше буду слушать версию 6 на даче с Sony SS-2030, у них на мой взгляд середина хорошая. 
    • Опять же, "с батареей" а не только ионистором. Сталкивался с S7-200 в ремонте. Там тоже есть ионистор и нет батареи. Слета программы за пол года лежания не замечено, но ионистор не замерял..
    • Фото предоставленное вами выше говорит, что вы не понимаете того факта что энергию вашей "приблуды" потребляет не только микроконтроллер но и некоторые другие элементы на платке.
    • Существует и третий вариант - и карта, и батарейка, и ионистор.  Объясняется очень просто: батарейка на одной плате, а SRAM с рабочей программы на другой, на ней и стоит ионистор. Ионистор нужен в ремонтных целях - чтобы при разборе ПЛК не обнулилась память SRAM.  Попутно решается задача замены батарейки - не нужно это делать при включенном питании ПЛК. Гарантируется хранение в несколько часов, что для ремонта обычно достаточно. На практике же встретился станок, который везли по ж\д с вконец конченной батарейкой, и тем не менее рабочая программа в SRAM осталась жива. 
    • Логично предположить, что с таймером все в порядке. А вот согнал DONE стоит проверить, возможно где то в программе он ломается при работе с датчиком.
×
×
  • Создать...