WinAvr в вопросах и ответах
- SarCity
- Прорезались зубы
- Сообщения: 215
- Зарегистрирован: Вт июн 10, 2008 09:17:06
- Откуда: г. Саратов
- Контактная информация:
Re: WinAvr в вопросах и ответах
Т.к. я чайник мне это не осилить.
- Реклама
- urry
- Сверлит текстолит когтями
- Сообщения: 1262
- Зарегистрирован: Пн дек 08, 2008 10:58:48
- Откуда: Винница
- Контактная информация:
Re: WinAvr в вопросах и ответах
могу как бы разочаровать - именно чайники это осваивают в первую очередь.
Есть выбор как бы и он за вами....
Есть выбор как бы и он за вами....
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: WinAvr в вопросах и ответах
urry +1
не нам же его писать,тем более, что это уже готовый проект.смотрите на сайте тело выглядит так :
тип_переменной имя_функции (тип_переменной имя_входящих_данных [,тип_переменной имя_входящих_данных ]){
объявления используемых внутри тела переменных;
действия ;}
то что в квадратных скобках может отсутствовать,а может повторяться.
остальные знаки препинания обязательны.
нужно найти где тело прописаноSarCity писал(а):Т.к. я чайник мне это не осилить.
не нам же его писать,тем более, что это уже готовый проект.смотрите на сайте тело выглядит так :
тип_переменной имя_функции (тип_переменной имя_входящих_данных [,тип_переменной имя_входящих_данных ]){
объявления используемых внутри тела переменных;
действия ;}
то что в квадратных скобках может отсутствовать,а может повторяться.
остальные знаки препинания обязательны.
В поисках истины человек развивается.
Re: WinAvr в вопросах и ответах
Говоря по простому, где-то должен быть *.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 прототип нужно указывать обязательно...
файл 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 прототип нужно указывать обязательно...
Re: WinAvr в вопросах и ответах
Прошу помощи по ассемблеру.
Не могу найти ошибку!!!
Имеется код на асме, который в CodeVision отлично работает.
Это часть дизассемблера, которая интересует (без оптимизации):
А это - та же интересующая часть, только с полной оптимизацией:
Соответствующий выделенным в тексте строкам код:
Не обращая особо ваше внимание на алгоритм, у меня такой вопрос.
Почему в строках (в дизасме они выделены жирным) задействованы одинаковые регистры. Ведь в коде, вроде бы, все правильно стоит (имеется в виду вывод в новый регистр - модификатор '&' в строке вывода - : [RES]"=&r" (result), [TMP]"=&r" (tmp)), а используется один и тот же регистр. В данных случаях - это R18 и R20.
Соответственно результат, который должен быть равен: 1234h * 1234h = 14B 5A90h не получается правильным.
В моих случаях (и в одном и в другом мне интересны только старшие байты) такие результаты:
1(оптимизация откл.) - 1 4Dh
2(оптимизация вкл.) - 1 44h
Ассемблерный код рабочий (проверен в CV).
Где я ошибаюсь?
Не могу найти ошибку!!!
Имеется код на асме, который в 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 в вопросах и ответах
А почему бы не умножать на си, если пишешь на си, зачем умножать на асме? Или умножай на чистом асме, а так получается компилятор сам выбирает регистры, с которыми ему удобней работать.
Re: WinAvr в вопросах и ответах
Дело в том, что умножение 2х 16ти битных чисел - это лишь маленькая часть проекта.zero648 писал(а):А почему бы не умножать на си, если пишешь на си, зачем умножать на асме? Или умножай на чистом асме ...
Так-то оно, так. Но как же тогда правильно выбрать регистры? Собственно - этот вопрос и требуется мне разрешить.zero648 писал(а):... а так получается компилятор сам выбирает регистры, с которыми ему удобней работать.
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: WinAvr в вопросах и ответах
Значит пиши на асме и сам придумай алгоритм умножения, тогда компилятор будет использовать твои регистры, т.е. повторит то что ты напишешь.
Можно умножить на си, а алгоритм дизасмом выдрать.
Можно умножить на си, а алгоритм дизасмом выдрать.
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: WinAvr в вопросах и ответах
алгоритм сложно дизасмом выдирать. Компилятор повторяющиеся части выделяет в куски, которые потом сложно вместе собирать.кусок от деления, умножения может сочетаться с другими кусками, причем еще все это с относительной адресацией между переходами.
задача не для слабонервных.
если только два числа умножить и посмотреть что получилось.
задача не для слабонервных.
если только два числа умножить и посмотреть что получилось.
В поисках истины человек развивается.
Re: WinAvr в вопросах и ответах
Мужики, помогите, мне очень стыдно, но я совсем не знаю С++, создаю свой проект на 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.
Мне нужно превратить число (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 в вопросах и ответах
Недавно обсуждалось здесь: http://radiokot.ru/forum/viewtopic.php?f=20&t=76244
P.S. Это вовсе не C++. Просто C.
P.S. Это вовсе не C++. Просто C.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
J. Ganssle
Re: WinAvr в вопросах и ответах
Спасибо за ответ. Не подскажете как работает вот эта строчка 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', как это работает? Я понимаю что тут заполняется массив слова в цифрах. Мне знаний не хватает.
/* 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 в вопросах и ответах
По пунктам: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
J. Ganssle
Re: WinAvr в вопросах и ответах
Я сейчас скачал таблицу ASCII, посмотрел, действительно все совпадает. Ничего себе, как придумано уравнение здорово и просто.
Я так понял что в строке эта цифра удаляется как десятичный остаток (n = n/10):
while ((n /= 10) > 0); /* удаляем */
Можно еще вопрос?
А вот функция void itoa(int n, char s[])
Она ведь принимает два значение int n, char s[], или же она принимает значение числа int n, и объявляет массив char s[]?
PS: Спасибо за помощь многоуважаемый кот.
Я так понял что в строке эта цифра удаляется как десятичный остаток (n = n/10):
while ((n /= 10) > 0); /* удаляем */
Можно еще вопрос?
А вот функция void itoa(int n, char s[])
Она ведь принимает два значение int n, char s[], или же она принимает значение числа int n, и объявляет массив char s[]?
PS: Спасибо за помощь многоуважаемый кот.
Кот должен прожить жизнь без сожаления.
- Goldsmith
- Опытный кот
- Сообщения: 736
- Зарегистрирован: Пн янв 10, 2011 03:06:36
- Откуда: Ростов-на-Дону
- Контактная информация:
Re: WinAvr в вопросах и ответах
Используется тот факт, что цифры в кодировке ASCII идут подряд. Поэтому достаточно прибавить цифру к коду нуля, чтобы получить код литеры для этой цифры. Обратное преобразование делается столь же просто - из кода литеры вычитаем код нуля и получаем значение цифры.DruidCat писал(а):Ничего себе, как придумано уравнение здорово и просто.
В других кодировках обычно также придерживаются подобного принципа. Например, в ныне почти забытой EBCDIC цифры тоже упорядочены.
Совершенно верно. И так до тех пор, пока цифр не останется вовсе (условие > 0).DruidCat писал(а):Я так понял что в строке эта цифра удаляется как десятичный остаток (n = n/10):
while ((n /= 10) > 0); /* удаляем */
Клиент (то есть код, вызывающий функцию) должен предоставить буфер достаточной для хранения текстового представления числа длины (с учетом признака конца строки '\0', а то можно и в чужую область залезть) и передать указатель на него (поскольку фактически объявление char s[] является указателем на начало массива, а не самим массивом).DruidCat писал(а):Можно еще вопрос?
А вот функция void itoa(int n, char s[])
Она ведь принимает два значение int n, char s[], или же она принимает значение числа int n, и объявляет массив char s[]?
P.S. Вообще тема массивов и указателей, пожалуй, наиболее скользкая в языке C. Если хотите разобраться, рекомендую книгу: Ted Jensen. Tutorial on Pointers and Arrays in C.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
J. Ganssle
Re: WinAvr в вопросах и ответах
Спасибо большое за подробный ответ. 
PS: В инете нашел только на английском языке эту книгу "Ted Jensen. Tutorial on Pointers and Arrays in C."
PS: В инете нашел только на английском языке эту книгу "Ted Jensen. Tutorial on Pointers and Arrays in C."
Кот должен прожить жизнь без сожаления.
- Goldsmith
- Опытный кот
- Сообщения: 736
- Зарегистрирован: Пн янв 10, 2011 03:06:36
- Откуда: Ростов-на-Дону
- Контактная информация:
Re: WinAvr в вопросах и ответах
Да, это она и есть, мне не попадался ее перевод на русский. Впрочем, обычная ситуация - хороших книг почти не переводят, в основном макулатуру.DruidCat писал(а):PS: В инете нашел только на английском языке эту книгу "Ted Jensen. Tutorial on Pointers and Arrays in C."
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
J. Ganssle
- slavokhire5
- Прорезались зубы
- Сообщения: 202
- Зарегистрирован: Пн сен 26, 2011 13:48:25
- Откуда: Харьков
Re: WinAvr в вопросах и ответах
Доброго времени суток, форумчане. Появилось свободное время, начал ковырять отправку данных через COM-port.
Написал какой-никакой код. Естественно, не компилится =) Голову себе сломал, не пойму в чем ошибка
ругается на первую строку приведенного кода: main.c:121: error: expected ')' before ';' token
Написал какой-никакой код. Естественно, не компилится =) Голову себе сломал, не пойму в чем ошибка
Код: Выделить всё
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;
}
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
--------------------------
Пишу на Си за еду
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: WinAvr в вопросах и ответах
неплохо бы проект целиком, возможно где то в макросе ошибка сделана, а показывает здесь, потому что макрос вставляется компилятором как текст бездумно, а потом уже компилируется.
если проверяется только один флаг, то можно опустить сравнение так как это еще одна команда.Можно вот так
Возможно конечно компилятор опустит эту команду ввиду однозначнсти решения, но не факт.
Хотя в общем можно и оставить для лучшей читаемости.
Код: Выделить всё
#define RESEIVED 0x01;//приведет к ошибке, которую вы указали
#define RESEIVED 0x01 //правильно
Код: Выделить всё
if ((FLAGS & RESEIVED) == RESEIVED)
Код: Выделить всё
if (FLAGS & RESEIVED) {
}
Возможно конечно компилятор опустит эту команду ввиду однозначнсти решения, но не факт.
Хотя в общем можно и оставить для лучшей читаемости.
В поисках истины человек развивается.
- slavokhire5
- Прорезались зубы
- Сообщения: 202
- Зарегистрирован: Пн сен 26, 2011 13:48:25
- Откуда: Харьков
Re: WinAvr в вопросах и ответах
Да, действительно у меня в дефайне ошибка. Спасибо большое:)
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
--------------------------
Пишу на Си за еду


