PDA

Просмотр полной версии : Си для AVR



bob1
24.11.2009, 22:26
Вот пошел второй месяц как пытаюсь понять искусство писания на данном языке. Возник вопрос. Имею число типа Float хочу записать в EEProm. Как обратится к 1,2,3,4 байту числа Float???? Компилятор IAR Embedded Workbench.

ut1wpr
24.11.2009, 22:42
Вот пошел второй месяц как пытаюсь понять искусство писания на данном языке. Возник вопрос. Имею число типа Float хочу записать в EEProm. Как обратится к 1,2,3,4 байту числа Float???? Компилятор IAR Embedded Workbench.
Видимо, следует почитать про формат числа float в представлении библиотеки math.h для Вашего МК.
С трудом представляю, а для чего это может понадобиться? Наверное, я что-то упустил в жизни. :)

unname
24.11.2009, 22:58
главное не пользоваться АВРовским компилятором.
Я его года 4 назад мучал, потом посомтрел ассемблер с него на выходе, за голову взялся...
Если у него конструкции CASE и вложенные IF Выдают на выходе совершенно разный код...

Genadi Zawidowski
24.11.2009, 23:08
Вот пошел второй месяц как пытаюсь понять искусство писания на данном языке. Возник вопрос. Имею число типа Float хочу записать в EEProm. Как обратится к 1,2,3,4 байту числа Float???? Компилятор IAR Embedded Workbench.



typedef union
{
float f;
unsigned char a [sizeof (float)];
} bd_dloat;

....
bd_float v;

v.f = 355.0 / 113.0;
int i;

for (i = 0; i < sizeof v.f; ++ i)
write_one_byte_to_ee prom(offset + i, v.a [i]);


(не идеал, но как пример для этой архитектуры пойдёт)
или с использованием многобайтных функций записи в eeprom:




float v;

v = 355.0 / 113.0;

eeprom_busy_wait();
eeprom_write_block(d ata, (void *) offset_in_eeprom, sizeof v);

RU3XN
24.11.2009, 23:48
Я, конечно, в С не шибко силен, но я думаю, что компилятор будет не очень доволен. Ведь в объединение записали float, а берем из него unsigned char.

v.f = 355.0 / 113.0; это float, а здесь

write_one_byte_to_ee prom(offset + i, v.a [i]); уже не float

RU3XN
24.11.2009, 23:57
вообще-то не будет ругаться. Книжку почитал.

unname
25.11.2009, 00:03
а если побитовым сдвигом разделить значение float на 4 char и спокойно их сохранить в памяти?

EU1ME
25.11.2009, 00:24
Такие вещи делаю указателями.

bob1
25.11.2009, 08:29
unname
Ассемблер лучше не смотреть, что бы за голову не держаться :)
Genadi Zawidowski
Геннадий спасибо :пиво:. Уже попробовал--работает.
RU3XN
Что за книжка?
unname
НА побитовый сдвиг числа float компилятор ругается.
Alex007
Пробовал так:
float *A;
uint8_t *B;
B=A;
В 3 строчке пишет ошибка.
p.s.Проц ATxMega128A1. Там указатели занимают 3 байта.
Успехов!!

Genadi Zawidowski
25.11.2009, 08:33
Ещё так.


float f;
const uint8_t * p;
int8_t i;

p = (const uint8_t *) & f;
for (i = 0; i < sizeif f; ++ i)
write_byte_to_eeprom (offset + i, p [i]);


или вот так



float f;
int8_t i;

for (i = 0; i < sizeif f; ++ i)
write_byte_to_eeprom (offset + i, ((const uint8_t *) & f) [i]);



А что, функций блочной записи в eeprom нет?

EU1ME
25.11.2009, 09:13
void ddsSetFTW (unsigned long ftw)
{
unsigned char *ptrFTW;
ptrFTW = &ftw;

DDSCS=0;
Send_SPI (DDS_AD9954_FTW0);
Send_SPI ( *ptrFTW );
Send_SPI ( *(ptrFTW+1) );
Send_SPI ( *(ptrFTW+2) );
Send_SPI_END ( *(ptrFTW+3) );
DDSCS=1;
}


Вот пример для целого числа

bob1
25.11.2009, 11:11
Genadi Zawidowski
Спасибо за примеры. Буду разбираться. Блочной записи не нашел. Есть там страничная. Сначала в буфер,а потом всю страницу сразу.
Запись в буфер также побайтная, да и стр. занимает 32-64 байта.
Alex007
float TT;
uint8_t *oo;
oo=&TT;
На код выдает ошибку. С целым так же ошибка. Может в настройках поменять чего надо?????
Error[Pe513]: a value of type "float *" cannot be assigned to an entity of type "uint8_t *" E:\222\main.c 388
Успехов!!!

