diff options
Diffstat (limited to 'web/avr-asm.html')
-rw-r--r-- | web/avr-asm.html | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/web/avr-asm.html b/web/avr-asm.html new file mode 100644 index 0000000..04ca746 --- /dev/null +++ b/web/avr-asm.html @@ -0,0 +1,340 @@ +<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> +<html xmlns='http://www.w3.org/1999/xhtml' lang='es-MX,en'> +<head> +<meta http-equiv='Content-Type' content='text/html; charset=utf-8' /> +<meta content='initial-scale=1.0, maximum-scale=1.0, user-scalable=yes' name='viewport'/> +<link rel='stylesheet' href='./static/estilo.css'> +<title>🥭 — avr-asm</title> +</head> +<body> +<header> +<p><a href='./index.html'>{🥭}</a></p> +<h1>avr-asm</h1> +</header> +<nav><ul><li><a href='#attiny85'>attiny85</a></li> +<li><a href='#programas'>programas</a></li> + +</ul></nav> +<main><section><p> +explorando programación de microcontroladores avr a través de asm, en attiny85. <a href='./s-camino.html'>{s-camino}</a> +</p> +</section><section> +<h1 id='attiny85'>attiny85</h1> +<h2 id='diagrama de pines'>diagrama de pines</h2> +<pre> + ┌──────┐ +PB5 │1 8│ VCC +PB3 │2 7│ PB2 +PB4 │3 6│ PB1 +GND │4 5│ PB0 + └──────┘ +</pre> +<p> +además, cada pin es: +</p> +<ul> +<li>1: PB5 / PCINT5 / ~RESET / ADC0 / dW</li> +<li>2: PB3 / PCINT3 / XTAL1 / CLKI / ~OC1B / ADC3</li> +<li>3: PB4 / PCINT4 / XTAL2 / CLKO / OC1B / ADC2</li> +<li>5: PB0 / MOSI / DI / SDA / AIN0 / OC0A / ~OC1A / AREF / PCINT0</li> +<li>6: PB1 / MISO / DO / AIN1 / OC0B / OC1A / PCINT1</li> +<li>7: PB2 / SCK / USCK / SCL / ADC1 / T0 / INT0 / PCINT2</li> +</ul> +<p> +para flashear nos interesan los pines desde el punto de vista de SPI: +</p> +<pre> + ┌──────┐ +~RESET │1 8│ VCC + │2 7│ SCK + │3 6│ MISO +GND │4 5│ MOSI + └──────┘ +</pre> +<h2 id='programador'>programador</h2> +<p><a href='https://www.fischl.de/usbasp/' rel=external target=_blank>USBasp - USB programmer for Atmel AVR controllers (web)</a></p> +<h2 id='makefile'>makefile</h2> +<p> +para ensamblar y flashear +</p> +<pre> +# 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) +</pre> +</section><section> +<h1 id='programas'>programas</h1> +<p> +software experimental, compartido como referencia y sin garantía de ningún tipo :) +</p> +<h2 id='test.S'>test.S</h2> +<p> +enciende un el pin PB0 — conecta un led +</p> +<pre> +; 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 (?) +</pre> +<h2 id='blink.S'>blink.S</h2> +<p> +parpadea el pin PB0 usando el timer/counter0 — conecta un led +</p> +<pre> +; 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 +</pre> +<h2 id='buzz.S'>buzz.S</h2> +<p> +zumba el pin PB0 — conecta un buzzer +</p> +<pre> +; 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 +</pre> +<h2 id='alarm.S'>alarm.S</h2> +<p> +zumbido intermitente en el pin PB0 — conecta un buzzer +</p> +<pre> +; 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 +</pre> + +</section> +</main> +<footer> +<p><a href='./index.html'>{🥭}</a></p> +<p>página actualizada en: +<time datetime='2021-05-20'>sejmana-1660, día 1</time> + (12021-05-20) +</p> +<a href='https://endefensadelsl.org/ppl_es.html' rel=external target=_blank>ppl: licencia de producción de pares</a></p> +</footer> +</body> +</html> |