💾 Archived View for compudanzas.net › avr-asm.gmi captured on 2023-03-20 at 17:55:45. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2022-06-11)
-=-=-=-=-=-=-
explorando programación de microcontroladores avr a través de asm, en attiny85. s-camino
en debian-based:
sudo apt install gcc-avr avrdude avr-libc
┌──────┐ PB5 │1 8│ VCC PB3 │2 7│ PB2 PB4 │3 6│ PB1 GND │4 5│ PB0 └──────┘
además, cada pin es:
para flashear nos interesan los pines desde el punto de vista de SPI:
┌──────┐ ~RESET │1 8│ VCC │2 7│ SCK │3 6│ MISO GND │4 5│ MOSI └──────┘
USBasp - USB programmer for Atmel AVR controllers (web)
possible udev rule for e.g. /etc/udev/rules.d/80-usbasp.rules, por si las dudas. en principio no se debería necesitar.
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05dc", OWNER="user", GROUP="dialout", MODE="0777"
para ensamblar y flashear
# 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)
software experimental, compartido como referencia y sin garantía de ningún tipo :)
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 (?)
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
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
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
textos, imágenes y código compartidos bajo la licencia de producción de pares