320 lines
7.5 KiB
Plaintext
320 lines
7.5 KiB
Plaintext
# avr-asm
|
|
|
|
explorando programación de microcontroladores avr a través de asm, en attiny85. {s-camino}
|
|
|
|
# attiny85
|
|
|
|
## diagrama de pines
|
|
|
|
```diagrama de pines
|
|
┌──────┐
|
|
PB5 │1 8│ VCC
|
|
PB3 │2 7│ PB2
|
|
PB4 │3 6│ PB1
|
|
GND │4 5│ PB0
|
|
└──────┘
|
|
```
|
|
|
|
además, cada pin es:
|
|
|
|
* 1: PB5 / PCINT5 / ~RESET / ADC0 / dW
|
|
* 2: PB3 / PCINT3 / XTAL1 / CLKI / ~OC1B / ADC3
|
|
* 3: PB4 / PCINT4 / XTAL2 / CLKO / OC1B / ADC2
|
|
* 5: PB0 / MOSI / DI / SDA / AIN0 / OC0A / ~OC1A / AREF / PCINT0
|
|
* 6: PB1 / MISO / DO / AIN1 / OC0B / OC1A / PCINT1
|
|
* 7: PB2 / SCK / USCK / SCL / ADC1 / T0 / INT0 / PCINT2
|
|
|
|
para flashear nos interesan los pines desde el punto de vista de SPI:
|
|
|
|
```pines spi
|
|
┌──────┐
|
|
~RESET │1 8│ VCC
|
|
│2 7│ SCK
|
|
│3 6│ MISO
|
|
GND │4 5│ MOSI
|
|
└──────┘
|
|
```
|
|
|
|
## programador
|
|
|
|
=> https://www.fischl.de/usbasp/ USBasp - USB programmer for Atmel AVR controllers (web)
|
|
|
|
## makefile
|
|
|
|
para ensamblar y flashear
|
|
|
|
```makefile
|
|
# Makefile
|
|
# nombre del programa sin .S :
|
|
PROG = test
|
|
# config hardware
|
|
BOARD = attiny85
|
|
PROGRAMMER = usbasp
|
|
|
|
# ensambla programa a .hex
|
|
hex:
|
|
avr-gcc -Os -DF_CPU=8000000 -mmcu=$(BOARD) -c $(PROG).S
|
|
avr-ld -o $(PROG).elf $(PROG).o
|
|
avr-objcopy $(PROG).elf -O ihex $(PROG).hex
|
|
rm $(PROG).o $(PROG).elf
|
|
|
|
# flashea
|
|
flash:
|
|
avrdude -c $(PROGRAMMER) -p $(BOARD) -U flash:w:$(PROG).hex:i
|
|
|
|
# lee la memoria flash a read.hex
|
|
read:
|
|
avrdude -c $(PROGRAMMER) -p $(BOARD) -U flash:r:read.hex:i
|
|
|
|
# prueba conexión con programador y micro
|
|
test:
|
|
avrdude -c $(PROGRAMMER) -p $(BOARD)
|
|
```
|
|
|
|
|
|
|
|
# programas
|
|
|
|
software experimental, compartido como referencia y sin garantía de ningún tipo :)
|
|
|
|
|
|
## test.S
|
|
|
|
enciende un el pin PB0 — conecta un led
|
|
|
|
```
|
|
; test.S
|
|
; enciende un pin
|
|
#include <avr/io.h>
|
|
.org 0x0000
|
|
|
|
ldi r17, (1<<DDB0) ; configura al PB0 como salida
|
|
sts DDRB, r17
|
|
|
|
ldi r16, (1<<PB0) ; enciende el bit correspondiente al PB0
|
|
sts PORTB, r16 ; actualiza el puerto
|
|
|
|
sleep ; duerme por siempre (?)
|
|
```
|
|
|
|
## blink.S
|
|
|
|
parpadea el pin PB0 usando el timer/counter0 — conecta un led
|
|
|
|
```
|
|
; blink.S
|
|
; parpadea el pin PB0 (OC0A)!
|
|
; r16 y r17 se usan como registros auxiliares
|
|
|
|
; el programa usa el timer/counter 0 con:
|
|
; * waveform generation mode (WGM0): 2, que es CTC (clear timer on compare match)
|
|
; * compare match output A mode (COM0A): 1, que es toggle en compare match
|
|
; * clock select (CS0): 5, que utiliza el reloj i/o dividido entre 1024
|
|
|
|
; notas sobre el reloj:
|
|
; por default el attiny85 va a 8MHz, y el reloj i/o va a 1MHz
|
|
; 1MHz/1024 ~= 967 Hz
|
|
|
|
#include <avr/io.h>
|
|
; ***********************
|
|
; vectores de interrupts:
|
|
; ***********************
|
|
; Reset
|
|
.org 0x0000
|
|
rjmp main
|
|
|
|
; ***********************
|
|
; Main
|
|
; ***********************
|
|
.org 0x0010
|
|
main:
|
|
; pin PB0 (OC0A) como pin de salida
|
|
ldi r16, (1<<DDB0) ; pin de salida
|
|
sts DDRB, r16
|
|
|
|
; togglea OC0A en Compare match (1 en COM0A[1:0])
|
|
; y usa modo Clear Timer on Compare Match (2 en WGM0[2:0])
|
|
ldi r16, (0<<COM0A1) | (1<<COM0A0) | (1<<WGM01) | (0<<WGM00)
|
|
sts TCCR0A, r16
|
|
|
|
; completa el modo WGM (waveform generaton mode, bit 2)
|
|
; establece el tipo de reloj: 0b101 en CS0 es clk/1024
|
|
ldi r16, (0<<WGM02) | (1<<CS02) | (0<<CS01) | (1<<CS00)
|
|
sts TCCR0B, r16
|
|
|
|
; el TOP es el valor en OCR0A
|
|
ldi r16, 0x80
|
|
sts OCR0A, r16
|
|
|
|
loop:
|
|
sleep
|
|
rjmp loop
|
|
```
|
|
|
|
## buzz.S
|
|
|
|
zumba el pin PB0 — conecta un buzzer
|
|
|
|
```
|
|
; buzz.S
|
|
; haz zumbar el pin PB0 (OC0A)!
|
|
; el código es igual a blink.S, pero con diferentes frecuencias
|
|
; r16 y r17 se usan como registros auxiliares
|
|
|
|
; el programa usa el timer/counter 0 con:
|
|
; * waveform generation mode (WGM0): 2, que es CTC (clear timer on compare match)
|
|
; * compare match output A mode (COM0A): 1, que es toggle en compare match
|
|
; * clock select (CS0): 4, que utiliza el reloj i/o dividido entre 256
|
|
|
|
; notas sobre el reloj:
|
|
; por default el attiny85 va a 8MHz, y el reloj i/o va a 1MHz
|
|
; 1MHz/256 ~= 3906 Hz (/2 para el periodo completo ~=1953Hz)
|
|
|
|
#include <avr/io.h>
|
|
; ***********************
|
|
; vectores de interrupts:
|
|
; ***********************
|
|
; Reset
|
|
.org 0x0000
|
|
rjmp main
|
|
|
|
; ***********************
|
|
; Main
|
|
; ***********************
|
|
.org 0x0010
|
|
main:
|
|
; pin PB0 (OC0A) como pin de salida
|
|
ldi r16, (1<<DDB0) ; pin de salida
|
|
sts DDRB, r16
|
|
|
|
; togglea OC0A en Compare match (1 en COM0A[1:0])
|
|
; y usa modo Clear Timer on Compare Match (2 en WGM0[2:0])
|
|
ldi r16, (0<<COM0A1) | (1<<COM0A0) | (1<<WGM01) | (0<<WGM00)
|
|
sts TCCR0A, r16
|
|
|
|
; completa el modo WGM (waveform generaton mode, bit 2)
|
|
; establece el tipo de reloj: 0b100 en CS0 es clk/256
|
|
ldi r16, (0<<WGM02) | (1<<CS02) | (0<<CS01) | (0<<CS00)
|
|
sts TCCR0B, r16
|
|
|
|
; el TOP es el valor en OCR0A
|
|
ldi r16, 0x02
|
|
sts OCR0A, r16
|
|
|
|
loop:
|
|
sleep
|
|
rjmp loop
|
|
```
|
|
|
|
## alarm.S
|
|
|
|
zumbido intermitente en el pin PB0 — conecta un buzzer
|
|
|
|
```
|
|
; alarm.S
|
|
; zumbido intermitente en el pin PB0 (OC0A)!
|
|
; r16 y r17 se usan como registros auxiliares
|
|
; r20 tiene el valor de TCCR0A para apagar sonido
|
|
; r21 tiene el valor de TCCR0A para encenderlo
|
|
|
|
; el programa usa el timer/counter 0 con:
|
|
; * waveform generation mode (WGM0): 2, que es CTC (clear timer on compare match)
|
|
; * compare match output A mode (COM0A): 1, que es toggle en compare match
|
|
; * clock select (CS0): 3, que utiliza el reloj i/o dividido entre 64
|
|
|
|
; y el timer/counter 1 con:
|
|
; * clock select (CS1): 0b1010, que es clk/512
|
|
; * interrupciones de overflow y de compare match A:
|
|
; - en compare match A el zumbido se apaga
|
|
; - en overflow el zumbido inicia
|
|
|
|
; notas sobre el reloj:
|
|
; por default el attiny85 va a 8MHz, y el reloj i/o va a 1MHz
|
|
; 1MHz/256 ~= 3906 Hz (/2 para el periodo completo ~=1953Hz)
|
|
|
|
#include <avr/io.h>
|
|
; ***********************
|
|
; vectores de interrupts:
|
|
; ***********************
|
|
; Reset
|
|
.org 0x0000
|
|
rjmp main
|
|
|
|
; dirección 0x0003 * 2
|
|
.org 0x0006
|
|
rjmp timer1compareA_isr
|
|
|
|
; dirección 0x0004 * 2
|
|
.org 0x0008
|
|
rjmp timer1overflow_isr
|
|
|
|
; ***********************
|
|
; Main
|
|
; ***********************
|
|
.org 0x001E
|
|
main:
|
|
;----------------------------------
|
|
; configuración general
|
|
;----------------------------------
|
|
|
|
; habilita interrupciones
|
|
sei
|
|
|
|
; pin PB0 (OC0A) como pin de salida
|
|
ldi r16, (1<<DDB0) ; pin de salida
|
|
sts DDRB, r16
|
|
|
|
; valores de TCCR0A para encender o apagar sonido
|
|
ldi r20, (0<<COM0A1) | (0<<COM0A0) | (1<<WGM01) | (0<<WGM00)
|
|
ldi r21, (0<<COM0A1) | (1<<COM0A0) | (1<<WGM01) | (0<<WGM00)
|
|
|
|
;----------------------------------
|
|
; configuración TIMER0 para buzzer
|
|
;----------------------------------
|
|
; togglea OC0A en Compare match (1 en COM0A[1:0])
|
|
; y usa modo Clear Timer on Compare Match (2 en WGM0[2:0])
|
|
sts TCCR0A, r21
|
|
|
|
; completa el modo WGM (waveform generaton mode, bit 2)
|
|
; establece el tipo de reloj: 0b011 en CS0 es clk/64
|
|
ldi r16, (0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00)
|
|
sts TCCR0B, r16
|
|
|
|
; el TOP es el valor en OCR0A
|
|
; más pequeño es más agudo
|
|
ldi r16, 0x06
|
|
sts OCR0A, r16
|
|
|
|
;----------------------------------
|
|
; configuración TIMER1 para alternar entre sonido on/off
|
|
;----------------------------------
|
|
; CS1 en 0b1010 es CK/512
|
|
ldi r16, (1<<CS13) | (0<<CS12) | (1<<CS11) | (0<<CS10)
|
|
sts TCCR1, r16
|
|
|
|
; establece el valor A al que cuenta el timer1 antes de apagar sonido
|
|
; menor valor, menor tiempo de sonido (duty cycle)
|
|
ldi r16, 0x30
|
|
sts OCR1A, r16
|
|
|
|
; set Timer overflow interrupt enable 1
|
|
; y timer output compare A interrupt enable 1
|
|
ldi r16, (1<<TOIE1) | (1<<OCIE1A)
|
|
sts TIMSK, r16
|
|
|
|
loop:
|
|
sleep
|
|
rjmp loop
|
|
|
|
timer1compareA_isr:
|
|
; apaga la salida
|
|
sts TCCR0A, r20
|
|
reti
|
|
|
|
timer1overflow_isr:
|
|
; enciende la salida
|
|
sts TCCR0A, r21
|
|
; regresa de la interrupción
|
|
reti
|
|
```
|