AVR:Пример asm:Прочее

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск


Примеры кода на асемблере


Пример 1

<source lang="asm">

Пример1
Подсчет количества прерываний INT0 (результат увеличивается)
и INT1 (результат уменьшается)
Результат выводится в порт В
Подключение файла обьявления имен регистров ATmega8

.include "c:\...\m8def.inc"

.cseg .org 0

------------------ Вектора прерываний ---------------------------
         rjmp PROG
         rjmp SUBI_INT0
         rjmp SUBI_INT1
  reti ; rjmp SUBI_TIMER2_COMPARE
  reti ; rjmp SUBI_TIMER2_OVERFLOW
  reti ; rjmp SUBI_TIMER1_INPUT
  reti ; rjmp SUBI_TIMER1_COMPARE_A
  reti ; rjmp SUBI_TIMER1_COMPARE_B
  reti ; rjmp SUBI_TIMER1_OVERFLOW
  reti ; rjmp SUBI_TIMER0_OVERFLOW
  reti ; rjmp SUBI_SPI
  reti ; rjmp SUBI_USART_RECEIVE
  reti ; rjmp SUBI_USART_DATA_EMPTY
  reti ; rjmp SUBI_USART_TRANSMIT
  reti ; rjmp SUBI_ADC
  reti ; rjmp SUBI_EEPROM
  reti ; rjmp SUBI_COMPARATOR
  reti ; rjmp SUBI_TWI
  reti ; rjmp SUBI_SPM
-----------------------------------------------------------------
Начало программы

PROG:  ;PROG

  ldi  R16,high(RAMEND)       ;Инициализация стека
  out  SPH,R16
  ldi  R16,low(RAMEND)
  out  SPL,R16
Инициализация INT0 и INT1
                              ;INT.SenseControl=FallingEdge
  ldi  R16,(0<<ISC00)|(1<<ISC01)|(0<<ISC10)|(1<<ISC11)
  out  MCUCR,R16
  ldi  R16,(1<<INT0)|(1<<INT1);INT.Enable=1
  out  GICR,R16
Обнуление регистра R20 и установка порта В на вывод
  ldi  R20,$00                ;R20=$00
  ldi  R16,$FF                ;DDRB=$FF
  out  DDRB,R16
  sei                         ;I=1
Конец программы (бесконечный цикл)

END_PROG:  ;END PROG

  rjmp  END_PROG
-----------------------------------------------------------------
Начало подпрограммы обработки прерывания от INT1
                              ;SUBI INT0

SUBI_INT0:

  push R16
  in   R16,SREG
  push R16
  inc R20                     ;R20+$01
  out  PORTB,R20              ;PORTB=R20
Конец подпрограммы
  pop  R16                    ;END SUBI
  out  SREG,R16
  pop  R16
  reti
-----------------------------------------------------------------
Начало подпрограммы обработки прерывания от INT1
                              ;SUBI INT1

SUBI_INT1:

  in   R2,SREG
  dec  R20                    ;R20-$01
  out  PORTB,R20              ;PORTB=R20
Конец подпрограммы
  out  SREG,R2                ;END SUBI
  reti

</source> Avr primer asm o 1.gif

Пример 2

<source lang="asm">

TWI подчиненный (I2C) по прерыванию TWI
Результат выводится в порт В
Подключение файла обьявления имен регистров ATmega8

.include "c:\...\m8def.inc"

.cseg .org 0

------------------ Вектора прерываний ---------------------------
         rjmp PROG
  reti ; rjmp SUBI_INT0
  reti ; rjmp SUBI_INT1
  reti ; rjmp SUBI_TIMER2_COMPARE
  reti ; rjmp SUBI_TIMER2_OVERFLOW
  reti ; rjmp SUBI_TIMER1_INPUT
  reti ; rjmp SUBI_TIMER1_COMPARE_A
  reti ; rjmp SUBI_TIMER1_COMPARE_B
  reti ; rjmp SUBI_TIMER1_OVERFLOW
  reti ; rjmp SUBI_TIMER0_OVERFLOW
  reti ; rjmp SUBI_SPI
  reti ; rjmp SUBI_USART_RECEIVE
  reti ; rjmp SUBI_USART_DATA_EMPTY
  reti ; rjmp SUBI_USART_TRANSMIT
  reti ; rjmp SUBI_ADC
  reti ; rjmp SUBI_EEPROM
  reti ; rjmp SUBI_COMPARATOR
         rjmp SUBI_TWI
  reti ; rjmp SUBI_SPM
