WinAvr в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Аватара пользователя
Сообщения: 46
Зарегистрирован: Вс ноя 22, 2015 00:52:38
Откуда: Днепропетровск

Сообщение awas5 »

Подскажите мне надо в рабочей прошивка транзитестера поменять цвет фона и шрифта.Где это можно прочитать?
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Здравствуйте! может кто объяснить на примере как применяется макрос ISR_NAKED
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

При входе в прерывание (обычный ISR(.._vect)) сохраняется текущий контекст. Для этого генерируется код в начале прерывания, который текущие регистры сохраняет в стек, и в конце, который возвращает всё назад.

Добавляя ISR_NAKED, можно запретить генерировать этот код. Если прерывание не выполняет ничего критичного (не вычиляет ничего, не меняет регистр статуса), например, дёргает какой-нибудь порт, это сэкономит ресурсы и ускорит вход-выход из прерывания. Если же что-то вычисляется в прерывании, и используются для этого те же регистры, что были использованы в основном потоке, то при выходе из прерывания, может быть порча данных.

Вывод - при использовании ISR_NAKED нужно самому позаботиться о сохранении контекста (или его части) в стек и о вычитывании его назад.
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Вывод - при использовании ISR_NAKED нужно самому позаботиться о сохранении контекста (или его части) в стек и о вычитывании его назад.
Спасибочки, это стало понятно :beer:
Реклама
Эиком - электронные компоненты и радиодетали
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Разобрался.)
Реклама
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

Сообщение НАПАЛМ »

Привет.
Изучаю Си, пересел с ассемблера, до этого на Си не писал.
Программку набросал следующую: имеется таймер, три кнопки управления (PD4 - Stop, PD2 - Select, PD3 - Start), 5 светодиодов индицируют выбранное время 1..5мин, пищалка пищит по окончании.
Студия 4.19 с тулчейном встроенным, контроллер atmega48pa, проект закрепил в архиве.
Компилирую, начинаю отлаживать и вот после входа в бесконечный цикл программа выполняет участок кода по непонятной мне логике, а только потом идет на оператор switch. В регистре PIND сымитировал ненажатые кнопки, но судя по дизассемблеру программа даже не проверяет кнопки, а сразу бежит выполнять один из case.
Подскажите пожалуйста, где косяк, может еще чего заметите, что я неверно сделал.
Спойлер

Код: Выделить всё



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

#define LED_1MIN 1
#define LED_2MIN 2
#define LED_3MIN 3
#define LED_4MIN 4
#define LED_5MIN 5
#define Buzzer 5
#define ButtonStart 3
#define ButtonSelect 2 
#define ButtonStop 4

#define Selection 0
#define Running 1 
#define SoundSignal 2


volatile int TimerTime;
volatile int ICR1_additional_value;
volatile int ProgramStatus;




//Timer1 initializing
void init_timer1 (void)
{
	TIMSK1 = (1<<TOIE1); //Timer1 intrruption allow
	TCCR1A = (0<<WGM11)|(0<<WGM10);
	TCCR1B = (1<<WGM13)|(1<<WGM12);
	//Clear Timer on Compare Match (CTC) mode
	//TOP value - ICR1
}

void stop_timer1 (void)
{	
	TCCR1B = (1<<WGM13)|(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);
	TimerTime = 1;
}

void start_timer1 (void)
{	
	TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10);
	//Precaler 1024
}

void write_status (int TimerTime)
{
	switch (TimerTime)
	{
	case LED_1MIN:
		PORTC = 1<<LED_1MIN;
		break;
	case LED_2MIN:
		PORTC = 1<<LED_2MIN;
		break;
	case LED_3MIN:
		PORTC = 1<<LED_3MIN;
		break;
	case LED_4MIN:
		PORTC = 1<<LED_4MIN;
		break;
	case LED_5MIN:
		PORTC = 1<<LED_5MIN;
		break;
	}
}


void set_timer_top_value (int TimerTime)
{
	switch (TimerTime)
	{
	case LED_1MIN:
		ICR1_additional_value = 8593;
		break;
	case LED_2MIN:
		ICR1_additional_value = 17187;
		break;
	case LED_3MIN:
		ICR1_additional_value = 25781;
		break;
	case LED_4MIN:
		ICR1_additional_value = 34375;
		break;
	case LED_5MIN:
		ICR1_additional_value = 42968;
		break;
	}
}


