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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
SarCity
Прорезались зубы
Сообщения: 215
Зарегистрирован: Вт июн 10, 2008 09:17:06
Откуда: г. Саратов
Контактная информация:

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

Сообщение SarCity »

Т.к. я чайник мне это не осилить.
Реклама
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

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

Сообщение urry »

могу как бы разочаровать - именно чайники это осваивают в первую очередь.
Есть выбор как бы и он за вами....
Реклама
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

urry +1
SarCity писал(а):Т.к. я чайник мне это не осилить.
нужно найти где тело прописано
не нам же его писать,тем более, что это уже готовый проект.смотрите на сайте тело выглядит так :
тип_переменной имя_функции (тип_переменной имя_входящих_данных [,тип_переменной имя_входящих_данных ]){
объявления используемых внутри тела переменных;
действия ;}

то что в квадратных скобках может отсутствовать,а может повторяться.
остальные знаки препинания обязательны.
В поисках истины человек развивается.
Аватара пользователя
_dark
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт апр 26, 2012 14:30:40
Откуда: под Москвой

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

Сообщение _dark »

Говоря по простому, где-то должен быть *.c файл с прототипом и телом функции, а для использования этой функции во внешних модулях, в *.h файле указываем прототип объявленный как extern, например:

файл urchin.с // о ежах
void kill_urchin(void) // прототип, объявление
.... //
void kill_urchin(void) // тело
{
... // убиваем ежа здесь
}

и файл urchin.h // подключаем его в том модуле, в котором нужно прибить ежа
extern void kill_urchin(void)

если нам нужно нужно убить ежа в другом модуле, то:

int main(void)
{
#include "urchin.h" // подключаем все внешние обявления о ежах
....
kill_urchin(); // наконец-то мы прибили ежа!
...
return 0;
}

З.Ы.
по моему народ путается с вариантом для компиляторов RAD или VC, где достаточно в h(hpp) объявить
extern void kill_urchin(void), а сам прототип можно опустить, но насколько я помню для WINAVR, ICC, IAR прототип нужно указывать обязательно...
Реклама
Эиком - электронные компоненты и радиодетали
hubble
Родился
Сообщения: 13
Зарегистрирован: Вс июн 14, 2009 00:34:38

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

Сообщение hubble »

Прошу помощи по ассемблеру.

Не могу найти ошибку!!!
Имеется код на асме, который в CodeVision отлично работает.

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

#include <avr/io.h>

// Умножение (возведение в квадрат) 2-х 16-ти битных чисел (погрешность - 2 младших байта)  
unsigned int mul16x16_square(unsigned int a, unsigned int b)
{
unsigned int result;
unsigned char tmp = 0;

	asm volatile(  										
	    "clr     %[TMP]"									"\n\t"
	    "mul     %B[A], %B[B]"				";Ah * Bh	 \n\t"
	    "movw    %C[RES], r0"							"\n\t"
	    "mul     %A[A], %A[B]"				";Al * Bl	 \n\t"	
	    "movw    %A[RES], r0"							"\n\t" 
	    "fmul    %B[A], %A[B]"				";Ah * Bl	 \n\t"	
	    "adc	 %D[RES], %[TMP]"							"\n\t"
	    "add	 %B[RES], r0"							"\n\t"
	    "adc	 %C[RES], r1"							"\n\t"    
	    "adc	 %D[RES], %[TMP]"							"\n\t"   
	    : [RES]"=&r" (result), [TMP]"=&r" (tmp)
	    : [A]"a" (a), [B]"a" (b) 	  
	);
	return result;
}

int main(void)
{
uint16_t qqq= 0x1234;

	while(1)
	{
		mul16x16_square(qqq, qqq);
		asm("nop"::);
	}	
}
Это часть дизассемблера, которая интересует (без оптимизации):

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