-----------------------------------------------------------------
Начало программы

PROG:  ;PROG

  ldi  R16,high(RAMEND)
  out  SPH,R16
  ldi  R16,low(RAMEND)
  out  SPL,R16
Инициализация TWI
  ldi  R16,$FF                ;DDRB=$FF
  out  DDRB,R16
  ldi  R16,$00                ;TWI.SlaveAdress=$40
  out  TWSR,R16
  ldi  R16,$40
  out  TWAR,R16
  ldi  R16,(1<<TWEA)|(1<<TWIE)|(1<<TWEN)
  out  TWCR,R16
Разрешение прерывания глобально
  sei                         ;I=1
Конец программы (бесконечный цикл)

END_PROG:  ;END PROG

  rjmp  END_PROG
-----------------------------------------------------------------
                              ;SUBI TWI

SUBI_TWI:

  push R16
  in   R16,SREG
  push R16
  push R20
Определение состояния шины WTI
  in   R20,TWSR               ;R20=TWI.Status
Если мастер передал адресс + W подчиненного отправляем ему байт данных
если нет определяем следующее состояние
  cpi  R20,$A8                ;IF R20<>$A8 GOTO Label1
  brne Label1
  ldi  R16,$24                ;TWI.Data=$24
  out  TWDR,R16

LABEL1:

Если мастер принял байт данных уже адресованному подчиненному
отправляем ему следующий байт данных
если нет определяем следующее состояние
  cpi  R20,$B8                ;IF R20<>$B8 GOTO Label2
  brne Label2
  ldi  R16,$24                ;TWI.Data=$24
  out  TWDR,R16

LABEL2:

Если мастер передал байт данных для подчиненного
заносим данные в порт В
  cpi  R20,$80                ;IF R20<>$80 GOTO Label3
  brne Label3
  in   R20,TWDR               ;R20=TWI.Data
  out  PORTB,R20              ;PORTB=R20

LABEL3:

Запуск и подтверждение приема-передачи данных.
                              ;TWI.Control=DataACK
  ldi  R16,(1<<TWINT)|(1<<TWIE)|(1<<TWEN)|(1<<TWEA)
  out  TWCR,R16
  pop  R16                    ;END SUBI
  out  SREG,R16
  pop  R16
  reti
-----------------------------------------------------------------

</source>

Пример 3

<source lang="asm">

TWI (I2C) Мастер,прием-передача
Результат выводится в порт В
Подключение файла обьявления имен регистров ATmega8

.include "c:\...\m8def.inc"

.cseg .org 0

------------------ Вектора прерываний ---------------------------
         rjmp PROG
-----------------------------------------------------------------
Начало программы

PROG:  ;PROG

  ldi  R16,high(RAMEND)
  out  SPH,R16
  ldi  R16,low(RAMEND)
  out  SPL,R16
  ldi  R16,$FF                ;DDRB=$FF
  out  DDRB,R16
Инициализация TWI,установка частоты SCL
  ldi  R16,$10                ;TWI.SCLfreguency=100K(8Mhz)
  out  TWBR,R16
Старт
                              ;TWI.Control=Start
  ldi  R16,(1<<TWSTA)|(1<<TWINT)|(1<<TWIE)|(1<<TWEN)
  out  TWCR,R16
Ожидание выполнения
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
Отправка адресса + R
  ldi  R16,$40                ;TWI.Data=$40
  out  TWDR,R16
                              ;TWI.Control=DataACK
  ldi  R16,(1<<TWINT)|(1<<TWIE)|(1<<TWEN)|(1<<TWEA)
  out  TWCR,R16
Ожидание выполнения
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
Отправка 1 байта
  ldi  R16,$11                ;TWI.Data=$11
  out  TWDR,R16
                              ;TWI.Control=DataACK
  ldi  R16,(1<<TWINT)|(1<<TWIE)|(1<<TWEN)|(1<<TWEA)
  out  TWCR,R16
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
Отправка 2 байта
  ldi  R16,$12                ;TWI.Data=$12
  out  TWDR,R16
                              ;TWI.Control=DataACK
  ldi  R16,(1<<TWINT)|(1<<TWIE)|(1<<TWEN)|(1<<TWEA)
  out  TWCR,R16
Ожидание выполнения
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
Стоп
                              ;TWI.Control=Stop
  ldi  R16,(1<<TWSTO)|(1<<TWINT)|(1<<TWIE)|(1<<TWEN)
  out  TWCR,R16
  ldi  R16,$40
  dec  R16
  brne (PC-1)