void Sound_Out (void)
{
	int i;
	for (i = 1000; i > 0; i--)
	{
		PORTD = PORTD^(1<<Buzzer); //inverse bit
		_delay_us (500);
		PORTD = PORTD^(1<<Buzzer);
		_delay_us (500);
	}
}


//Timer/Counter1 Capture Event Handler
ISR (TIMER1_CAPT_vect)
{
	//you can calculate final timer value in this formula:
	//50000*TimerTime + ICR1_additional_value
	if (ICR1 == ICR1_additional_value)
	{
		ProgramStatus = SoundSignal; //it means time is up, and indicate it with sound
	}
	else
	{
		TimerTime--;
		if (TimerTime == 0)
		{
			ICR1 = ICR1_additional_value;
		}
	}

	return;
}



int main(void)
{
	init_timer1();

	TimerTime = 1; //initial timer value is 1 minute

	ProgramStatus = Selection;

	//ports initializing
	//PC5-PC1, PD5 - outputs, PD2 - input
	
	DDRC = 1<<LED_1MIN|1<<LED_2MIN|1<<LED_3MIN|1<<LED_4MIN|1<<LED_5MIN;
	PORTC = 1<<LED_1MIN; //initial timer indicator is 1min

	DDRD = 1<<Buzzer|0<<ButtonSelect|0<<ButtonStart|0<<ButtonStop;
	PORTD = 0<<Buzzer|1<<ButtonSelect|1<<ButtonStart|1<<ButtonStop;

	sei(); //interrupts enable

	//main infinite cycle
	while (1)  
	{
		switch (ProgramStatus)
		{
		case Running:
			//Proccesing Stop Button
			if ((PIND & (1<<ButtonStop)) == 0)
			{
				_delay_ms (50); //for button bounce reduce
				if ((PIND & (1<<ButtonStop)) == 0)
				{
					ProgramStatus = Selection;
					stop_timer1();
				}
				while ((PIND & (1<<ButtonStop)) == 0) //waiting for releasing the button
				{ 
				}
			}
			break;

		case Selection:
			//Proccesing Select Button
			if ((PIND & (1<<ButtonSelect)) == 0)
			{
				_delay_ms (50); //for button bounce reduce
				if ((PIND & (1<<ButtonSelect)) == 0)
				{
					TimerTime++; //change time
					if (TimerTime == 6)
					{	
						TimerTime = 1;
					}
					write_status(TimerTime); //indicate timers value
				}
				while ((PIND & (1<<ButtonSelect)) == 0) //waiting for releasing the button
				{ 
				}
			}

			//Proccesing Start Button
			if ((PIND & (1<<ButtonStart)) == 0)
			{
				_delay_ms (50); //for button bounce reduce
				if ((PIND & (1<<ButtonStart)) == 0)
				{
					ProgramStatus = Running;
					ICR1 = 50000; //default top value
					set_timer_top_value(TimerTime); //additional top value
					start_timer1();
				}
				while ((PIND & (1<<ButtonStart)) == 0) //waiting for releasing the button
				{
				}
			}
			break;

		case SoundSignal:
			//stop timer and give sound signal to user
			stop_timer1();
			ProgramStatus = Selection;
			Sound_Out();	
			break;
		
		default:
			break;

		}		



	}
	return 0;
}







Вложения
Timer v1.0.rar
(18.42 КБ) 483 скачивания
Реклама
Встал на лапы
Сообщения: 134
Зарегистрирован: Вс авг 01, 2010 16:05:25

Сообщение TICLIR »

Добрый вечер, вопрос такой функция переполняет стек

Код: Выделить всё

uint64_t  delit;
uint64_t  delim;
uint64_t  my_sf;

uint64_t any_podeli(uint64_t dalc){

 
 delit=(my_sf*my_sf*395*dalc)/10;

 delim= 1000000000000000000/delit;
 return delim;

}
А формула такая L=1/4*П*П*f*f*c
А словами индуктивность равна 4 пи в квадрате умножить на частоту в квадрате и умножить на емкость в контуре.
Короче протеус пишет что выходим за рамки стека, может есть вариант как то по другому производить вычисления?
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Не вникал, причем здесь стек, но я такие задачи, обычно, решаю примерно так:
Спойлер

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> 
#include <math.h>



