AVR:Пример asm:Прочее
Примеры кода на асемблере
Содержание
Пример 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
Пример 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
- -----------------------------------------------------------------
Пример 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
- -----------------------------------------------------------------
Пример 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
- Конец подпрограммы
- -----------------------------------------------------------------