Старт
                              ;TWI.Control=Start
  ldi  R16,(1<<TWSTA)|(1<<TWINT)|(1<<TWIE)|(1<<TWEN)
  out  TWCR,R16
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
Отправка адресса + W
  ldi  R16,$41                ;TWI.Data=$41
  out  TWDR,R16
                              ;TWI.Control=DataACK
  ldi  R16,(1<<TWINT)|(1<<TWIE)|(1<<TWEN)|(1<<TWEA)
  out  TWCR,R16
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
Прием 1 байта
                              ;TWI.Control=DataACK
  ldi  R16,(1<<TWINT)|(1<<TWIE)|(1<<TWEN)|(1<<TWEA)
  out  TWCR,R16
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
  in   R20,TWDR               ;R20=TWI.Data
  out  PORTB,R20              ;PORTB=R20
Прием 2 байта (при окончании приема мастер
должен выставить на шину NACK)
                              ;TWI.Control=DataNACK
  ldi  R16,(1<<TWINT)|(1<<TWIE)|(1<<TWEN)
  out  TWCR,R16
  in   R16,TWCR               ;TWI.WAIT(TWINT)
  sbrs R16,TWINT
  rjmp (PC-2)
  in   R20,TWDR               ;R20=TWI.Data
  out  PORTB,R20              ;PORTB=R20
Стоп
                              ;TWI.Control=Stop
  ldi  R16,(1<<TWSTO)|(1<<TWINT)|(1<<TWIE)|(1<<TWEN)
  out  TWCR,R16
  ldi  R16,$40
  dec  R16
  brne (PC-1)
Конец программы (бесконечный цикл)

END_PROG:  ;END PROG

  rjmp  END_PROG
-----------------------------------------------------------------

</source> Avr primer asm o 2.gif

Пример 4

<source lang="asm">;Вывод данных через USART

Подключение файла обьявления имен регистров ATmega8

.include "c:\...\m8def.inc"

.cseg .org 0

------------------ Вектора прерываний ---------------------------
         rjmp PROG
-----------------------------------------------------------------
Начало программы

PROG:  ;PROG

  ldi  R16,high(RAMEND)
  out  SPH,R16
  ldi  R16,low(RAMEND)
  out  SPL,R16
Инициализация USART
  ldi  R16,$00                ;USART.Mode=9600,N,1(8Mhz)
  out  UCSRA,R16
  ldi  R16,$86
  out  UCSRC,R16
  ldi  R16,$33
  out  UBRRL,R16
  ldi  R16,$00
  out  UBRRH,R16
  ldi  R16,$F9
  out  UCSRB,R16 
Передача байта (символа) данных
  ldi  R16,$04                ;USART.Data=$04
  out  UDR,R16
Ожидание конца передачи
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
Передача байта (символа) данных
  ldi  R16,'P'                ;USART.Data="P"
  out  UDR,R16
Ожидание конца передачи
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
Передача байта (символа) данных
  ldi  R16,'r'                ;USART.Data="r"
  out  UDR,R16
Ожидание конца передачи
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
  ldi  R16,'i'                ;USART.Data="i"
  out  UDR,R16
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
  ldi  R16,'v'                ;USART.Data="v"
  out  UDR,R16
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
  ldi  R16,'e'                ;USART.Data="e"
  out  UDR,R16
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
  ldi  R16,'t'                ;USART.Data="t"
  out  UDR,R16
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
  ldi  R16,'!'                ;USART.Data="!"
  out  UDR,R16
  in   R16,UCSRA              ;USART.WAIT(UDRE)
  sbrs R16,UDRE
  rjmp (PC-2)
Конец программы (бесконечный цикл)

END_PROG:  ;END PROG

  rjmp  END_PROG
-----------------------------------------------------------------

</source>


Пример 5

<source lang="asm">;Прием данных по USART

Результат выводится в порт В
Подключение файла обьявления имен регистров ATmega8

.include "c:\...\m8def.inc"

.cseg .org 0

------------------ Вектора прерываний ---------------------------
         rjmp PROG
-----------------------------------------------------------------
Начало программы

PROG:  ;PROG

  ldi  R16,high(RAMEND)
  out  SPH,R16
  ldi  R16,low(RAMEND)
  out  SPL,R16
  ldi  R16,$FF                ;DDRB=$FF
  out  DDRB,R16
Инициализация USART
  ldi  R16,$00                ;USART.Mode=9600,N,1(8Mhz)
  out  UCSRA,R16
  ldi  R16,$86
  out  UCSRC,R16
  ldi  R16,$33
  out  UBRRL,R16
  ldi  R16,$00
  out  UBRRH,R16
  ldi  R16,$F9
  out  UCSRB,R16 
