Не про радио | Всем, кого достал 1,2,3 ! Краткий курс. |
|
---|---|---|
Хотя, согласен, один хрен - что в тех демках с паскаля на си переучиваться, что в AVR-GCC. |
|
|
Фото с девушкой и сигаретой - это 5 баллов !!! |
|
|
Нет, ещё не собирал. |
|
|
BASIC-контроллер - аналог МК-85 что ли? |
|
|
caddr: - Ужас-то какой, пользоваться под Linux демкой кривого виндового компилятора, когда есть родной avr-gcc : - ) |
|
|
Num Lock: то где он советы давать будет по своему курсу, если будет чё непонятно. он на робофоруме сидит и на хоботе целая тема его Num Lock: А я хотел демо-версии ПО из его курса проверить на совместимость с wine, и в случае успеха нАчать программирование МК изучать. тебе же уже давно сказали, что все есть под линупс |
|
|
Дык никто не спорит, что AVR-GCC круче, но у него недостаток один есть: по нему товарищ 123 консультировать не умеет. |
|
|
Может быть мы вскорости устроим "Ликбез по AVR" здесь? Как уже был "Ликбез по PIC". Примерно по такому же принципу - техзадание, его обсуждение, граф и алгоритм, программа, её отладка, реализация в железе. С подробным обсуждением каждого шага. Есть желающие? ИМХО - 12З мог бы оказать немалую помощь начинающим АВР-щикам, не будь он столь фанатичным маньяком своего курса, и не суй почти в каждое своё сообщение ссылки на него. Попытки договориться с ним по-хорошему оказались в своё время бесполезны... |
|
|
picmaniac, так было уже такое. Лично я тему и замутил. "Наш ответ Чемберлену" называлась, если помните. В нее этот ... товарищ ... и влез. Больше рисковать не хочется |
|
|
что нужно знать начинающему AVR-щику: ( найдено на просторах интернета) 1. В командах sbr и cbr нужно применять не номер бита, а маску, нужно писать (1<Bit) или exp2(Bit). 2. Для обращения к таблицам в памяти программ командой lpm указатель Z нужно загружать значением (метка * 2). Память программ организована как слова, а lpm работает с байтами. Нужно писать так: ldi ZL,low(Label*2) ldi ZH,high(Label*2). 3. Для сброса флага прерывания в него нужно записать "1". 4. Нет приоритетов прерываний. Прерывания автоматически запрещаются в начале обработки. Если требуются вложенные прерывания, в обработчик нужно добавить команду sei. Команда reti делает то же самое, что и ret, плюс разрешает прерывания. 5. Питание портов, на которых располложены входы АЦП, производится от AVCC/AGND. Если это питание не подать, порты работать не будут. 6. В EEPROM лучше не использовать ячейку с адресом 0, регистр адреса EEPROM лучше обнулять после операций с EEPROM. Для младших AVR, которые не имеют встроенного BOD, при использовании EEPROM обязательно нужен внешний супервизор. В современных AVR есть BOD, он должен быть включен фузом. Для таких AVR внешний супервизор лучше не использовать, может быть даже хуже - помехи на линии RESET могут вызвать даже порчу содержимого памяти программ. Вход RESET желательно подтянуть к питанию резистором порядка 4.7К и подключить конденсатор порядка 10 нФ на землю (программированию он обычно не мешает). 7. Команды с непосредственным операндом sbr, cbr, ldi, ori, andi, subi, sbci возможны только с регистрами R16 - R31. 8. Побитовая работа с портами sbi, cbi возможна только в диапазоне адресов 00 - 1F. 9. ADIW, SUBIW работают только с R24, 26, 28, 30. 10. movw работает с парами четный:нечетный регистр R0:R1 и т.д. 11. inc не устанавливает флаг C. 12. Команды с автоинкрементом/декрементом не изменяют старший байт указателя в устройствах с ОЗУ менее 256 байт. Его можно использовать для других целей. Команды ADIW, SUBIW - изменяют. 13. При определении таблиц в памяти программ за каждой директивой DB должно быть четное количество байт, иначе автоматически добавляется 0x00. 14. При переходе с AT90S1200 (без стека) на старшие AVR не забывать инициализировать стек. 15. Запись в EEPROM time-controlled, нужно запрещать прерывавания. 16. У некоторых AVR, например, mega8, нужно специальным битом разрешать не только выключение WDT, но и изменение его интервала. 17. Для 16-разрядных регистров периферии читать первым L, писать первым H. 18. Если есть JTAG, то его надо выключать фузом, иначе не работают соответствующие порты. Если есть фуз совместимости с Мегой103, его нужно не забывать убрать. 19. Чтение состояния внешнего сигнала, подключенного к порту, производится из PINx, а не из PORTx. 20. Mega64, 128 программируется через выводы RXD, TXD (а не MISO, MOSI). 21. Mega64, 128 OC2 и OC1C на одной ноге! 22. У новых мег UART имеет FIFO, в котором сохраняются данные и флаги ошибок (FE, DOR). Поэтому UDR нужно читать один раз на один принятый байт. Флаги ошибок нужно читать перед чтением UDR. 23. При использовании аппаратного SPI в режиме мастера вывод SS нельзя использовать в качестве входа. 24. У старших мег часть периферии находится не в адресном пространстве IO, а в адресном пространстве данных (например, порт F). В таких случаях доступ нужно осуществлять командами STS, LDS а не OUT, IN. 25. Внимательно изучите фузы, особенно типа тактового генератора и времени стартапа. Всегда желательно ставить Full Amplitude, иначе некачественные кварцы могут генерировать неустойчиво. Указать состояние фузов в исходном тексте программы нельзя, их нужно программировать отдельно (программаторы имеют такую возможность). 26. Некоторые программаторы (PonyProg, например) применяют инверсное обозначение состояния фузов. Будьте бдительны, распространенная ошибка - перевод AVR на внешнее тактирование. При этом он перестает отвечать программатору и выглядит совсем мёртвым. Выход из такой ситуации - подключение внешнего клока к XTAL1 на время программирования. 27. Не переключайте фузом вход RESET в режим обычного IO - контроллер невозможно будет дальше программировать последовательным программатором. 28. При чтении PINx нужно учитывать, что внешние сигналы синхронизируются в нутренней тактовой частотой, что приводит к задержке. Поэтому если мы что-то вывели на порт и хотим это же прочитать, нужно вставить команду NOP между OUT и IN. Хотя чтение собственного выходного сигнала требуется очень редко. 29. Линии, которые используются для внутрисхемного программирования (MISO, MOSI, SCK) можно использовать в проекте как порты ввода-вывода. Если используется вывод, то никаких дополнительных мер принимать не надо (только учтите, что в момент программирования будет "дергаться" подключенная периферия). Если используется ввод, то выход внешней схемы, подключенный к этому входу, надо развязать резистором порядка 470 ом. 1. Исходный текст лучше делить на модули, а не сваливать всё в один файл. Намного упрощается повторное использование кода, да и продуманные связи между модулями делают алгоритм понятнее. Например, программа управления усилителем. Я бы разбил текст римерно так: header.asm - здесь размещаем описание портов, глобальных регистровых переменных, основных констант. keyboard.asm - модуль обслуживания клавиатуры. Содержит как минимум две функции - инициализацию подсистемы клавиатуры и что-то типа Get_Scan_Code, которую нужно вызывать из основного цикла в main. display.asm - модуль обслуживания дисплея. Опять содержит как минимум инициализацию и собственно индикацию. menu.asm - модуль, содержащий логику меню, строковые константы и т.д. hw.asm - модуль, содержащий функции работы с железом, которые могут вызываться из других модулей. Структура каждого модуля чем-то напоминает структуру класса в духе ООП: функция инициализации - это как бы конструктор класса, есть набор методов, модули могут содержать какие-то поля данных. К сожалению, ассемблер не содержит поддержки областей видимости функций и переменных, всё это приходится отслеживать вручную. Очень может помочь система префиксов к именам. Но ООП-эшный стиль мышления очень помогает составлять простые для понимания программы даже на ассемблере. Пусть не наследование, так хоть подобие инкапсуляции Нужно отметить, что красота исходного текста ведет к увеличению объема кода и уменьшению скорости его выполнения. Что-то вроде плавного перехода на язык высокого уровня 2. Нельзя экономить на именах переменных и функций. Они должны нести смысловую нагрузку. Плохо: DScPh: .byte 1 Лучше: Display_Scan_Phase: .byte 1 3. Не следует в тексте применять константы в числовом виде. Все константы должны быть описаны в начале того файла, где они применяются. Так писать нельзя: ldi temp,220 А так - уже лучше: .equ ON_DELAY = 220 ;задержка включения усилителя ldi temp,ON_DELAY 4. Не стесняйтесь загружать препроцессор транслятора вычислениями. К примеру, в программе используются какие-то временные задержки. Представьте, Вы захотели перейти на другую частоту кварца. Если не хотите при этом править в тексте десятки констант, вычисляйте все константы на этапе трансляции, используя константу тактовой частоты. Пример: .equ FCLK = 11059200 ;тактовая частота, Гц .equ UBRRV = (((Fclk*10)/(16*Baud))-5)/10 ;рассчитываем (с округлением) константу для делителя UART При таком расчете констант может случится, что результат "не влезает" в разрядную сетку результата. Хорошим тоном является сделать проверку: .equ MAXWORD = 0xFFFF .if UBRRV > MAXWORD Если полученное значение окажется больше MAXWORD, транслятор дасть ошибку с текстом "out of range constant". Текст можно задать любой, например, "превед, красавчег!". 5. AVR не имеет прямой адресации бит (адресация есть только в пределах байта). Это уменьшает гибкость переопределения портов. Например, на макете сигнал Load_Relay был на порту PB0, а при разводке платы оказалось удобнее подключить его к порту PD2. Что делать? По всей программе искать и исправлять? Лучше для обращения к портам использовать макросы. В файле header.asm пишем: .equ Load_Relay = PB0 ;управление реле нагрузки .macro Port_Load_Relay_0 ;устанавливает линию Load_Relay в "0" .macro Port_Load_Relay_1 ;устанавливает линию Load_Relay в "1" Везде в программе обращение к этой линии порта делаем так: Port_Load_Relay_0 ;включение реле Любые перестановки портов тогда можно сделать корректировкой определений и макросов в одном местем (в header.asm). Для входных линий порта макрос может быть таким: .macro Skip_if_Protection_0 ;пропустить команду, если Protection = 0 6. Если нужны разные варианты одной и той же программы, не делайте копий исходников (запутаетесь при изменениях!), а применяйте условную трансляцию. Например, в плату могут быть установлены индикаторы с общим анодом или общим катодом. Пишем так: #define COMMON_ANODE #ifdef COMMON_ANODE 7. Все-таки добавлю. При настройке встроенной периферии не следует писать так: ldi temp,0xd8 Мало того, что для этого нужно на бумажке собирать биты в байты, так и при переносе программы могут возникнуть трудности, если какой-то бит в другом контроллере изменит своё расположение. А вот это - другое дело: ldi temp,(1RXCIE) | (1TXCIE) | (1RXEN) | (1TXEN) С именами всё гораздо приятнее, не надо даже лезть в даташит, чтобы понять текст. Ну и так далее в том же духе MACRO - Начало макроса С директивы MACRO начинается определение макроса. В качестве параметра директиве передаётся имя макроса. При встрече имени макроса позднее в тексте программы, компилятор заменяет это имя на тело макроса. Макрос может иметь до 10 параметров, к которым в его теле обращаются через @0-@9. При вызове параметры перечисляются через запятые. Определение макроса заканчивается директивой ENDMACRO. По умолчанию в листинг включается только вызов макроса, для разворачивания макроса необходимо использовать директиву LISTMAC. Макрос в листинге показывается знаком +. Пример: .CSEG ; Начало программного сегмента |
|
|
Форум про радио — сайт, посвященный обсуждению электроники, компьютеров и смежных тем. pro-radio.online | Обратная связь |
© 2003—2024 |