Radiohobby Forum

Интернет конференция журнала "Радиохобби"

Вы не вошли.

Объявление

Подписка на новые материалы от Николая Сухова - ролики, схемы, модели, онлайн конференции, консультации, чат.

Внимание! Почта в доменах Яндекс и Mail.ru не будет работать в профилях форумчан, из-за введённых правительством Украины санкций против этих компаний. Всем, кто ранее использовал подобную почту, для сохранения прежней функциональности форума, рекомендуется её поменять.

Огромная просьба, заливать тематические картинки и файлы в личные файловые каталоги на форуме, чтобы они не потерялись, со временем!

Ссылка "Загрузки" находится справа внизу формы набора сообщения.

Подписка на журнал "Радиохобби" прекращена. Подробности. Форум же - продолжает свою работу.

#1 27.07.2006 07:16:36

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

AVR для "чайников"

Все, кончаем оффтоп в известной ветке. Все вопросы по AVR сюда.


......There is someone in my head, but it's not me.......

Вне форума

#2 27.07.2006 10:09:38

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

2 Liv

Буд очень признателе за список граблей. Это сейчас важно, как никогда. У меня снова вопрос: линии порта В, занятые под MISO, MOSI, и проч. для работы использовать можно??  Или свободными оставить для прошивки??


......There is someone in my head, but it's not me.......

Вне форума

#3 27.07.2006 12:05:36

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Алексей пишет:

Буд очень признателе за список граблей. У меня снова вопрос: линии порта В, занятые под MISO, MOSI, и проч. для работы использовать можно??  Или свободными оставить для прошивки??

Это даже не грабли, а то, что нужно знать начинающему 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 ом.

Пока хватит smile

Вне форума

#4 27.07.2006 16:23:21

Jaxon
радиолюбовник
Откуда: Николаев
Здесь с 22.01.2004
Сообщений: 3,015

Re: AVR для "чайников"

спасибо, просветился!
пару слов о "дурном стиле", что можно делать, а чего низзя(хотя работать может в обеих случаях).

Вне форума

#5 27.07.2006 17:22:28

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

2 Liv
Большое спасибо за ценные (вернее бесценные smile ) советы!!
У меня процесс уже пошел. Первая программа написана, сегодня еду за байтбластером, а затра за 2313-м.
Как говорил Фоменко "Решительный шаг вперед это, как правило, результат хорошего пинка сзади" smile
Для начала заставлю МК бесшумно включать питание и переключать входы в моем усилке. Следующий пункт в списке - оптический валкодер.
А дальше видно будет. smile


......There is someone in my head, but it's not me.......

Вне форума

#6 27.07.2006 22:25:35

Vasil
Ветеран
Откуда: близ Киева
Здесь с 23.01.2004
Сообщений: 1,155

Re: AVR для "чайников"

По поводу п.15:
имеется некоторое устройство, в котором при выключении ( или случайном пропадании) питания текущие параметры должны сохраниться в еепром. Решается по-простому, компаратор МК "следит за питанием" сразу за вырямителем, а емкость конденсатора фильтра  по питанию МК имеет величину достаточную, чтобы выполнить операции записи до срабатывания браунаут детектора. Оно как то работает, но сложилось впечатление, что заремленные инструкции внутри прерывания не работают, в частности _CLI(), т.е. контроллер до срабатывания детектора попадает в прерывание несколько раз, или.., в чем ошибка?:
обработчик:
  #pragma vector=ANA_COMP_vect
__interrupt void On_ANA_wr_eeprom(void)

    //TIMSK=0x00;
    PORTD|=0x3c;
     PORTD|=ON;
     
   _EEPUT(3,t1);
   _EEPUT(4,t1>>8);
   _EEPUT(5,t2);
   _EEPUT(6,t2>>8);
  // ACSR=0x00;
    //_CLI();
}     
ЗЫ ,   t1, t2 -     unsigned int ;

Отредактировано Vasil (27.07.2006 22:33:45)

Вне форума

#7 28.07.2006 00:08:05

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Jaxon пишет:

пару слов о "дурном стиле", что можно делать, а чего низзя

Это очень обширная и неоднозначная тема. Подробно ответить я не готов, хотя что-то сказать могу.