Ждем приема данных
  in   R16,UCSRA              ;USART.WAIT(RXC)
  sbrs R16,RXC
  rjmp (PC-2)
  in   R20,UDR                ;R20=USART.Data
  out  PORTB,R20              ;PORTB=R20
Конец программы (бесконечный цикл)

END_PROG:  ;END PROG

  rjmp  END_PROG
-----------------------------------------------------------------

</source> Avr primer asm o 3.gif

Пример 6

<source lang="asm">;Увеличение значения при нажатии на кнопку "+" и уменьшение при "-"

Сканирование клавиатуры 4*4 с помощью подпрограммы BUTTON
Подпрограмма однократно возвращает значение(символ) кнопки при нажатии
При удержании или не нажатых кнопках возвращает $00
В шаблонах можно изменить присваемое значение каждой кнопке
а также менять скорость опроса кнопок.
Подключение файла обьявления имен регистров ATmega8

.include "c:\...\m8def.inc"

.cseg .org 0

------------------ Вектора прерываний ---------------------------
  rjmp PROG
-----------------------------------------------------------------
Начало программы

PROG:  ;PROG

  ldi  R16,high(RAMEND)
  out  SPH,R16
  ldi  R16,low(RAMEND)
  out  SPL,R16
  ldi  R21,$00                ;R21=$00
  ldi  R16,$FF                ;DDRB=$FF
  out  DDRB,R16

LABEL1:

  rcall BUTTON
  cpi  R20,'+'                ;IF R20<>'+' GOTO LABEL2
  brne LABEL2
  inc  R21                    ;R21+

LABEL2:

  cpi  R20,'-'                ;IF R20<>'-' GOTO LABEL3
  brne LABEL3
  dec  R21                    ;R21-
  out  PORTB,R21              ;PORTB=R21

LABEL3:

  out  PORTB,R21              ;PORTB=R21
  rjmp  LABEL1                ;GOTO LABEL1
Конец программы (бесконечный цикл)

END_PROG:  ;END PROG

  rjmp  END_PROG
-----------------------------------------------------------------
Начало подпрограммы BUTTON

BUTTON:

  ldi  R16,$0F                ;R20=BUTTON.PortD
  out  DDRD,R16
  ldi  R16,$00
  ldi  ZL,$01
  out  PORTD,ZL
  ldi  ZH,$10
  dec  ZH
  cpi  ZH,$00
  brne (PC-2)
  sbic PIND,4
  ldi  R16,'7'  ;'7'=$37
  sbic PIND,5
  ldi  R16,'8'  ;'8'=$38
  sbic PIND,6
  ldi  R16,'9'  ;'9'=$39
  sbic PIND,7
  ldi  R16,'/'  ;'/'
  ldi  ZL,$02
  out  PORTD,ZL
  ldi  ZH,$10
  dec  ZH
  cpi  ZH,$00
  brne (PC-2)
  sbic PIND,4
  ldi  R16,'4'  ;'4'=$34
  sbic PIND,5
  ldi  R16,'5'  ;'5'=$35
  sbic PIND,6
  ldi  R16,'6'  ;'6'=$36
  sbic PIND,7
  ldi  R16,'*'  ;'*'
  ldi  ZL,$04
  out  PORTD,ZL
  ldi  ZH,$10
  dec  ZH
  cpi  ZH,$00
  brne (PC-2)
  sbic PIND,4
  ldi  R16,'1'  ;'1'=$31
  sbic PIND,5
  ldi  R16,'2'  ;'2'=$32
  sbic PIND,6
  ldi  R16,'3'  ;'3'=$33
  sbic PIND,7
  ldi  R16,'-'  ;'-'
  ldi  ZL,$08
  out  PORTD,ZL
  ldi  ZH,$10
  dec  ZH
  cpi  ZH,$00
  brne (PC-2)
  sbic PIND,4
  ldi  R16,'C'  ;'C'
  sbic PIND,5
  ldi  R16,'0'  ;'0'=$30
  sbic PIND,6
  ldi  R16,'='  ;'='
  sbic PIND,7
  ldi  R16,'+'  ;'+'
  lds  ZH,$060
  sts  $060,R16
  cpse ZH,R16
  rjmp (PC+2)
  ldi  R16,$00
  mov  R20,R16
  ret
Конец подпрограммы
-----------------------------------------------------------------

</source> Avr primer asm o 4.gif