Реклама ⓘ
Главная » Микроконтроллеры
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Похожие статьи:


Реклама ⓘ

Структура программы

Рассмотрим синтаксические особенности ассемблера AVR на примере небольшой тестовой программы для микроконтроллера ATmega8, приведенной ниже. Программа формирует на выводе PB2 импульсы с частотой следования ≈ 2.5 Гц при частоте внутреннего RC-генератора 1 МГц.

1. ;  Тестовая программа для ATmega8.
2. // Светодиод подключен к выводу PB0 микроконтроллера.        
3. /* Биты конфигурации:  
        Low Fuse                     High Fuse     
      BODLEVEL = 1                  RSTDISBL = 1      
      BODEN    = 1                  WDTON    = 1
      SUT1     = 1                  SPIEN    = 1   
      SUT0     = 0                  CKOPT    = 1   
      CKSEL3   = 0 |                EESAVE   = 1   
      CKSEL2   = 0 |_ RC-генератор  BOOTSZ1  = 1         
      CKSEL1   = 0 |     1 МГц      BOOTSZ0  = 1      
      CKSEL0   = 1 |                BOOTRST  = 1   */ 
    
4.        .nolist  ;подключение стандартного заголовочного файла
5.        .include "m8def.inc"
6.        .list 
                     
7.        .equ PAUSE  = 50000 ;задержка времени
8.        .equ LED    = PB2   ;вывод для подключения светодиода
            
9.        .def temp   = R16  ;регистр для промежуточных операций
10.       .def buffer = R17  ;регистр для чтения порта

11.              .cseg
12.             .org 0
13.          rjmp  initial                                          ;0xC01F
14.          rjmp  0 ;rjmp  service_INT0 ;внешнее прерывание 0      0xCFFE
15.          rjmp  0 ;rjmp  service_INT1 ;внешнее прерывание 1     0xCFFD
16.          rjmp  0 ;rjmp  service_OC2  ;совпадение TCNT2 и OCR2   0xCFFC
17.          rjmp  0 ;rjmp  service_OVF2 ;переполнение TCNT2        0xCFFB
18.          rjmp  0 ;rjmp  service_ICP1 ;захват в ICP1           0xCFFA
19.          rjmp  0 ;rjmp  service_OC1A ;совпадение TCNT1 и OCR1A  0xCFF9
20.          rjmp  0 ;rjmp  service_OC1B ;совпадение TCNT1 и OCR1B  0xCFF8
21.          rjmp  0 ;rjmp  service_OVF1 ;переполнение TCNT1       0xCFF7
22.          rjmp  0 ;rjmp  service_OVF0 ;переполнение TCNT0         0xCFF6
23.          rjmp  0 ;rjmp  service_SPI  ;прерывание от модуля SPI  0xCFF5
24.          rjmp  0 ;rjmp  service_URXC ;получение байта по USART   0xCFF4
25.          rjmp  0 ;rjmp  service_UDRE ;опустошение UDR в USART    0xCFF3
26.          rjmp  0 ;rjmp  service_UTXC ;передача байта по USART    0xCFF2
27.          rjmp  0 ;rjmp  service_ADCC ;прерывание от АЦП          0xCFF1
28.          rjmp  0 ;rjmp  service_ERDY ;завершение записи в EEPROM 0xCFF0
29.          rjmp  0 ;rjmp  service_ACI  ;прерывание от компаратора  0xCFEF
30.          rjmp  0 ;rjmp  service_TWI  ;прерывание от модуля TWI   0xCFEE
31.          rjmp  0 ;rjmp  service_SPMR ;завершение выполнения spm  0xCFED

32.             .org 0x20
33. initial: ldi   temp,low(RAMEND)                                   ;0xE50F        
34.          out   SPL,temp                                           ;0xBF0D
35.          ldi   temp,high(RAMEND)                                  ;0xE004
36.          out   SPH,temp                                           ;0xBF0E
37.          cbi   PORTB,LED                                          ;0x98C2
38.          sbi   DDRB,LED                                           ;0x9ABA
39.          ldi   temp,1«LED                                         ;0xE004

40. main:    in    buffer,PORTB                                       ;0xB318        
41.          eor   buffer,temp                                        ;0x2710
42.          out   PORTB,buffer                                       ;0xBB18
43.          rcall delay                                              ;0xD001
44.          rjmp  main                                               ;0xCFFB

45. delay:   ldi   XH,high(PAUSE)                                     ;0xECB3
46.          ldi   XL,low(PAUSE)                                      ;0xE5A0
47.          sbiw  XH:XL,1                                            ;0x9711
48.          brne  PC-1                                               ;0xF7F1
49.          ret                                                      

В строках 1…3 приведено 3 возможных варианта оформления комментариев. Комментарий в строке 1, начинающийся со знака “;”, распознается любым ассемблером и поэтому является наиболее предпочтительным. Комментарии в строках 2 и 3 подобны тем, которые используются в нотациях языков высокого уровня. Последний из них дает возможность выделить сразу несколько строк (маркерами начала и конца фрагмента текста является “/*” и “*/” соответственно).