1. Исходный текст лучше делить на модули, а не сваливать всё в один файл. Намного упрощается повторное использование кода, да и продуманные связи между модулями делают алгоритм понятнее. Например, программа управления усилителем. Я бы разбил текст римерно так:
main.asm - основная программа. Здесь размещаем инициализацию и основной цикл, где вызываем функции из других модулей.

header.asm - здесь размещаем описание портов, глобальных регистровых переменных, основных констант.

keyboard.asm - модуль обслуживания клавиатуры. Содержит как минимум две функции - инициализацию подсистемы клавиатуры и что-то типа Get_Scan_Code, которую нужно вызывать из основного цикла в main.

display.asm - модуль обслуживания дисплея. Опять содержит как минимум инициализацию и собственно индикацию.

menu.asm - модуль, содержащий логику меню, строковые константы и т.д.

hw.asm - модуль, содержащий функции работы с железом, которые могут вызываться из других модулей.

Структура каждого модуля чем-то напоминает структуру класса в духе ООП: функция инициализации - это как бы конструктор класса, есть набор методов, модули могут содержать какие-то поля данных. К сожалению, ассемблер не содержит поддержки областей видимости функций и переменных, всё это приходится отслеживать вручную. Очень может помочь система префиксов к именам. Но ООП-эшный стиль мышления очень помогает составлять простые для понимания программы даже на ассемблере. Пусть не наследование, так хоть подобие инкапсуляции smile Нужно отметить, что красота исходного текста ведет к увеличению объема кода и уменьшению скорости его выполнения. Что-то вроде плавного перехода на язык высокого уровня smile

2. Нельзя экономить на именах переменных и функций. Они должны нести смысловую нагрузку.

Плохо:

DScPh: .byte 1

Лучше:

Display_Scan_Phase: .byte 1

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

Так писать нельзя:

ldi temp,220
sts Soft_Timer,temp

А так - уже лучше:

.equ    ON_DELAY = 220 ;задержка включения усилителя

ldi temp,ON_DELAY
sts Soft_Timer,temp

4. Не стесняйтесь загружать препроцессор транслятора вычислениями. К примеру, в программе используются какие-то временные задержки. Представьте, Вы захотели перейти на другую частоту кварца. Если не хотите при этом править в тексте десятки констант, вычисляйте все константы на этапе трансляции, используя константу тактовой частоты. Пример:

.equ    FCLK    = 11059200        ;тактовая частота, Гц
.equ    BAUD    = 115200        ;скорость передачи UART

.equ UBRRV = (((Fclk*10)/(16*Baud))-5)/10 ;рассчитываем (с округлением) константу для делителя UART

При таком расчете констант может случится, что результат "не влезает" в разрядную сетку результата. Хорошим тоном является сделать проверку:

.equ    MAXWORD    = 0xFFFF

.if  UBRRV > MAXWORD
.error "out of range constant"
.endif

Если полученное значение окажется больше 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"
    cbi    PORTB,Load_Relay
.endm

.macro    Port_Load_Relay_1 ;устанавливает линию Load_Relay в "1"
    sbi    PORTB,Load_Relay
.endm

Везде в программе обращение к этой линии порта делаем так:

Port_Load_Relay_0 ;включение реле
ldi temp,ON_DELAY
rcall Delay_ms       ;задержка ON_DELAY
Port_Load_Relay_1 ;выключение реле

Любые перестановки портов тогда можно сделать корректировкой определений и макросов в одном местем (в header.asm).

Для входных линий порта макрос может быть таким:

.macro    Skip_if_Protection_0 ;пропустить команду, если Protection = 0
    sbic    PIND,Protection
.endm

6. Если нужны разные варианты одной и той же программы, не делайте копий исходников (запутаетесь при изменениях!), а применяйте условную трансляцию. Например, в плату могут быть установлены индикаторы с общим анодом или общим катодом. Пишем так:

#define COMMON_ANODE

#ifdef    COMMON_ANODE
    Port_CT1_1            ;выключение линий сканирования
    Port_CT2_1
    Port_CT3_1
#else
    Port_CT1_0
    Port_CT2_0
    Port_CT3_0
#endif

7. Все-таки добавлю. При настройке встроенной периферии не следует писать так:

    ldi    temp,0xd8
    out    UCSRB,temp
    ldi    temp,0x86
    out    UCSRC,temp

