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

Отладка 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-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 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 пользователей онлайн

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

    • У меня больше всего вопросов вызвала необычная схема обеспечения отрицательного питания. Автор этой обстоятельной заметки пишет: For this supply to work correctly, the transformer must have a secondary voltage of at least 18V RMS.  Почему? Что будет не так с отрицательным питанием, если напряжение на трансформаторе будет меньше 18В?   https://tinyurl.com/23mlwxtt - я в простейшей эмуляции ставлю 12В пикового напряжения для трансформатора и на стабилитроне все как положено: -5.6В.
    • Согласен, очень криво объяснил. Это работа трёх вольтовой линии, просто на диод шотки сдвоенный, на один анод приходит сигнал напрямую с трансформатора, а на второй через дроссель. Вольт/деление 5 вольт в клетке, тайминг по моему 10 МС. Третья фотография это сигнал на катодах уровень земли ровно по центру экрана. Но все линии по итогу в порядке 3.3 в, 5, в, 12 в и -12 в. Нагрузить все линии не могу сразу ,так как тут же выгорают транзисторы (имеется нагрузка 250 ватт по 10 ампер на каждую линию за исключением-12в), поэтому нагружаю 3.3 вольтовую линию на 10 ампер,  подключаю переменный резистор 50 ватт на 15 ом на 5 вольтовую линию и постепенно довожу до той той картины с перекосом (это гдето  50 ватт общее). По поводу микросхемы, вверху имеется скрин где между импульсами проскакивает мини импульс, если так можно сказать, он проскакивает и на одной  и на второй ноге (7,8). Микросхема не tl 494, а lw4933/abx942.1/c9421646. Далее они приходят на базы транзисторов 945g  коллекторы этих транзисторов соединены с  выводами трансформатора. Просто схема типовая, легче мне кажется просто привести фото самого блока, для тех кто разбирается будет гораздо информативне.  Диод шотки по 12 вольтовой линии был подгоревший, заменил на донора. Приводить скрины не буду что бы не захламлять тему. В итоге, пока все так же, при достижении определенной нагрузки суммарно где-то 50 ватт, появляется этот "выброс и перекос". По этому имеются мысли на два варианта, это микросхема , этот мини импульс между периодами, на низкой нагрузке особо не влияет, но при достижении определенной приводит с самовозбуждению входной цепи и непроизвольному открытию транзистора нижнего плеча. Либо дело в "горячей части", плавающий дефект в обвязке силовых ключей.  Спасибо за ответ.
    • @Gomerchik а вы контролировали как меняется уровень сигнала на А1 ардуины?
    • Спасибо за совет. Автором данного проекта я не являюсь, мне нужно было воссоздать уличный датчик для метеостанции взамен пропавшего(( Из разного найденного в интернете этот проект работает с моей станцией Орегон (спасибо автору). В понедельник попробую последовать Вашему совету. Но все равно куча непоняток  как блин это работает)) Если дело в неправильной отправки команды, то как на это влияет подключение датчика температуры? Если совсем не подключать таймер, то передача идет один раз (как и прописано в программе), станция принимает и отображает, но минут через сколько-то естественно станция уже ни чего не показывает, но с таймером питание полностью не пропадает с ардуинки, но передача сигнала каким-то образом работает по таймеру.  В моем понимании данная команда подается один раз потому, что таймер должен отключать питание МК после передачи сигнала и каждые 43 сек снова подавать питание (так того требует станция).  Ардуино передает показания температуры отключается полностью и 43 секунды мк не работает.  Сейчас у меня питание пока сделано на подпитке от солнечной батареи, но пару пасмурных дней и аккумулятор съедается до отключения(
    • thickman Так и сделаю. Вытащу из бу БП.  Буду знать, как отличить. Благодарю. Заменил транзисторы на IRFB20N50K. Картина стала, совсем другой.  Похоже трудность не в драйвере, на момент подвозбуда, переходные процессы, в нем, завершены. Увеличил затворные резисторы до 50ом, стало немного лучше.  Не понятно, почему верхний ключ греется несколько сильнее. Возможно, стоит посмотреть ток в коллекторе.  Снабберные емкости временно удалил, изменений не произошло.  Замена ТГР на другой, на кольце MSTN-16A-TH, так же, результата не принесла.   irfb20n50k.pdf
    • А что нить из ассортимента активных щупов производства СССР..))
×
×
  • Создать...