RU3XN
25.11.2009, 14:33
bob1

Да, обычная книга.
М.Полубенцева.
"С/С++.Процедурное программирование."

EU1ME
25.11.2009, 17:30
bob1
Я не знаю как в АВРах типы правильно обываются, возможно что и не так. У меня код для компилятора Keil, конкретно для 8051.

bob1
26.11.2009, 07:21
Alex007
Спасибо за подержку. Самому не понятно почему не проходит . Указатели имеют один формат. Борюсь с ним (компилятором). Он меня или я его :rotate: На asm давно наверно написал. :crazy:
Успехов!!

Genadi Zawidowski
26.11.2009, 09:17
float TT;
uint8_t *oo;
oo=&TT;
На код выдает ошибку. С целым так же ошибка. Может в настройках поменять чего надо?????
Error[Pe513]: a value of type "float *" cannot be assigned to an entity of type "uint8_t *" E:\222\main.c 388
Успехов!!!
oo = (uint8_t *) & TT;

Приведение типа в данном случае требуется.

Tadas
26.11.2009, 09:50
Имею число типа Float хочу записать в EEProm. Как обратится к 1,2,3,4 байту числа Float????
Так задача в чем ?
Записать Float в EEPROM или получить доступ к отдельным байтам ?

Если первое, то делается элементарно:

//---------------------------------------
float __eeprom fl;

fl=310.55;
//---------------------------------------

Обо всем остальном позаботится компилятор.

bob1
26.11.2009, 19:08
Genadi Zawidowski
Все стало на свои места. Надо было принудительно указатель привести!!!
Tadas
Компилятор наверно не правильный :-( . Не хочет предложенный Вами код брать.

Успехов!

Tadas
26.11.2009, 19:44
Не хочет предложенный Вами код брать.
Мой ИАР берет и не кашляет :)
Смотрел ассемблерный листинг - загружает число в регистры и вызывает библиотечную функцию записи в EEPROM .

А какими словами он Вас ругает ?

bob1
26.11.2009, 21:26
Tadas
С ATXmega тоже получается???? 8O
Error[Be009]: memory attributes not allowed on auto variables or parameters D:\222\main.c 450