+0000002E:   818C        LDD       R24,Y+4        Load indirect with displacement
+0000002F:   819D        LDD       R25,Y+5        Load indirect with displacement
+00000030:   812E        LDD       R18,Y+6        Load indirect with displacement
+00000031:   813F        LDD       R19,Y+7        Load indirect with displacement
+00000032:   01AC        MOVW      R20,R24        Copy register pair
+00000033:   24FF        CLR       R15            Clear Register
+00000034:   9F53        MUL       R21,R19        Multiply unsigned
[b]+00000035:   0190        MOVW      R18,R0         Copy register pair
+00000036:   9F42        MUL       R20,R18        Multiply unsigned[/b]
+00000037:   0180        MOVW      R16,R0         Copy register pair
+00000038:   035A        FMUL      R21,R18        Fractional multiply unsigned
+00000039:   1D3F        ADC       R19,R15        Add with carry
+0000003A:   0D10        ADD       R17,R0         Add without carry
+0000003B:   1D21        ADC       R18,R1         Add with carry
+0000003C:   1D3F        ADC       R19,R15        Add with carry
+0000003D:   831B        STD       Y+3,R17        Store indirect with displacement
+0000003E:   830A        STD       Y+2,R16        Store indirect with displacement
+0000003F:   82F9        STD       Y+1,R15        Store indirect with displacement
А это - та же интересующая часть, только с полной оптимизацией:

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

+0000001C:   01AC        MOVW      R20,R24        Copy register pair
+0000001D:   2788        CLR       R24            Clear Register
+0000001E:   9F57        MUL       R21,R23        Multiply unsigned
[b]+0000001F:   01A0        MOVW      R20,R0         Copy register pair
+00000020:   9F46        MUL       R20,R22        Multiply unsigned[/b]
+00000021:   0190        MOVW      R18,R0         Copy register pair
+00000022:   035E        FMUL      R21,R22        Fractional multiply unsigned
+00000023:   1F58        ADC       R21,R24        Add with carry
+00000024:   0D30        ADD       R19,R0         Add without carry
+00000025:   1D41        ADC       R20,R1         Add with carry
+00000026:   1F58        ADC       R21,R24        Add with carry
Соответствующий выделенным в тексте строкам код:

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

"movw    %C[RES], r0"
"mul     %A[A], %A[B]"

Не обращая особо ваше внимание на алгоритм, у меня такой вопрос.
Почему в строках (в дизасме они выделены жирным) задействованы одинаковые регистры. Ведь в коде, вроде бы, все правильно стоит (имеется в виду вывод в новый регистр - модификатор '&' в строке вывода - : [RES]"=&r" (result), [TMP]"=&r" (tmp)), а используется один и тот же регистр. В данных случаях - это R18 и R20.
Соответственно результат, который должен быть равен: 1234h * 1234h = 14B 5A90h не получается правильным.
В моих случаях (и в одном и в другом мне интересны только старшие байты) такие результаты:
1(оптимизация откл.) - 1 4Dh
2(оптимизация вкл.) - 1 44h

Ассемблерный код рабочий (проверен в CV).
Где я ошибаюсь?
Реклама
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

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

Сообщение zero648 »

А почему бы не умножать на си, если пишешь на си, зачем умножать на асме? Или умножай на чистом асме, а так получается компилятор сам выбирает регистры, с которыми ему удобней работать.
Реклама
hubble
Родился
Сообщения: 13
Зарегистрирован: Вс июн 14, 2009 00:34:38

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

Сообщение hubble »

zero648 писал(а):А почему бы не умножать на си, если пишешь на си, зачем умножать на асме? Или умножай на чистом асме ...
Дело в том, что умножение 2х 16ти битных чисел - это лишь маленькая часть проекта.
zero648 писал(а):... а так получается компилятор сам выбирает регистры, с которыми ему удобней работать.
Так-то оно, так. Но как же тогда правильно выбрать регистры? Собственно - этот вопрос и требуется мне разрешить.
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

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

Сообщение zero648 »

Значит пиши на асме и сам придумай алгоритм умножения, тогда компилятор будет использовать твои регистры, т.е. повторит то что ты напишешь.
Можно умножить на си, а алгоритм дизасмом выдрать.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