volatile uint64_t inductance;

uint64_t lcalc (uint32_t freq, uint32_t capacity)
{
	uint64_t wrk;	// рабочая переменная

	wrk = 2533029591058444286;	// (1e20 / (4 * pi * pi)), посчитано заранее на виндовом калькуляторе
	wrk /= freq;
	wrk /= freq;
	wrk /= capacity;
	return wrk;
}

int main(void)
{
	inductance = lcalc ((uint32_t)24000, (uint32_t)16450);
}
Здесь емкость в пикушках, частота в герцах, а индуктивность получается в десятках наногенри. В принципе, если частота выше 10 Гц, перед делением переменной wrk на емкость ее можно умножить на 10, тогда результат будет в наногенри. Впрочем, при частоте в единицы герц точность не получишь, вернее частоту надо будет представлять не в герцах, а, допустим, в миллигерцах. А так, если там сотни кГц - десятки МГц, можно после каждого деления wrk на частоту умножать ее (wrk) на 1000, в чем получится результат - сообразишь.

Да, Студия 4.19, камушек - ATmega328P, программа в симуляторе Студии работает нормально.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

А если посчитать не в uint64_t, а в float? Да, на 8бит МК лучше избегать использования форматов с плавающей точкой, но это может быть лучше расчётов с такими бешеными коэффициентами.
Контактная информация:
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

WiseLord писал(а):Да, на 8бит МК лучше избегать использования форматов с плавающей точкой, но это может быть лучше расчётов с такими бешеными коэффициентами.
Не-а! Не будет лучше. Да и что там такого бешеного? Посчитал в виндовом калькуляторе 1/(4пи квадрат), там же умножил это дело, не мелочась, на 1е24, скопипастил, компилирую - не лезет! Ладно, начинаю по циферке отбрасывать, 4 отбросил - влезло. Дальше оно только делится, так, что переполнений точно не будет. То есть, конечно, надо было подсчитать и сразу написать 1е20, но я поленился.

Да и потом, преобразовать такое число для вывода - не фиг делать, прикинул, в каких единицах нужен результат, поделил на 10 в соответствующей степени и переводи целое число, хоть библиотечной программой, хоть по-простому, дели последовательно на 10 и собирай остатки. А плавучку переводить? Это же какую-то библиотеку цеплять надо, а она толстая...
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

afz писал(а):Не-а! Не будет лучше.
лучше будет с точки зрения простоты понимания выполняемых действий. для любых инженерных расчетов практически достаточно точности 3 знаков после запятой, поэтому емкость 100 мкФ записывать в с точностью до единиц пикофарад попросту глупо.
плавучка добавить пару килобайт для AVR семейства mega, еще пару килобайт добавит stdio с поддержкой плавучки, в итоге даже в 8-ю мегу все это вместится очень просто, и останется место еще много для чего...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Встал на лапы
Сообщения: 134
Зарегистрирован: Вс авг 01, 2010 16:05:25

Сообщение TICLIR »

[uquote="afz",url="/forum/viewtopic.php?p=3436992#p3436992"]Не вникал, причем здесь стек, но я такие задачи, обычно, решаю[/uquote]

Спасибо за способ. С таким решением кода занимает на 4% в ATmega16, не знаю но Протэус всё равно пишет
PC=0x2FFC. [AVR MEMORY] Writing to memory location 0x04DC outside of memory size 0x0460.
А в реальном такого не замечал, т.е. в протеусе контроллер сбрасывается , а в реальности нет
Поставщик валерьянки для Кота
Сообщения: 2194
Зарегистрирован: Вс ноя 15, 2009 23:13:59
Откуда: Харьков

Сообщение watchmaker »

PC=0x2FFC. [AVR MEMORY] Writing to memory location 0x04DC outside of memory size 0x0460.
Это уже не флэш-памяти не хватает, а оперативной.
Иногда мой питомец уходит в такую спячку, что разбудить его можно только щелчком по первой ноге...
Контактная информация:
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Похоже, Протеус колбасит слегка. У меня Студия отчиталась, что оперативка (.data + .bss + .noinit) 280 байт, стек в самой глубине вызовов не превышает 100 байт и все прекрасно работает. Естественно, никаких выходов адресов за область ОЗУ не наблюдается.