В строке 5 директивой .include к программе подключается стандартный заголовочный файл "m8def.inc". Необязательные директивы .nolist и .list (строки 4 и 6 соответственно) запрещают вывод содержимого подключаемого файла в файл листинга.

Все директивы допускается размещать в одной строке. Так, например, можно было бы записать
.nolist .include "m8def.inc" .list

Несмотря на это, желательно придерживаться правильного стиля программирования, в соответствии с которым в одной строке должна быть расположена только одна директива ассемблера.

Объявление констант находится в строках 7 и 8. Константе LED присваивается номер линии ввода-вывода PB2 = 2, описание которой находится в заголовочном файле. В строках 9 и 10 двум рабочим РОНам назначаются пользовательские имена.

Секция рабочего кода открывается директивой .cseg в строке 11. Директива .org 0 (строка 12) устанавливает начальный адрес в памяти программ. В строке 13 должна находиться инструкция перехода на метку начала основной программы initial.

Метка представляет собой адрес в пределах секции кода или данных. В ассемблере AVR она должна быть записана в начале строки и завершаться в конце двоеточием.

Конечно, адрес в команде может быть указан и явно. В данном примере его можно задать безошибочно (rjmp 0x20 вместо rjmp initial). Но, это возможно только потому, что директива .org 0x20 (строка 32) заставляет компилятор поместить команду в строке 33 по адресу 32-го слова FLASH-памяти программ. Однако, в большинстве случаев, адрес размещения той или иной команды заранее неизвестен и, кроме того, он может изменяться по мере того, как в программу будут вноситься изменения. Именно поэтому предпочтительней использовать метки. Назначение их адресов производится автоматически на этапе компиляции. Да и символьные имена меток, предоставляют об объектах намного больше информации, чем просо какие-то числа.

На месте каждого неиспользуемого в программе прерывания желательно поставить “заглушки” в виде команды возврата rjmp 0 или reti, как это сделано в строках 14…31.

В строках 33…39 производится инициализация ресурсов микроконтроллера. Любая программа обязательно должна начинаться с установки начального значения указателя стека (если он имеется). В строках 33…36 в SPH:SPL заносится значение RAMEND = 0x045F (вершина стека перемещается в самый верх SRAM). Для выделения младшего и старшего полубайтов константы RAMEND используются встроенные функции low(RAMEND)=0x5F и high(RAMEND)=0x04 соответственно.   

Далее разряд LED в регистре данных порта B сбрасывается на 0 (стока 37), а сама линия управления светодиодом настраивается на вывод (стока 38). В строке 39 в регистр temp заносится константа 1<

 ldi temp,(1«PB0)|(1«PB5) или ldi temp,(1«PB0)+(1«PB5)    ;temp <- 0b00100001  
 out DDRB,temp                                            ;DDRB <- temp  

Код в строках 40…44 представляет собой тело основной программы. В регистр buffer считывается текущее состояние порта данных PORTB (строка 40). Далее между содержимым buffer и temp производится операция “Исключающее ИЛИ” (строка 41), после чего модифицированное содержимое buffer снова выводится в порт (строках 42). В результате такого действия логический уровень на линии PB2 изменится на противоположный. В строке 43 происходит вызов подпрограммы задержки времени delay (≈200 мс), а в строке 44 расположена инструкция перехода на метку main. Так образуется основной цикл программы, в котором происходит постоянное повторение операторов в строках 40…44: инвертирование уровня на выводе LED, задержка, затем снова инвертирование и т.д.

Внутри подпрограммы delay в регистровую пару XH:XL заносится число PAUSE = 50000, определяющее длительность задержки времени (строки 45, 46). В строке 47 из содержимого XH:XL вычитается 1. Команда условного перехода в строке 48 проверяет, значение флага Z из SREG. Если Z = 1 (результат предыдущей операции не равен нулю), то управление передается на строку 47. Так будет повторяться до тех пор, пока не выполнится условие XH:XL = 0 (т.е. пока не пройдет 50000 циклов вычитания). Команда выхода ret в строке 49 возвращает управление в то место основной программы, с которого произошел вызов delay.

Отдельно стоит обратить внимание на встроенную в ассемблер переменную PC в строке 48. Она представляет собой текущее содержимое программного счетчика. Адрес PC-1 будет указывать на предыдущее слово в памяти программ микроконтроллера. В данном случае в этом слове находится команда sbiw XH:XL,1. Использовать PC очень удобно для программных переходов в небольших пределах. Однако здесь всегда необходимо помнить, что у микроконтроллеров AVR имеются команды, которые имеют размер в 2 16-разрядных слова программ (lds Rd,k, jmp k и др.), из-за чего при вычислении смещения необходимо будет добавлять\отнимать к PC значение 2 вместо 1 на каждую такую инструкцию.

Справа, в листинге приведен машинный код, который будет сгенерирован после компиляции программы.

Перейти к следующей части:

Теги:

Котов Игорь Юрьевич Опубликована: 2012 г. 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (0) | Я собрал (0) | Подписаться

Статью еще никто не комментировал. Вы можете стать первым.
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическая мощность?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

AVR-программатор USB ASP
AVR-программатор USB ASP
Паяльная станция Hakko 936 Макетная плата для пайки (10 шт)
вверх