Tadas
26.11.2009, 21:54
Про Хмегу не скажу, не приходилось щупать :-(

RU3XN
26.11.2009, 23:56
bob1

Попробуем разобраться.

float TT; здесь вы объявляете переменную TT типа float

uint8_t *oo; здесь - указатель на переменную oo типа unsigned integer

oo=&TT; тут вы хотитете переменной oo типа unsigned int
присвоить адрес переменной TT, компилятор ругается
на это, поскольку адрес можно присвоить только
переменной типа указатель.

Наверное надо было таким образом записать строку 3:

*oo=&TT;

Genadi Zawidowski
27.11.2009, 01:06
Наверное надо было таким образом записать строку 3:

*oo=&TT;

Что получается (не говоря о предупредлениях или ошибках) в этом варианте:

Берётся адрес переменной TT и один байт от него записываетс в память (куда-то в память - oo не инициализированно) по адресу, который содержится в переменной - указателе oo.

Кукин Николай Николаевич
27.11.2009, 12:23
uint8_t *oo; здесь - указатель на переменную oo типа unsigned integer

Неправильно.

Следует сказать
uint8_t *oo; здесь oo - указатель на переменную типа unsigned char (uint8_t – unsigned char).

Если рассматривать oo как область памяти, то в этом месте должен сидеть адрес переменной, имеющей тип unsigned char, а не сама переменная. И обращаться с оо необходимо как с адресом.
Выражение oo=&TT; на первый взгляд выглядит правильным, но компилятор указывает на ошибку.
Ошибка заключается в том, что в оо должен записываться адрес переменной unsigned char, а не float, а мы пытаемся записать адрес переменной , объявленной как float TT. Именно об этом и сообщение компилятора. Правила обработки переменных разных типов разные, и обработка указателей на unsigned char и float будет тоже производиться по разным правилам, т.е. в конечном счете будет сгенерирован разный ассемблерный текст.
Чтобы успокоить компилятор по формальным признакам, перед присваиванием нужно выполнить приведение типов, выражением oo= (uint8_t *) &TT;

Но это еще не означает, что Вы получите то, что хотели.

Ну , а то, что получилось у Вас, и как это будет работать, уже сказал Геннадий. Ведь в неинициализированной области памяти оо сидит вообще неизвестно что – то что осталось от предыдущих записей в эту область памяти.

Tadas
27.11.2009, 12:58
Error[Be009]: memory attributes not allowed on auto variables or parameters D:\222\main.c 450
Так это означает, что Вы пытаетесь создать локальную переменную с аттрибутом __eeprom.
Объявите ее как глобальную (вне функции) и все должно пойти.

bob1
27.11.2009, 18:21
Tadas
Скинул ошибку да нету(торопился). Создал новый проект --работает. Попробовал в своем не работает :-( . настройки одинаковые. По новой пересоздал проект и заработало :crazy: Спасибо.
Успехов!!

bob1
29.11.2009, 19:31
Подскажите еще такая проблема периодически возникает. Если в функцию передается много переменных, то компится нормально без ошибок,а работать не хочет. Начал разбираться IAR помечает часть данных в регистры и SRAM,а части назначает адреса ниже начального адреса SRAM-вот и не работает!!! В чем может быть проблема. Может стек мал??

Genadi Zawidowski
29.11.2009, 19:38
Вот пошел второй месяц как пытаюсь понять искусство писания на данном языке. Возник вопрос. Имею число типа Float хочу записать в EEProm. Как обратится к 1,2,3,4 байту числа Float???? Компилятор IAR Embedded Workbench.

Подскажите еще такая проблема периодически возникает. Если в функцию передается много переменных, то компится нормально без ошибок,а работать не хочет. Начал разбираться IAR помечает часть данных в регистры и SRAM,а части назначает адреса ниже начального адреса SRAM-вот и не работает!!!
В чем может быть проблема. Может стек мал??
На одном из сайтов видел замечательный баннер:
"Бригада квалифицированных телепатов ответит на ваши вопросы"
Какой процессор-то?
Обычно в таких проблемах помогает другим разбираться проект с проблемой (желательно демонстрационный - то есть, без лишнего кода, демонстрирующий проблему).

Tadas
29.11.2009, 20:07
Может стек мал??
Ну так увеличьте и попробуйте.

bob1
29.11.2009, 20:56
Tadas
Похоже перегрелся уже. Начал задавать глупые вопросы. Нашел ,где он. Увеличил CSTACK с 0x20 до 0x40 b и заработало :D
Успехов!!

unname
01.12.2009, 22:53
странно а чего он ругается?

UR3CMB
02.12.2009, 13:18
Здравствуйте уважаемые знатоки!
Хочу освоить С для AVRов. Посоветуйте какую нибудь полезную литературу актуальную для данного контекста. Или поделитесь если в кого есть. Спасибо

УС4ИЛЩ
02.12.2009, 13:49
UR3CMB

Я тоже только только начинаю учиться,
Вот кое что интересное:

CodeVisionAVR Пособие для начинающих М.Б.Лебедев 2008-600M.djvu
Микроконтроллеры AVR семейства Mega А.В.Евстифеев2007-600RM.djvu

Гуглем элементарно находится
И еще много чего

А так же интересные сайты

http://eugenemcu.ru/
http://chipenable.ru/index.php/programming-c
http://forum.cxem.net/index.php?s=a5681ee4 06acace56a399d2fe233 96ec&showforum=77
http://www.radiokot.ru/
http://www.remexpert.com/ipb/forum44.html
http://kazus.ru/forums/forumdisplay.php?f=6
http://arv.radioliga.com/component/option,com_frontpage/Itemid,1/
И еще много много других.

UR3CMB
02.12.2009, 14:01
УС4ИЛЩ
Спасибо! Попробую . Это пока энтузиазм не пропал :пиво:

УС4ИЛЩ
02.12.2009, 14:10
UR3CMB
Вот еще сайт:
http://avr123.nm.ru/
Сам я издеваюсь над АТмега 16 в КОДЕВИЖЕНЕ
:D

UR3CMB
02.12.2009, 18:22
УС4ИЛЩ
В полку садистов пополнение , ваш покрный слуга :D

Сергей из Киева
13.02.2010, 19:23
Мой ИАР берет и не кашляет.

У меня тоже от IAR Systems - подстрочник, из командной строки запускается, древний, когда ATmega8 уже был, а ATmega48 ещё не было. Так под очередной новый AVR-микроконтроллер соответствующий включаемый h-файл с адресами встроенной периферии и векторов прерываний только раздобыть надо, в крайнем случае в текстовом редакторе набрать - и всё работает. Всё, что есть в классическом ANSI C, есть и у этого, плюс микроконтроллерные особенности: раздельное размещение ОЗУ , ПЗУ и EEPROM, дополнительные директивы препроцессора для написания обработчиков прерываний, и пр. Математику с плавающей точкой поддерживает без ограничений, включая стандартные библиотечные функции. В общем, вполне доволен, и за новинками не гоняюсь...

Tadas
14.02.2010, 23:07
В общем, вполне доволен, и за новинками не гоняюсь...
В новых версиях по немножко плотность упаковки кода повышается.
Но часто это не принципиально.

Neman2000
03.03.2010, 20:03
Подскажите никто не пользовался этой программой- http://flowcode.info
,там у них на сайте по просьбе трудящихся и совершенно бесплатно мужик пишет программу за 15 минут и самое интересное говорит что и другие в течении месяца научатся.

RA4FOC
24.03.2010, 14:00
Хочу освоить С для AVRов. Посоветуйте какую нибудь полезную литературу актуальную для данного контекста.

CodeVision AVR. Пособие для начинающих. Лебедев М.Б.
http://atxmega.narod.ru/CodeVision_AVR.html

Там же диск к ней.

ut1wpr
24.03.2010, 14:48
Пользую IAR (случайно на улице нашел).
Для 51 и ARM - KEIL (случайно на улице нашел).
:)
Кто будет писать в коммерческих целях, советую на улице случайно не находить. Прекрасный продукт AVRGCC. Постоянно совершенствуется и сопровождается. Есть много доступной информации. Проверял, понравилось. Не перехожу из-за привычки и лени. Много "поделок" наваяно в Яре.

vadim_d
24.03.2010, 22:01
Прекрасный продукт AVRGCC.
Это который в WinAVR http://winavr.sourceforge.n et/ ? Если как Геннадий, взять Атмегу с запасом и не заморачиваться, то да. А если попытаться запихать функциональность синтезатора RD3AY (двухстрочного) в оригинальную Atmega8, то не вдруг. Сделал клавиатуру, валкодер (с учетверением :super: ), сопрограммную многозадачную среду и все это с минимальным вовлечением ассемблера. А тут написал две строчки расчета FCW DDS, сдвиг и деление 64-битного слова, и прослезился - две функции библиотеки наддали почти четыре килобайта. Опять ручками оптимизировать :-(

Кукин Николай Николаевич
25.03.2010, 10:33
To Vadim_d

Вадим, может то, что я скажу про Winavr, Вы уже знаете, тем не менее…

Если Вы не читали файл Optimize-Options.html, лежащий в winavr\doc\gcc\html\ gcc-4.3.0\gcc, (у Вас версия gcc может быть другая) то найдете там много интересного.

Во всяком случае, стандартный ключ максимальной оптимизации –Os не позволяет получить максимально глубокой оптимизации кода.
Тут надо пробовать вариации дополнительных параметров.
Попробуйте в маке-файле в опциях компиляции добавить, например, такие строчки и поиграть со значением inline-call-cost.
…………………
#---------------- Compiler Options C ----------------

…………………………………………………… .
#--------------------------------------------------
CFLAGS += --param inline-call-cost=1
CFLAGS +=-fno-split-wide-types
CFLAGS +=-ffunction-sections
CFLAGS +=-Wl,-gc-section
#--------------------------------------------------
…………………..

Кроме того, по вложенным функциям тоже интересно поиграть параметрами.
Так можно выкинуть более килобайта скомпилированного кода.
Но Вы безусловно правы в том, что библиотечные функции математики с плавающей точкой жрут очень нехило.
Николай.

vadim_d
25.03.2010, 14:20
Во всяком случае, стандартный ключ максимальной оптимизации –Os не позволяет получить максимально глубокой оптимизации кода.
Тут надо пробовать вариации дополнительных параметров.
Николай, все правильно, я начал с ключей оптимизации, потом перешел к аттрибутам отдельных функций, а потом к ассемблерным кускам.

Но Вы безусловно правы в том, что библиотечные функции математики с плавающей точкой жрут очень нехило.
Целочисленная арифметика под 64 бита ей мало уступает :D Видно, что задача ручной оптимизации решаемая (сделать пару своих функций для тех мест, где вычисления вылезают за 32 бита), осталось собраться с силами :D

ur8us
25.03.2010, 15:06
Прекрасный продукт AVRGCC.
Это который в WinAVR http://winavr.sourceforge.n et/ ? Если как Геннадий, взять Атмегу с запасом и не заморачиваться, то да. А если попытаться запихать функциональность синтезатора RD3AY (двухстрочного) в оригинальную Atmega8, то не вдруг. Сделал клавиатуру, валкодер (с учетверением :super: ), сопрограммную многозадачную среду и все это с минимальным вовлечением ассемблера. А тут написал две строчки расчета FCW DDS, сдвиг и деление 64-битного слова, и прослезился - две функции библиотеки наддали почти четыре килобайта. Опять ручками оптимизировать :-(

И это есть вполне нормально, и ничего страшного в "ручной" оптимизации нет. Встроенная "плавающая" арифметика, кроме большого объема библиотечного кода, обладает весьма ограниченной разрядностью, которая влечет за собой ограниченную точность вычислений. В результате, например, рассчитанное слово DDS может на одну-две единицы отличаться от нужного. Мелочь, но неприятно.

Когда-то я делал (на ассемблере, правда) арифметику для дробных чисел с фиксированной точкой. Такой подход оправдывает себя, когда заранее известны диапазоны значений чисел и требуемая точность вычислений. Думаю, что если переписать эти расчеты в виде функций на Си, получится довольно компактно.

Кстати, бОльшая часть кода программы для такой штуки, как синтезатор, посвящена не математике и не собственно программированию чипов DDS, а интерфейсу с пользователем - обработке нажатий на кнопочки, выводу на дисплей. Вот тут-то программисты на ассемблере натыкаются на большой "облом" совершенствовать интерфейс с пользователем (и в результате интерфейс остается "топорным"), а программисты на Си легким движением руки пишут несколько вариантов, а затем выбирают самый лучший.

А вот используя двухстрочный ЖКИ, можно испортить любую хорошую конструкцию...

Кукин Николай Николаевич
25.03.2010, 15:49
Вадим, получается Вы прошли весь путь. Тогда Вам остается копить силы.
:cry: :D Желаю удачи. :пиво:
Николай.

vadim_d
25.03.2010, 22:59
И это есть вполне нормально, и ничего страшного в "ручной" оптимизации нет. Встроенная "плавающая" арифметика, кроме большого объема библиотечного кода, обладает весьма ограниченной разрядностью, которая влечет за собой ограниченную точность вычислений.
В моем конкретном случае это была целочисленная, но 64-битная арифметика. Понятно, что переделать несложно.

Когда-то я делал (на ассемблере, правда) арифметику для дробных чисел с фиксированной точкой. Такой подход оправдывает себя, когда заранее известны диапазоны значений чисел и требуемая точность вычислений. Думаю, что если переписать эти расчеты в виде функций на Си, получится довольно компактно.
Для 8080, 8085 и Z80 я пользовал компилятор Aztec C под CP/M, но ассемблировал и собирал M80/L80. Родная библиотека была свалена в один модуль, который цеплялся при вызове любой функции. Побив его на мелкие кусочки (а исходники там были) удавалось сократить размер добавки до 0.5 кило при 16-битной арифметике. А чтобы удержаться в 16 битах при фиксированной точке, пришлось сделать единственную функцию mul_div(a,b,c), которая множила a*b с 32-битным результатом, который делила на c, возвращая 16 бит.

Кстати, бОльшая часть кода программы для такой штуки, как синтезатор, посвящена не математике и не собственно программированию чипов DDS, а интерфейсу с пользователем - обработке нажатий на кнопочки, выводу на дисплей.
Да и не только синтезаторов. Мой переход на Си произошел при написании программы управления тиристорным инвертором с принудительной коммутацией, причем для пользовательского интерфейса скорости не требовалось, а хотелось иметь читаемый код, дабы не погрязнуть в отладке.

ut1wpr
27.03.2010, 16:52
Прекрасный продукт AVRGCC.
Это который в WinAVR http://winavr.sourceforge.n et/ ? Если как Геннадий, взять Атмегу с запасом и не заморачиваться, то да. А если попытаться запихать функциональность синтезатора RD3AY (двухстрочного) в оригинальную Atmega8, то не вдруг. Сделал клавиатуру, валкодер (с учетверением :super: ), сопрограммную многозадачную среду и все это с минимальным вовлечением ассемблера. А тут написал две строчки расчета FCW DDS, сдвиг и деление 64-битного слова, и прослезился - две функции библиотеки наддали почти четыре килобайта. Опять ручками оптимизировать :-(

И это есть вполне нормально, и ничего страшного в "ручной" оптимизации нет. Встроенная "плавающая" арифметика, кроме большого объема библиотечного кода, обладает весьма ограниченной разрядностью, которая влечет за собой ограниченную точность вычислений. В результате, например, рассчитанное слово DDS может на одну-две единицы отличаться от нужного. Мелочь, но неприятно.

Когда-то я делал (на ассемблере, правда) арифметику для дробных чисел с фиксированной точкой. Такой подход оправдывает себя, когда заранее известны диапазоны значений чисел и требуемая точность вычислений. Думаю, что если переписать эти расчеты в виде функций на Си, получится довольно компактно.

Кстати, бОльшая часть кода программы для такой штуки, как синтезатор, посвящена не математике и не собственно программированию чипов DDS, а интерфейсу с пользователем - обработке нажатий на кнопочки, выводу на дисплей. Вот тут-то программисты на ассемблере натыкаются на большой "облом" совершенствовать интерфейс с пользователем (и в результате интерфейс остается "топорным"), а программисты на Си легким движением руки пишут несколько вариантов, а затем выбирают самый лучший.

А вот используя двухстрочный ЖКИ, можно испортить любую хорошую конструкцию...
Я боюсь показаться устаревшим... :) Я когда-то давно, для DDS считал FCW дедовским способом. Дело в том, что в программе я работал с ASCII представлением частот (можно BCD - без разницы). Держал таблицу весов FCW для каждого десятичного разряда. Ну, а дальше все просто. Суммировал все веса по количеству цифр в разрядах. Погрешности не наблюдал. Наблюдал отсутствие плавающей арифметики, что радовало.. :) Да и по скорости не уступало обработке FP. Может, кто подскажет, в чем минус этого подхода? Такое вот "полутабличное" преобразование...

vadim_d
27.03.2010, 17:51
Держал таблицу весов FCW для каждого десятичного разряда.
Виктор, тут можно и для каждого двоичного разряда таблицу весов сделать :D Если более серьезно, то деление возникает только один раз, и при постоянной опорной частоте останется только умножение. Здесь же заложена коррекция частоты опоры, поэтому хотя бы раз при старте деление остается (но скорость его может быть любой). В общем, сдвиг на 25 бит сделал, дабы Си не давал предупреждений об отсутствии возвращаемого значения перенесу этот кусок в чисто ассемблерный модуль. Взялся за неторопливое, но компактное деление :D

ur8us
29.03.2010, 05:35
Я боюсь показаться устаревшим... :) Я когда-то давно, для DDS считал FCW дедовским способом. Дело в том, что в программе я работал с ASCII представлением частот (можно BCD - без разницы). Держал таблицу весов FCW для каждого десятичного разряда. Ну, а дальше все просто. Суммировал все веса по количеству цифр в разрядах. Погрешности не наблюдал. Наблюдал отсутствие плавающей арифметики, что радовало.. :) Да и по скорости не уступало обработке FP. Может, кто подскажет, в чем минус этого подхода? Такое вот "полутабличное" преобразование...

Виктор, я тут просто недавно запускал AD9832, у нее на максимальной тактовой частоте получается дискретность установки частоты около 0.1 Гц. И мне было нужно получить выходную частоту без дополнительных погрешностей для синхронизации с сигналом, полученным другим способом (но от того же кварца). При расчете слова на калькуляторе и использовании его в DDS я получал то, что нужно. А при расчете внутри микроконтроллера получал на выходе DDS меньшую частоту. Оказалось, что вместо значения (для примера) 215.5 (которое округлялось до 216) микроконтроллер получал 215. 49999999 (которое округлялось уже до 215).

А что касается "полутабличного" преобразования, я бы рассчитывал веса с запасом, например, в дополнительные 8 разрядов, а перед программированием DDS эти 8 бит отбросил бы. Иными словами, использовал бы 8 двоичных разрядов после запятой - и при вычислениях эта арифметика с фиксированной точкой ничем бы не отличалась от целочисленной.

ur8us
29.03.2010, 05:46
Держал таблицу весов FCW для каждого десятичного разряда.
Виктор, тут можно и для каждого двоичного разряда таблицу весов сделать :D Если более серьезно, то деление возникает только один раз, и при постоянной опорной частоте останется только умножение. Здесь же заложена коррекция частоты опоры, поэтому хотя бы раз при старте деление остается (но скорость его может быть любой). В общем, сдвиг на 25 бит сделал, дабы Си не давал предупреждений об отсутствии возвращаемого значения перенесу этот кусок в чисто ассемблерный модуль. Взялся за неторопливое, но компактное деление :D

Вадим, а если не секрет - зачем здесь нужно деление? Разве нельзя обойтись умножением?

vadim_d
29.03.2010, 09:54
зачем здесь нужно деление? Разве нельзя обойтись умножением?
Денис, выход DDS при 32-битном аккумуляторе, такте f0 и слове управления fcw будет
f=(fcw/(2^32))*f0
откуда
fcw=f*((2^32)/f0)
то есть если f0 подстраивается пользователем, то после ее коррекции надо хотя бы раз посчитать ((2^32)/f0) (домноженную на какую-нибудь степень двойки, чтобы не потерять точность), а потом останется только умножение на эту константу (с хорооошей длиной выходного слова) и сдвиг результата вправо для компенсации этой избыточной степени двойки. Впрочем, деление уже сделал, и даже преобразование в двоично-десятичный код для индикации.

ut1wpr
29.03.2010, 12:04
А при расчете внутри микроконтроллера получал на выходе DDS меньшую частоту. Оказалось, что вместо значения (для примера) 215.5 (которое округлялось до 216) микроконтроллер получал 215. 49999999 (которое округлялось уже до 215).

А что касается "полутабличного" преобразования, я бы рассчитывал веса с запасом, например, в дополнительные 8 разрядов, а перед программированием DDS эти 8 бит отбросил бы. Иными словами, использовал бы 8 двоичных разрядов после запятой - и при вычислениях эта арифметика с фиксированной точкой ничем бы не отличалась от целочисленной.
Я так и делал. Это же не принципиально. Для FTW=32 (4 байта) в таблице держал 5-байтные веса. После суммирования использовал 4 старших байта.
А насчёт "подстройки F0 под пользователя [vadim_d]"... Тут уж я и растерялся.
Если я делаю устройство с фиксированными компонентами - то и firmware для него - уникальный. Всё остальное (гибкость, подстраиваемость) - это уже "универсальность". А за всё нужно платить. Повторяю, кто как для себя задачу ставит. Можно предусмотреть смену чуть-ли не всего, и типов дисплеев, и типов DDS (какие проблемы?) - но что мы при этом породим в софте? Монстра?
:)

vadim_d
29.03.2010, 13:11
Всё остальное (гибкость, подстраиваемость) - это уже "универсальность". А за всё нужно платить.
Виктор, ввод реальной частоты опоры с точностью 10Гц - стандартная "фича" синтезатора RD3AY, и она там явно востребована, поскольку большинство народа берет такт на DDS с кварца Атмеги. А вот в антенном анализаторе UT2FW степень двойки, поделенная на номинальное значение опоры, живет константой в ПЗУ, и при шаге в 1кГц это никому не мешает.

ur8us
29.03.2010, 14:44
зачем здесь нужно деление? Разве нельзя обойтись умножением?
Денис, выход DDS при 32-битном аккумуляторе, такте f0 и слове управления fcw будет
f=(fcw/(2^32))*f0
откуда
fcw=f*((2^32)/f0)
то есть если f0 подстраивается пользователем, то после ее коррекции надо хотя бы раз посчитать ((2^32)/f0) (домноженную на какую-нибудь степень двойки, чтобы не потерять точность), а потом останется только умножение на эту константу (с хорооошей длиной выходного слова) и сдвиг результата вправо для компенсации этой избыточной степени двойки. Впрочем, деление уже сделал, и даже преобразование в двоично-десятичный код для индикации.

Ага, понял. Не додумался, что пользователь может вводить частоту задающего генератора в единицах частоты. :-)

ut1wpr
29.03.2010, 18:27
Всё остальное (гибкость, подстраиваемость) - это уже "универсальность". А за всё нужно платить.
Виктор, ввод реальной частоты опоры с точностью 10Гц - стандартная "фича" синтезатора RD3AY, и она там явно востребована, поскольку большинство народа берет такт на DDS с кварца Атмеги. А вот в антенном анализаторе UT2FW степень двойки, поделенная на номинальное значение опоры, живет константой в ПЗУ, и при шаге в 1кГц это никому не мешает.
Ой как долго можно спорить. Причина в отношении к метрологии. :)
Если я ввожу 10Гц шаг, мне почему-то хочется, чтобы я таки верил тому, что отображается на шкале. Обычно DDS-ки клокируют частотой повыше, ясно почему. Использовать этот клокт для тактировки МК - сомнительная возможность. 200МГц генератор дополнительно делить?
Да и требования по ppm к тактовой МК и опорнику DDS очень уж разные. С моей точки зрения (повторяю, лишь с моей) тактироваться от общего источника двумя схемами с разными требованиями по ppm - моветон :)
Повторяю, это бесконечная тема, для каждого конкретного применения свои подходы. Незыблима лишь одна истина - за универсальность надо расплачиваться.
Я прекращаю дебаты, их по сути и нет. Каждый прав. :)

bob1
29.05.2010, 21:00
IAR AVR v5.3. Хочу задать переменной адрес явно к примеру: uint8_t temp @ 0x3000;
Выдает ошибку Error[Be022]: location address not allowed for initialized variables (writable variables without the __no_init attribute) .
В инете нашел подсказку "Линкер этим занимается - создаете сегментик с переменной и линкуете его куда хотите." Практически как сделать?? Заранее спасибо!

vadim_d
30.05.2010, 14:12
IAR AVR v5.3. Хочу задать переменной адрес явно к примеру: uint8_t temp @ 0x3000;
Выдает ошибку Error[Be022]: location address not allowed for initialized variables (writable variables without the __no_init attribute) .
В инете нашел подсказку "Линкер этим занимается - создаете сегментик с переменной и линкуете его куда хотите." Практически как сделать?? Заранее спасибо!
В сообщении об ошибке есть и другая подсказка - явно указать отсуствие инициализации, что-нибудь вроде

uint8_t attribute __no_init temp @ 0x3000;

или может быть

uint8_t __no_init temp @ 0x3000;

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

bob1
30.05.2010, 15:03
vadim_d
Вот так все ок!
__no_init uint8_t temp @ 0x3000;
Успехов!!

bob1
08.09.2010, 18:11
IAR AVR числа Float как кодируются? Не кто не разбирался??? хочу число float по байт но передать в комп и там его обратно собрать.

vadim_d
08.09.2010, 21:51
IAR AVR числа Float как кодируются? Не кто не разбирался??? хочу число float по байт но передать в комп и там его обратно собрать.
Я бы передал его в текстовом виде, если канал позволяет, так и отладить легче, ибо все видно. Но если хочется понять, "как они в конфеты повидло запихивают", то посмотрите побайтно на нуль и степени двойки с разным знаком (0, 1, -1, 1/2, -1/2, 1/4, -1/4 ...). Обычно мантиссу и экспоненту (со смещением) сразу видно.

bob1
11.09.2010, 18:53
Я бы передал его в текстовом виде, если канал позволяет, так и отладить легче, ибо все видно.
Не такой вариант не устраивает. Надо число обратно вернуть и памяти жалко.

"как они в конфеты повидло запихивают",
Число float ABCD. 4 в степени ((А&0x7F)-0x40)*(2+1+1/2+1/4+1/8......) числа 1,1/2,1/4,1/8...нужно складывать если есть 1 в BCD. 1-это 7 бит числа B. 1/2-это 6 бит числа B. и т.д. 7 бит числа А-это минус.
Успехов!!!

bob1
12.09.2010, 13:34
Число float ABCD. 4 в степени ((А&0x7F)-0x40)*(2+1+1/2+1/4+1/8......) числа 1,1/2,1/4,1/8...нужно складывать если есть 1 в BCD. 1-это 7 бит числа B. 1/2-это 6 бит числа B. и т.д. 7 бит числа А-это минус.
Ошибся похоже!!! Правильно так 4 в степени ((А&0x7F)-0x40)*(2 или1)*(2+1+1/2+1/4+1/8......) числа 1,1/2,1/4,1/8...нужно складывать если установлен бит в BCD. 1-это 6 бит числа B. 1/2-это 5 бит числа B. и т.д. 7 бит числа B -это множитель (2 или1). 7 бит числа А-это минус.

Vl@d
12.09.2010, 14:17
Хочу освоить С для AVRов. Посоветуйте какую нибудь полезную литературу актуальную для данного контекста.
Выучить английский и пользоватся оригинальной техдокументацией!!!
Ибо если будете учить например по "CodeVision AVR. Пособие для начинающих. Лебедев М.Б.", то шаг влево, шаг вправо, где не описано, не показан пример, что б как макака передирать, у вас возникнут большие сложности. Будете засорять всякие форумы а настроение испортится. А самое главное, хоть десять таких книжек прочтете, все равно дилетантом так и останетесь. Так что... я уже посоветовал.
П.С. Сам я англицкий оч плохо знаю, смотрю в того же лебедева, но над чем трудится знаю, ибо набил уже шишки)

vadim_d
12.09.2010, 23:47
Правильно так 4 в степени ((А&0x7F)-0x40)*(2 или1)*(2+1+1/2+1/4+1/8......) числа 1,1/2,1/4,1/8...нужно складывать если установлен бит в BCD. 1-это 6 бит числа B. 1/2-это 5 бит числа B. и т.д. 7 бит числа B -это множитель (2 или1). 7 бит числа А-это минус.
Минус в старшем бите A - так обычно у всех, а вот дальше что-то у Вас не то. Один разряд в мантиссе скрытый, то есть там всегда единица - посмотрите например http://en.wikipedia.org/wiki/IEEE_floating_point , поскольку мантисса больше или равна 1/2 и меньше единицы, половинка есть всегда, биты мантиссы начинаются с четвертинки. Экспонента - степень двойки, а никак не четверки, смещение обычно на "пол-шкалы" :smile:

bob1
13.09.2010, 17:55
Минус в старшем бите A - так обычно у всех
У Пиков -это 6 бит.

Один разряд в мантиссе скрытый,
Здесь это 2 . По идее можно всю скобку разделить на 2 или 4....

Экспонента - степень двойки, а никак не четверки
Формула главное заворачивает "конфеты как надо", а какой она имеет вид для меня не столь важно..
Успехов!!!