Мало того, что для этого нужно на бумажке собирать биты в байты, так и при переносе программы могут возникнуть трудности, если какой-то бит в другом контроллере изменит своё расположение.

А вот это - другое дело:

    ldi    temp,(1<<RXCIE) | (1<<TXCIE) | (1<<RXEN) | (1<<TXEN)
    out    UCSRB,temp
    ldi    temp,(1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
    out    UCSRC,temp

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

Ну и так далее в том же духе smile

Отредактировано Liv (28.07.2006 00:46:00)

Вне форума

#8 28.07.2006 00:17:41

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Алексей пишет:

сегодня еду за байтбластером

Я пользуюсь программатором AVR ISP (по application note 910). Вызывается прямо из AVR Studio, его очень легко собрать, подключается к COM-порту, умещается в корпусе разъема, может работать через переходник USB - COM. Я для него обновил прошивку:
www.spetspribor.com/products/tools/dn_t … risp31.zip
В этом программаторе используется 2313 (на тактовой 11.0592 МГц, скорость обмена 115 Кбод). Так что для его изготовления понадобится другой программатор (чем не курица и яйцо smile Но это вопрос решаемый.

Алексей пишет:

а затра за 2313-м.

Решили начинать на нем? Лучше возмите ATmega8.

Алексей пишет:

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

Это хорошо, что реальный проект есть. А то учиться чисто теоретически не интересно. Проект совместными усилиями одолеем smile

Вне форума

#9 28.07.2006 00:31:15

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Vasil пишет:

но сложилось впечатление, что заремленные инструкции внутри прерывания не работают, в частности _CLI(), т.е. контроллер до срабатывания детектора попадает в прерывание несколько раз, или.., в чем ошибка?:

Очень не хочется здесь начинать разговор про Си, это отдельная большая тема. Ну да ладно... Ставить в конце обработчика прерывания _CLI() совершенно бессмысленно, так как после нее будет выполнена команда reti, которая тут же прерывания разрешит. Если не хотите повторной записи в EEPROM, заведите флаг Save_Done, который будете сбрасывать при старте программы, а устанавливать в обработчике прерывания после записи в EEPROM.

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

И еще про начальную инициализацию EEPROM. Значения по умолчанию храню в виде констант в памяти программ. Один или два байта EEPROM отвожу под сигнатуру. Программа первым делом проверяет сигнатуру EEPROM. Если она неправильная, производится полная инициализация EEPROM. В частности, это происходит при первом включении устройства.

Вне форума

#10 28.07.2006 07:03:14

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

Liv пишет:

Я пользуюсь программатором AVR ISP (по application note 910). Вызывается прямо из AVR Studio, его очень легко собрать, подключается к COM-порту, умещается в корпусе разъема, может работать через переходник USB - COM. Я для него обновил прошивку:
www.spetspribor.com/products/tools/dn_t … risp31.zip
В этом программаторе используется 2313 (на тактовой 11.0592 МГц, скорость обмена 115 Кбод). Так что для его изготовления понадобится другой программатор (чем не курица и яйцо smile Но это вопрос решаемый.

Ну как Вам сказать... Бластер мне подарили бесплатно, а это придется делать за денежку да еще и программатор искать. Так что лучше я пойду своим путем в этом вопросе.

Liv пишет:

Решили начинать на нем? Лучше возмите ATmega8.

Ок. Сегодня на работе гляну даташЫт.

Liv пишет:

Это хорошо, что реальный проект есть. А то учиться чисто теоретически не интересно. Проект совместными усилиями одолеем smile

Если б у меня не было реальных задач, я б за это дело не взялся. В пока учился в универе, у меня была уйма времени, и можно было все это изучить. Но не было реальных применений, поэтому особо не хотелось. А сейчах хочется. Хочется безупорную ручку громкости, хочется пульт ДУ, хочется красивый экран с русскими буковками (чтоб когда ручку крутишь, он писал что-то типа "громкость 50%"), в общем много чего хочется.


......There is someone in my head, but it's not me.......

Вне форума

Сейчас в этой теме пользователей: 0, гостей: 1
[Bot] ClaudeBot

Подвал форума

Под управлением FluxBB
Модифицировал Visman

[ Сгенерировано за 0.053 сек, 7 запросов выполнено - Использовано памяти: 673.25 Кбайт (Пик: 723.62 Кбайт) ]