алгоритм сложно дизасмом выдирать. Компилятор повторяющиеся части выделяет в куски, которые потом сложно вместе собирать.кусок от деления, умножения может сочетаться с другими кусками, причем еще все это с относительной адресацией между переходами.
задача не для слабонервных.
если только два числа умножить и посмотреть что получилось.
В поисках истины человек развивается.
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

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

Сообщение DruidCat »

Мужики, помогите, мне очень стыдно, но я совсем не знаю С++, создаю свой проект на WinAVR и столкнулся с колосальной нехваткой знаний по С++. Помогите пожалуйста, я читал посты на этом форуме и не смог найти ответ.
Мне нужно превратить число (int) в символы (char). В этой теме я нашел подобный пример на atoi:

#include <stdlib.h>
char *number = "123";
int n = atoi(number);

А мне нужно сделать наоборот.
Я пытался сделать так:

int n=123;
char number = atoi(n);

у меня компилятор выдает предупреждения.
Помогите мужики, если вам не тяжело, и желательно на примере, совсем у меня знаний не хватает по С++. И еще, не подскажите, как можно подсчитать колличество символов в таком массиве?
char a[]="много символов";
Заранее спасибо, я читаю ваш форум, и нахожу ответы на свои вопросы. Особенно спасибо urry, vitalik_1984 и ARV.
Кот должен прожить жизнь без сожаления.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

Недавно обсуждалось здесь: http://radiokot.ru/forum/viewtopic.php?f=20&t=76244

P.S. Это вовсе не C++. Просто C.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

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

Сообщение DruidCat »

Спасибо за ответ. Не подскажете как работает вот эта строчка s[i++] = n % 10 + '0'; в листинге:
/* itoa: конвертируем n в символы в s */
void itoa(int n, char s[])
{
int i, sign;

if ((sign = n) < 0) /* записываем знак */
n = -n; /* делаем n положительным числом */
i = 0;
do { /* генерируем цифры в обратном порядке */
s[i++] = n % 10 + '0'; /* берем следующую цифру */
} while ((n /= 10) > 0); /* удаляем */
if (sign < 0)
s[i++] = '-';
s = '\0';
reverse(s);
}
Я не пойму что значит n %10 + '0', как это работает? Я понимаю что тут заполняется массив слова в цифрах. Мне знаний не хватает. :(
Кот должен прожить жизнь без сожаления.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

DruidCat писал(а):Я не пойму что значит n %10 + '0'
По пунктам:

n %10 - остаток от деления n на 10, т.е. младшая цифра десятичного представления n.
'0' - код литеры 0 в используемой Вами однобайтной кодировке (на 99.999....% это ASCII).
Вся конструкция в целом - код литеры, соответствующей младшему десятичному разряду n.

Пример: n = 367, тогда n %10 + '0' == '7' == 0x37 == 067 == 55
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

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

Сообщение DruidCat »

Я сейчас скачал таблицу ASCII, посмотрел, действительно все совпадает. Ничего себе, как придумано уравнение здорово и просто.
Я так понял что в строке эта цифра удаляется как десятичный остаток (n = n/10):
while ((n /= 10) > 0); /* удаляем */

Можно еще вопрос?
А вот функция void itoa(int n, char s[])
Она ведь принимает два значение int n, char s[], или же она принимает значение числа int n, и объявляет массив char s[]?

PS: Спасибо за помощь многоуважаемый кот. :beer:
Кот должен прожить жизнь без сожаления.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

DruidCat писал(а):Ничего себе, как придумано уравнение здорово и просто.
Используется тот факт, что цифры в кодировке ASCII идут подряд. Поэтому достаточно прибавить цифру к коду нуля, чтобы получить код литеры для этой цифры. Обратное преобразование делается столь же просто - из кода литеры вычитаем код нуля и получаем значение цифры.

В других кодировках обычно также придерживаются подобного принципа. Например, в ныне почти забытой EBCDIC цифры тоже упорядочены.
DruidCat писал(а):Я так понял что в строке эта цифра удаляется как десятичный остаток (n = n/10):
while ((n /= 10) > 0); /* удаляем */
Совершенно верно. И так до тех пор, пока цифр не останется вовсе (условие > 0).
DruidCat писал(а):Можно еще вопрос?
А вот функция void itoa(int n, char s[])
Она ведь принимает два значение int n, char s[], или же она принимает значение числа int n, и объявляет массив char s[]?
Клиент (то есть код, вызывающий функцию) должен предоставить буфер достаточной для хранения текстового представления числа длины (с учетом признака конца строки '\0', а то можно и в чужую область залезть) и передать указатель на него (поскольку фактически объявление char s[] является указателем на начало массива, а не самим массивом).

P.S. Вообще тема массивов и указателей, пожалуй, наиболее скользкая в языке C. Если хотите разобраться, рекомендую книгу: Ted Jensen. Tutorial on Pointers and Arrays in C.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

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

Сообщение DruidCat »

Спасибо большое за подробный ответ. :)
PS: В инете нашел только на английском языке эту книгу "Ted Jensen. Tutorial on Pointers and Arrays in C."
Кот должен прожить жизнь без сожаления.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

