Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей...

 
Опции темы
Непрочитано 20.03.2010, 00:55  
kison
Почётный гражданин KAZUS.RU
 
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Сообщение от neiver Посмотреть сообщение
Никто никого не инлайнит.
Сообщение №10 прочтите - https://kazus.ru/forums/showpost.php...9&postcount=10 И то что Вы отцитировали и то что в ответ написали. Изначально речь шла о оптимизации на уровне исходника. Я static в объектник добавить уже не могу.
Вообще вопрос линковки отдельный. Там уже никакой оптимизации не будет, только можно неиспользуемое выкинуть. GCC линкер умеет выкидывать только секциями целиком.
Реклама:
kison вне форума  
Непрочитано 20.03.2010, 00:59  
neiver
Временная регистрация
 
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
neiver на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Сообщение от kison Посмотреть сообщение
Там, где Вы ищете PINF - регистр зарезервирован для будущего использования.
Частный случай.
Читайте следующие посты. Там будет другой подход. Этот подход я привел как пример подхода к вопросу в лоб, и сам его забраковал, по причине неэффективности работы с такими пинами как глобальными переменными. Почитайте мои посты сначала.
neiver вне форума  
Непрочитано 20.03.2010, 01:08  
neiver
Временная регистрация
 
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
neiver на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Сообщение от kison Посмотреть сообщение
Там, где Вы ищете PINF - регистр зарезервирован для будущего использования.
Кстати спасибо за наводку, учту.
neiver вне форума  
Непрочитано 20.03.2010, 01:09  
kison
Почётный гражданин KAZUS.RU
 
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Сообщение от neiver Посмотреть сообщение
Частный случай.
Так все из этого и состоит. Из таких вот частностей.
Но раз механизм признан неприемлемым, то спорить не буду.
Странно что Вы в конструктор не добавили еще параметров - PINx,DDRx...

Сообщение от neiver Посмотреть сообщение
Почитайте мои посты сначала.
Я то их читаю. Похоже что я один вникаю в то, что Вы пишете.
Ждемс продолжения
kison вне форума  
Непрочитано 20.03.2010, 01:11  
kison
Почётный гражданин KAZUS.RU
 
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Сообщение от neiver Посмотреть сообщение
Кстати спасибо за наводку, учту.
Сходите на электроникс, там долго перебирались варианты. И с классами и со структурами и еще что то было. Решения универсального до сих пор нет
Или нет - не ходите. Так интересней
kison вне форума  
Непрочитано 20.03.2010, 01:48  
roxfan
Временная регистрация
 
Регистрация: 25.11.2009
Сообщений: 61
Сказал спасибо: 1
Сказали Спасибо 17 раз(а) в 17 сообщении(ях)
roxfan на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Попробуй вот так:
Код:
template ‹volatile unsigned char &port, uint8_t pin› class Pin
{
public:
	void Set() const
	{
		port |= (1 ‹‹ pin);
	}
	void Set(uint8_t val) const
	{
		if(val)
			Set();
		else Clear();
	}
	void Clear()const
	{
		port &= (uint8_t)~(1 ‹‹ pin);
	}
	void Togle()const
	{
		port ^= (1 ‹‹ pin);
	}
	void SetDirWrite ()const
	{
		*(&port - 1) |= (1 ‹‹ pin);
	}
	void SetDirRead()const
	{
		*(&port - 1) &= (uint8_t)~(1 ‹‹ pin);
	}
	uint8_t IsSet()const
	{
		return (*(&port - 2)) & (uint8_t)(1 ‹‹ pin);
	}
};

Pin‹PORTA, 1› pin1;
Объект памяти не занимает, а компилятор может проделать максимальную оптимизацию, т.к. все констаты подставляются во время компиляции.
Не тестировал, т.к. не программлю под AVR, но пробовал такой подход на армах, результат положительный.
roxfan вне форума  
Непрочитано 20.03.2010, 11:21  
neiver
Временная регистрация
 
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
neiver на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Сообщение от roxfan Посмотреть сообщение
Попробуй вот так:
Об этом дальше. Я этот путь уже прошел. Буду потихоньку выкладывать.
neiver вне форума  
Непрочитано 20.03.2010, 13:36  
neiver
Временная регистрация
 
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
neiver на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Можно попробовать передать порт и номер пина в виде шаблонных параметров.
Однако сделать это непосредственно, как уже советуют некоторые товарищи, к сожалению не получится:
Код:
template ‹volatile unsigned char &port, uint8_t pin› 
class Pin
{…};
Pin‹PORTA, 1› pin1;
В Си++ нетиповые параметры шаблонов могут быть только интегральных типов: целые, bool и перечисления - всё. Ни указатель, ни ссылку, ни вещественное число, нельзя использовать, по крайней мере, в текущей реализации.
Придётся вводить ещё один уровень абстракции. Надо как-то заменить
volatile unsigned char &port;
на тип, чтобы его можно было передать в шаблон в качестве типового параметра.
То есть нужен тип, который бы представлял порт – по одному типу на каждый порт. Для этого придётся воспользоваться препроцессором:
Код:
#define MAKE_PORT(portName, ddrName, pinName, className) \
	struct className{\
		static volatile uint8_t &data()\
		{\
			return portName;\
		}\
		static volatile uint8_t &dir()\
		{\
			return ddrName;\
		}\
		static volatile uint8_t &pin()\
		{\
			return pinName;\
		}\
		static void Write(uint8_t value)\
		{\
			data() = value;\
		}\
		static uint8_t Read()\
		{\
			return data();\
		}\
	};
