Перейти к содержанию
    

Сергей Борщ

Модератор
  • Постов

    10 921
  • Зарегистрирован

  • Посещение

  • Победитель дней

    31

Весь контент Сергей Борщ


  1. Проверил. При оптимизации по размеру разница есть - 32/44 байта: вы твоем str+Buf_Adres вычисляется дважды внутри цикла, хотя +3 встроено в команду LDD: LDD Z+3. При оптимизации по скорости разница больше - 32 / 46 байт, хотя суммирование вынесено за цикл. И все равно остается сравнение с 64 в конце цикла. А если str передавать как параметр, да еще перед функцией __x поставить - мой вариант получается еще лучше - 26 байт, а твой так и остается в районе 40. (я делал только цикл). Выигрыш получился имеено за счет указателя и того, что в результате вычисления Buf_Address-=2 сам собой получается флаг Z который тут же можно использовать для проверки окончания. Тогда для улучшения наглядности рекомендую такой вариант: str += 3; do { data = str[Buf_Adres+1]; data <<= 8; data |= str[Buf_Adres]; или str += 3; do { data = str[Buf_Adres++]; data |= (uint16_t)str[Buf_Adres++] << 8; а еще лучше str += 3; do { data = *str++; data |= (uint16_t)*str++ << 8; Новичков надо сразу приучать писать оптимально. Раз str больше не нужен, нет смысла его хранить неизменным. Пусть указывает на текущий байт. Тогда одной командой LD Rn, X+ сразу делаем и загрузку и передвигаем указатель. Кстати, в последнем варианте цикл получился 30 байт независимо от оптимизации. На эту тему много копий поломали с dxp в личной переписке (каждый остался при своем). Я не нашел в имеюмщемся у меня стандарте (ISO/IEC 9899) описания размеров данных. На всех известных мне компиляторах unsigned short действительно 2 байта. Но мне больше нравится подход с использованием заголовочного файла stdint.h. Объявленые в нем типы uint8_t, uint16_t, int8_t и т.д. имеют один и тот же размер всегда и везде. Упустил из виду. Можете кратко сказать с чем его едят? подкоректирую - будет скоро готов. "Говорю одно, делаю третье, думаю второе". Имел в виду intrinsics.h. Можно указать, что функции работы с флешкой описаны в файле intrinsics.h, тогда код будет самодостаточен - не нужны левые flash.h. Пришли (в почту) файл flash.h, я посмотрю как его макросы заменить на функции из intrinsics.h.
  2. Молодец! Первая ласточка в FAQ. "необходимо отредактировать файл lnkm8s.xcl" - лучше все же скопировать его в папку проекта и редактировать копию - а то потом остальные проекты (которые использовали lnkm8s.xcl) перестанут работать. Еще можно добавить в какой папке искать этот файл (\avr\config). -H1895 -h(CODE)1C00-1C25 /*Fill unused interrupt vector's with RETI */ Не нужно. Правильно написанная программа не должна влетать в ненужные вектора, а эту память можно использовать под код (загрузчик обычно стремится занять всю отведенную память и еще чуть-чуть:-) "Тогда файл будет браться из Workspace проекта" - из папки проекта (гдe лежит .ewp). В Workspace обычно куча проектов из разных папок. #include "inavr.h" #include "iom8.h" #include "stdio.h" #include "flash.h" 1) первые три файла надо указать в угловых скобках. 2) вместо #include "iom8.h" #include <ioavr.h> - тогда нужный ioxxx.h будет подставлятся автоматически исходя из настроек проекта и исчезнет warning35 при линковке многофайловых пректов. 3) flash.h - файл явно не из комплекта компилятора, поэтому надо упомянуть где его брать. цикл я бы сделал иначе: #include <intrinsics.h> #define PAGE_SIZE 64 void update_Page(uint8_t *str) { uint8_t Buf_Address = PAGE_SIZE; uint8_t *ptr = str + 3 + PAGE_SIZE; do { uint16_t data = (uint16_t)*--ptr << 8; data |= *--ptr; _SPM_FILLTEMP(Buf_Address, data); } while (Buf_Address-=2); } И по ошибкам: "критЕку", "возможностями среда IAR", "что адре байта" Buf_Adres -> Buf_Address, NumbePageWrite -> NumberPageWrite P.S. с pgmspace.h так и не разобрались? У меня получилось такое: (для AVR231): #include <intrinsics.h> static void spmWriteWord(unsigned char APPFLASH *addr, unsigned int data) {_SPM_FILLTEMP(addr, data);} static int spmReadWord(unsigned char APPFLASH *addr) { return *addr; } static void spmErasePage(unsigned char APPFLASH *addr) { _SPM_ERASE(addr); while(SPMCR & (1<<0)); } static void spmProgramPage(unsigned char APPFLASH *addr) { _SPM_PAGEWRITE(addr); while(SPMCR & (1<<0)); } static void spmEEWriteByte(unsigned int addr, unsigned char data) { __EEPUT(addr, data); } static void spmWriteLockBits(unsigned char data) { _SPM_LOCKBITS(data); while(SPMCR & (1<<0)); }
  3. IAR и sprintf

    Лето... отпуск только через 2 недели. Совсем я плохой стал. char STR1[16]; char STR2[16]; sprintf(STR2, "%i", NUM); sprintf(STR1, "%i", NUM2); Не вижу тут ошибки... :-(
  4. Различные "чудесатые чудеса" наблюдал при отсутствии цепочки на ноге PLLRC.
  5. Аналогично. Кроме того заметил, что на странице форума в приветствии (там где "Добро пожаловать (ник), ваше последнее посещение чч:мм") не выводится ник. Также ника нет на личной панели управления (кажется раньше был) а в выпадающем меню слева в персональном меню стоит "Добро пожаловать" и в след. строке логин (а должен вроде как быть ник).
  6. Если схема вроде _Sam_ или моей, т.е с побитным отключением передатчика, то симптомы очень похожи на отсутствие растяжек. Если обычная - скорее всего перепутаны входы данных и включения передатчика.
  7. IAR и sprintf

    В данном случае все правильно. STR1 и STR2 - массивы из 16 элементов типа char. Поскольку массивов как таковых в С нет, то имя массива тождественно указателю на его первый элемент. Т.е. STR1, STR2 имеют тип char *. Поэтому запись char *ptr = STR1; вполне корректна. Она тождественна записи char *ptr = &STR1[0]; И с другой стороны в С массивы в функции передаются как указатель на первый элемент. Так что с какой стороны ни подойди - в этом месте ошибки нет. А если поменять их местами? Т.е. проблема в чем - вообще любой второй вызов функции глючит или именно преобразование отрицательного числа? Пока могу предположить налезание стеков друг на друга. sprintf требовал стека более 100 байт. Сколько точно - не помню :-( А! можно в .map посмотреть.
  8. Замечание: Очень полезно при передаче 1 тоже включать передатчик, но на очень короткий промежуток времени (~50% бита на макс. скорости) для быстрой перезарядки емкости линии. Прилагаемая схема делает это и плюс давит эхо. Работает до 115200 без всяких настроек скорости и процессоров. Растяжки, конечно, обязательны.
  9. СОМ порт в компьютере асинхронный по условию. В самом простом (и наиболее часто используемом варианте) подключение такое: 10 или 11 ногу MAX на TXD меги, соответственно 14 или 7 МАХ на RXD компа (2 ножка). 12 или 9 МАХ на RXD меги, 13 или 8 МАХ на TXD компа (3 ножка). GND компа (5 ножка) на землю платы. Прилагаю код под мегу-8, переставил в проекте кристалл на 32, компилятор не ругается. Прием/передача по прерываниям, буфера приема/передачи, в main() делает эхо. UART.zip
  10. О! Может тут кто-нибудь скажет: 1) как заставить WinAVR не подлинковывать функции к которым никто не обращается? Бить исходный файл на десять (по файлу на функцию) и делать из них библиотеку не хочу - дурная работа и инкапсуляция страдает. 2) объявляю две функции (putstring, putstring_P) у одной аргумет - указатель на флеш, у второй - указатель на RAM. Еще не зная о тонкостях досупа к флеш в обоих написал putchar(*ptr++); и получил две функции с идентичным кодом (т.е. с LD вместо LPM во второй) _без_всяких_варнингов_. Это штатное поведение? Как же тогда отслеживать ошибки типа "забыл вытащить переменную через макрос"?
  11. Так и спрашивать надо было не в этом подфоруме. WinAVR - совершенно другой компилятор. Читайте в папке \doc в описании avrlibc как оформляются прерывания в WinAVR. Раздел (если память не изменяет) interrupt.h
  12. О какой эвалюшн-версии идет речь? В 30-дневной с сайта ИАР все библиотеки прилагаются.
  13. Конечно проще. Хотя еще проще - купить новый паяльник. А поскольку автор ветки Творит просто для удовольствия, то знание о других возможных решениях будут только полезны. А если сделатьтак к гейту П канала подключить Гейт Н канала ? Теоретически можно. Но в моменты переключения когда один еще не закрылся а второй уже начал открываться будет течь сквозной ток, который будет греть транзисторы и уменьшать КПД. Попробовать можно. Зависит от скорости открывания/закрывания и пороговых напряжений полевиков.
  14. SAM7 + IAR

    Ну так опубликуйте код этой функции. А еще лучше вместе с ассемблерным листингом этого цикла. Вот здесь возможна проблема. Т.е. warning может и изчезнет, но вместе с ним и чтение TC_SR. предлагаю volatile u32 dummy; dummy = AT91C_BASE_TC0 -> TC_SR;//Acknowledge interrupt status
  15. Конечно проще. Хотя еще проще - купить новый паяльник. А поскольку автор ветки Творит просто для удовольствия, то знание о других возможных решениях будут только полезны.
  16. SAM7 + IAR

    Значит надо смотреть что делают эти дивные функции. Поскольку они не являются частью компилятора то о содержании их можно только гадать. А за ожидание внутри обработчика прерывания нужно бить больно. Первое, что приходит в голову - эти функции используют прерывания которые не могут выполнится потому что ты уже в прерывании.
  17. Не прав. Дроссель является индуктивностью, а ток в индуктивности не может измениться мгновенно (напряжение может, на этом зажигание в автомобиле работает). Вот при закрытии транзистора ток и продолжает течь, но уже через диод. А чтобы он не грелся и КПД был совсем хороший, имеет смысл поставить вместо него n-канальный полевик, который открывать в противофазе с Q1. Еще неплохо бы уменьшить R3 до ~680 ом - быстрее будет закрываться Q2 и, следовательно, Q1. несовсем понятно куда нуно поставить Q1 если заменить егь на N канал Q1 заменять не нужно. Полевик можно поставить вместо D2. Важно чтобы этот дополнительный транзистор и Q1 не были открыты одновременно.
  18. извиняюсь за повтор, сглюконуло что-то.
  19. Не прав. Дроссель является индуктивностью, а ток в индуктивности не может измениться мгновенно (напряжение может, на этом зажигание в автомобиле работает). Вот при закрытии транзистора ток и продолжает течь, но уже через диод. А чтобы он не грелся и КПД был совсем хороший, имеет смысл поставить вместо него n-канальный полевик, который открывать в противофазе с Q1. Еще неплохо бы уменьшить R3 до ~680 ом - быстрее будет закрываться Q2 и, следовательно, Q1.
  20. Посмотри тут, похоже твой случай: http://electronix.ru/forum/index.php?s=&am...st&p=120688 Есть лекарство для 3.20А для 30-дневного варианта, могу мылом выслать. Вот тут впечатления о нем по семинару: http://electronix.ru/forum/index.php?s=&am...st&p=117135 В общем ответ такой - если можешь пользовать ИАР, то брось каку (композер). Если нет особой привязанности к GCC, то ИАР однозначно.
  21. Поразительное упорство. :) Я знаю :) :-) Но все равно "не выйдет из тебя путёвого старика" :-) Тем, что с этой самой переферией приходится работать самому. Т.е. ее в программе рассматриваешь как набор этих самых регистров. Т.е. в программе таймер ты видишь не как таймер, а как регистры. А ЕЕPROM компилятор представляет как ПАМЯТЬ в которую можно писать и из которой можно читать. Да, но об особенностях работы с этой памятью ты должен позаботиться сам. Тебя не удивляет ведь, что компилятор не запрещает прерывания при доступе к многобайтовым volatile - переменным? А ведь прерывание может изменить эту переменную посередине чтения в основном цикле. Хочешь атомарный доступ - ручками. Не хочешь - тебе виднее. Когда компиляторы научатся бегать за пивом я уволюсь - ибо тогда программы они смогут писать без меня и подавно. Попробуй вызвать таким манером библиотечную функцию strtok(). Получишь именно только что тобой описанное. Тебя это удивляет? Меня нет. Я знаю, что эта функция нереентерабельная (как и многие другие _библиотечные_ функции). Резюмирую: компилятор в твоих граблях не виноват. Он еще много чего не умеет делать сам ибо это в принципе не возможно. Потому-то к нему программист в комплекте должен быть.
  22. Как правило третий вывод - это встроенный терморезистор. Про зарядку довольно подробно описано в аппнотах атмела ( http://www.atmel.com/dyn/resources/prod_do...nts/doc1659.pdf ) и тексаса ( http://focus.ti.com/mcu/docs/mcusupporttec...actName=slaa287 ) а также в даташитах на микросхемы зарядников (Ti, Analog Devices, Maxim, Linear и т.д.) Скорее всего в аккумуляторе есть и схема защита от перезаряда/переразряда, но лучше в этом убедиться.
  23. Там суть в глобальных ресурсах - сохраняет-же он при входе в прерывание SREG, так чем EEAR и EEDR хуже? Поразительное упорство. А регисты таймера, портов, UARTa, АЦП и прочей периферии компилятор не должен сохранять при входе в прерывание? Нет? А чем они лучше чем EEAR, EEDR? Тем более IAR-овцы должны были на эту выдержку обратить внимание :( . Да не надо валить с больной головы на здоровую. Вам пять человек пытаются объяснить, что компилятор тут не при чем. Это не ИАРовцы, а Вы должны были прочитать эту выдержку и обратить на нее внимание. Ибо только Вам известно где Вы работаете с EEPROM - в прерывании, в основном цикле или и там и там. В двух случаях из упомянутых трех никаких "срадств защиты" на которых Вы настаиваете не требуется. И только в третьем случае нужно предохраняться. Но компилятор не имеет _никакой_ возможности определить какой метод пользуете Вы в своей программе. А поскольку обычно (грамотно) используют первые два подхода, то нет никакого резона перестраховываться и генерить лишний код на случай если кому-то придет в голову поизвращаться.
  24. Поставить курсор в окно с исходным текстом на С++. Ставишь брейкпоинт (кажется не более 3 при отладке из флеш, при том что одну отладчик ставит на main если стоит галочка "Run to main" и сколько угодно при отладке из ОЗУ), жмешь Run.
  25. LPC2214 & IO0PIN

    У LPC213x/4x уже официально, как R/W. Похоже :-(, я по простоте душевной несколько раз пользовал его на "старых" LPC, как R/W без побочных эффектов. Судя по всему у них периферийные блоки практически одни и те же. Не удивлюсь, если их делали одни и те же люди. Так что может статься, что они просто не потрудились описать заложенный функционал. Хотя лично мне этот функционал IOPIN (на запись в регистр) пока ни разу не требовался. Похоже это недоработка в доке. В усер мануале на 2119/2129/2192/2292/2294 тоже написано что он read only, но дальше сказано так:Applications that require instanatneous appearance of zeros and ones on the respected parallel port can use direct access to port’s corresponding GPIO Pin Value Register (IOPIN). Assuming that pins P0.8 to P0.15 are configured as output, write to IO0PIN: IO0PIN = 0x0000 C700 will produce the same output as following sequence of writes: IO0SET = 0x0000 C700 IO0CLR = 0x0000 3800
×
×
  • Создать...