DruidCat писал(а):PS: В инете нашел только на английском языке эту книгу "Ted Jensen. Tutorial on Pointers and Arrays in C."
Да, это она и есть, мне не попадался ее перевод на русский. Впрочем, обычная ситуация - хороших книг почти не переводят, в основном макулатуру.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
slavokhire5
Прорезались зубы
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

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

Сообщение slavokhire5 »

Доброго времени суток, форумчане. Появилось свободное время, начал ковырять отправку данных через COM-port.
Написал какой-никакой код. Естественно, не компилится =) Голову себе сломал, не пойму в чем ошибка

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

if ((FLAGS & RESEIVED) == RESEIVED) 
{
	// взять символ из буфера
	reseive[RI] = USART_GetChar();
				
	// c каждым новым символом обновляем CRC
	if ((RI > 0) && (RI < reseive[1] + 3)) 		Calculate_CRC16(reseive[RI],CRC16);
		
	// проверяем правильность стартовых и стоповых байтов
	if (RI == 0) 
	{	
		if (reseive[RI] == StartByte) 
		{
			FLAGS |= START_STOP_OK;
		}
		else FLAGS &= ~ START_STOP_OK;
	}
	if (RI == (reseive[1] + 6)) 
	{	
		if (reseive[RI] == StopByte) 
		{
			FLAGS |= START_STOP_OK;
			FLAGS |= RD_MSG;
		}
	              else FLAGS &= ~ START_STOP_OK;
	}
	
              // если последний информационный байт сообщения принят - сверяем CRC
	if (RI == reseive[1] + 4)								
	{
		if ((CRC16 >> 8) == reseive[RI]) 
		{
			FLAGS |= CRC_OK;
		}
		else FLAGS &= ~CRC_OK;						
	}
	if ((RI == reseive[1] + 5)	&& (FLAGS & CRC_OK))							
	{
		if ((CRC16 & 0x00FF) == reseive[RI]) 
		{
			FLAGS |= CRC_OK;
		}
		else FLAGS &= ~CRC_OK;						
	}
			
	RI ++;
	FLAGS &= ~ RESEIVED;
}
ругается на первую строку приведенного кода: main.c:121: error: expected ')' before ';' token
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

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

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

#define RESEIVED 0x01;//приведет к ошибке, которую вы указали
#define RESEIVED 0x01 //правильно
 

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

 
 if ((FLAGS & RESEIVED) == RESEIVED) 
 
если проверяется только один флаг, то можно опустить сравнение так как это еще одна команда.Можно вот так

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

 if (FLAGS & RESEIVED) {
}
 

Возможно конечно компилятор опустит эту команду ввиду однозначнсти решения, но не факт.
Хотя в общем можно и оставить для лучшей читаемости.
В поисках истины человек развивается.
Аватара пользователя
slavokhire5
Прорезались зубы
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

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

Сообщение slavokhire5 »

Да, действительно у меня в дефайне ошибка. Спасибо большое:)
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Ответить

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