Кстати, поражен оптимизаторскими способностями GCC. Заглянул в дизасм программы в том виде, как я ее опубликовал - о ужас! Никаких вычислений нет! Там же вызов с аргументами в виде констант, так компилятор вычислил все заранее и все действие в программе свелось к передаче результата этих вычислений в переменную industance (она же volatile). Пришлось править main(), а именно - модифицировать вызовы lcalc().
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Насчёт оптимизации - это верно.

Вот интереса ради можно, например, посмотреть, как gcc оптимизирует целочисленное деление числа (допустим, 8-битного) на 10. Часто бывает нужно при разборе числа на сотни-десятки-единицы для вывода на индикатор.

ЕМНИП, в дизассемблере это будет выглядеть как умножение на 205 (два такта) и сдвиг старшего байта результата вправо на 3.
Контактная информация:
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

ARV писал(а):поэтому емкость 100 мкФ записывать в с точностью до единиц пикофарад попросту глупо.
Так с ёмкостью 100 мкФ колебательных контуров и не бывает. Максимум 1-2 мкФ, и то, это при измерении больших индуктивностей (десятки Гн). А обычная для радиолюбителей практика - ёмкость в контуре - десятки-сотни-тысячи пикушек, редко когда десятки тысяч.

А еще вопрос, какие есть в наличии точные конденсаторы. У меня, например, лежат насколько конденсаторов КПГ - 4226 пФ, 9490 пФ,7530 пФ, все 0.5%, 16450 пФ 1%. До недавнего времени, когда у меня возникала необходимость измерить индуктивность, я клепал на "сопливчике" генератор с одной их этих емкостей, измерял частоту частотомером Ч1-33 и вычислял программой на Бейсике (на писюке) индуктивность. А тут вот наш коллега решил сгородить такое на МК - по всей видимости у него там генератор с эталонной емкостью и измеряемой индуктивностью, частотомер и программа расчета, которую он и отлаживает.
ARV писал(а):лучше будет с точки зрения простоты понимания выполняемых действий.
Не вижу разницы. Действия одни и те же, а что единицы измерения несколько странные, ну и что?

К тому же у меня острое недоверие к плавучке с 24-битной мантиссой. У нас в Политехе на ВЦ в свое время была ЭВМ Минск-32. Наш политеховский НИС (научно-исследовательский сектор) наклепал на Фортране несколько сотен разных задач, считали вентиляцию шахт, водопроводные и тепловые сети, еще кучу разного. Потом мы получили ЕС 1022, а Минск-32 начали готовить к списанию. Стали переносить задачи. Ладно, там Фортран-4, и тут Фортран-4, перекачали, подправили разночтения (их было очень мало), пускаем - изба фигвам! Многие задачи начали банально врать. Ряды расходятся или сходятся не туда, накопление ошибок и т.д. В конце концов разобрались: у М-32 мантисса 28 разрядов, у ЕС-ок 24. Поставили DOUBLE PRECISION вместо REAL, и все заработало!
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Друг Кота
Сообщения: 7722
Зарегистрирован: Вс июл 24, 2011 11:38:09

Сообщение 74LS00 »

Может кто знает как добавить STK500 в Makefile чтоб шить из Programmers Notepad [WinAVR].
Вижу что народ пытается с ним активно бороться и удаляет везде, а вот мне наоборот надо и его нет
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Цель в Makefile для avrdude добавить.

Что-то вроде:

Код: Выделить всё

MCU      = atmega328p

AVRDUDE = avrdude
AD_MCU  = -p $(MCU)
AD_PROG = -c stk500v2
AD_PORT = -P <порт>

AD_CMD  = $(AD_MCU) $(AD_PROG) $(AD_PORT)

flash:
	$(AVRDUDE) $(AD_CMD) -U flash:w:<прошивка>.hex:i
Шить через вызов "make flash". Ну и, естественно, порт и путь к прошивке должны быть верными.
Контактная информация:
Друг Кота
Сообщения: 7722
Зарегистрирован: Вс июл 24, 2011 11:38:09

Сообщение 74LS00 »

Куда деть последнюю строку, матюкает сильно.
Исходник от тестера типо такой https://github.com/svn2github/transisto ... u/Makefile
Для прошивки там только Tool-Program .
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

А зачем что-то куда-то девать? Там в finish.mk уже есть готовая цель program для прошивки avrdude, просто ею воспользуйтесь
Контактная информация:
Ответить

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