А теперь объявим портов на все случаи жизни, благо портов не много (если кому-то мало – можно и ещё добавить):
Код:
#ifdef PORTA
MAKE_PORT(PORTA, DDRA, PINA, Porta)
#endif

#ifdef PORTB
MAKE_PORT(PORTB, DDRB, PINB, Portb)
#endif

#ifdef PORTC
MAKE_PORT(PORTC, DDRC, PINC, Portc)
#endif

#ifdef PORTD
MAKE_PORT(PORTD, DDRD, PIND, Portd)
#endif

#ifdef PORTE
MAKE_PORT(PORTE, DDRE, PINE, Porte)
#endif

#ifdef PORTF
MAKE_PORT(PORTF, DDRF, PINF, Portf)
#endif

#ifdef PORTG
MAKE_PORT(PORTG, DDRG, PING, Portg)
#endif
Теперь у нас есть классы Porta, Portb,…,Portg если объявлены соответствующие им регистры.
И класс для пина можно теперь переписать так:
Код:
template‹class PORT, uint8_t PIN›
class TPin
{
public:
	static void Set()
	{
		PORT::data() |= (1 ‹‹ PIN);
	}
	static void Set(uint8_t val)
	{
		if(val)
			Set();
		else Clear();
	}
	static void Clear()
	{
		PORT::data() &= (uint8_t)~(1 ‹‹ PIN);
	}
	static void Togle()
	{
		PORT::data() ^= (1 ‹‹ PIN);
	}
	static void SetDirRead()
	{
		PORT::dir() &= (uint8_t)~(1 ‹‹ PIN);
	}
	static void SetDirWrite()
	{
		PORT::dir() |= (1 ‹‹ PIN);
	}
	static uint8_t IsSet()
	{
		return PORT::pin() & (uint8_t)(1 ‹‹ PIN);
	}	
	static void WaiteForSet()
	{
		while(IsSet()==0){}
	}
	static void WaiteForClear()
	{
		while(IsSet()){}
	}
};
Теперь посмотрим какой код будет генерироваться при использовании этого подхода:

Код:
TPin‹Porta, PA2› pin1;
int main()
{
	pin1.SetDirWrite();
	pin1.Set();
	pin1.Clear();
	pin1.Togle();
	pin1.SetDirRead();
	if(pin1.IsSet())
		pin1.Clear();
}
И в результате получаем то, что нужно. Даже при использовании глобальной переменной код оптимизируется как надо.
Код:
main:
	sbi 58-32,2
	sbi 59-32,2
	cbi 59-32,2

	in r24,59-32
	ldi r25,lo8(4)
	eor r24,r25
	out 59-32,r24

	cbi 58-32,2
	sbic 57-32,2
	cbi 59-32,2

	ldi r24,lo8(0)
	ldi r25,hi8(0)
	ret
Класс TPin полностью статический и переменную, в принципе, можно вообще не объявлять:
Код:
TPin‹Porta, PA2›::Set();
Однако удобнее её всё-таки объявить – места она всё равно не занимает.
neiver вне форума  
Непрочитано 20.03.2010, 23:34  
neiver
Временная регистрация
 
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
neiver на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

А теперь простой пример использования таких пинов.
Это класс для управления униполярным шаговым двигателем, которые подключен через интегральный драйвер, например популярный L293.

Код:
template‹class IN1, class IN2, class E1, class IN3, class IN4, class E2›
class SimpleStepper //L293 driver, for example
{
public:
	static void StepBack()
	{
		_phase = (_phase - 1) & 0x3;
		SetOutput();
	}
	static void StepFwd()
	{
		_phase = (_phase + 1) & 0x3;
		SetOutput();
	}
	static void Enable()
	{
		E1::SetDirWrite();
		E2::SetDirWrite();
		IN1::SetDirWrite();
		IN2::SetDirWrite();
		IN3::SetDirWrite();
		IN4::SetDirWrite();
		E1::Set();
		E2::Set();
	}
	static void Disable()
	{
		E1::Clear();
		E2::Clear();
	}
protected:
	static void SetOutput()
	{
		switch(_phase)
		{
			case 0:
				IN1::Set(); IN2::Clear(); IN3::Clear(); IN4::Clear();
			break;
			case 1: 
				IN1::Clear(); IN2::Clear(); IN3::Set(); IN4::Clear();
			break;
			case 2: 
				IN1::Clear(); IN2::Set(); IN3::Clear(); IN4::Clear();
			break;
			case 3: 
				IN1::Clear(); IN2::Clear(); IN3::Clear(); IN4::Set();
			break;
		}
	}
	static uint8_t _phase;
};

template‹class IN1, class IN2, class E1, class IN3, class IN4, class E2›
	uint8_t SimpleStepper‹IN1, IN2, E1, IN3, IN4,  E2›::_phase=0;
А вот так его можно использовать:
Код:
SimpleStepper
‹
	TPin‹Portc, 4›,	//in1
	TPin‹Portc, 5›,	//in2
	TPin‹Portd, 7›,	//e1
	TPin‹Portc, 6›,	//in3
	TPin‹Portc, 7›,	//in4
	TPin‹Portd, 6›	//e2
› stepper;
int main()
{
	while(1)
	{
		stepper.StepFwd();
		_delay_ms(5);
}
}
Преимущества такого подхода перед традиционным «сишным», когда порты и пины задаются define-ами:
- можно использовать любые доступные пины на любых имеющихся портах. В традиционном подходе пришлось бы написать 12 define-ов. Поэтому было естествнным стремление использовать ноги с одного порта, что не всегда возможно.
- вся конфигурация осуществляется в единственном месте – вместе использования класса. Не надо править библиотечные файлы под каждый проект, или объявлять кучу глобальных define-ов.
- можно подключить столько шаговиков сколько портов хватит. Объявляем ещё объекты SimpleStepper со своими наборами параметров и всё. В сишном подходе для этого придётся дублировать код, или вручную или с помощью препроцессора.
- код получается более чистым и легко читаемым, по сравнению с использованием битовых операций.
neiver вне форума  
Эти 5 пользователя(ей) сказали Спасибо neiver за это сообщение:
alexgap (21.03.2010), Highlander (04.02.2011), look22 (05.06.2011), luxin (27.01.2011), sspivak (29.03.2010)
Непрочитано 21.03.2010, 00:32  
kison
Почётный гражданин KAZUS.RU
 
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: О программировании AVR на C++.

Сообщение от neiver Посмотреть сообщение
Преимущества такого подхода перед традиционным «сишным», когда порты и пины задаются define-ами:
- можно использовать любые доступные пины на любых имеющихся портах. В традиционном подходе пришлось бы написать 12 define-ов. Поэтому было естествнным стремление использовать ноги с одного порта, что не всегда возможно.
О преимуществах написали. Давйте теперь и о недостатках. Ваш метод не проиграет традиционному сишному ( рассматриваем Ваш пример с ШД) только в случае, если все четыре вывода взяты с разных портов. А выиграть не сможет вообще никогда. Иначе - увы и ах, но за нежелание писать дефайны придется платить производительностью и размером программы. Если выводы все же на одном порту - Ваш метод дольше раза в три и больше тоже примерно в три раза. Не верите? Соберите для порта F, да вообще любого, куда не достает sbi.
В Вашем же примере все будет еще запущеннее - у Вас там четыре ветки внутри case. Я от такого листинга, который Вы получите, плакать начинаю или на людей кидаться.
Есть еще случаи с так называемым запрещенным состоянием выводов. Ну к примеру два вывода могут иметь состояние 10 или 01. А 00 и 11 - запрещены. Ваши действия? В традиционном подходе это не вызывает затруднений.
В общем реальный плюс один - лентяям, не желающим один раз за проект написать несколько дефайнов, способ понравится. Правда потом лентяям может придется потратить несколько дней, пытаясь всунуть раздувшуюся прошивку в выбранный кристалл... Есть история о одном байте. Не читали? Гугл сразу находит.
Я могу еще пару недостатков привести, но уже лень набирать.
kison вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
AVR JTAGICE MKII - проблемы firmware... Luxurious AVR 25 20.10.2014 10:50
Ищу книги по AVR rocky7 Микроконтроллеры, АЦП, память и т.д 9 17.03.2010 12:43
AVR. Как правильно совместить LCD и ISP на PORTB? Serg3621 Микроконтроллеры, АЦП, память и т.д 8 04.02.2010 14:03


Часовой пояс GMT +4, время: 21:15.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot