Arduino / Atmel Output Assembly?

4

Una cosa que no entiendo al leer acerca de cómo hacer ensamblaje con el AVR de Atmel (o quizás con la plataforma Arduino) es la salida real a dispositivos (como LEDS / motores) y demás. La mayoría de los "tutoriales" de ensamblajes simplemente explican el conteo / las cosas numéricas con los registros.

¿Alguien puede explicar cómo se envía exactamente una señal de salida a un motor o LED bajo el ensamblaje de AVR?

Supongo que no entiendo exactamente lo que hace cada "pin" para el microcontrolador, y cuáles pueden enviar señales de salida. (para encender un motor o led)

    
pregunta

3 respuestas

6

El AVR, como la mayoría de los microcontroladores, utiliza IO asignada en la memoria . En pocas palabras, esto significa que una parte del espacio de memoria del microcontrolador está reservado para los periféricos. Cuando cambia un poco en esta área de la memoria, no está enviando una señal para cambiar un poco de memoria, está enviando una señal para cambiar el valor de un periférico.

Para comprender los detalles de cómo funciona esto en su AVR, Registros de funciones especiales Se recomienda leer la sección de AVR-libc (y, lo que es más importante, sfr_defs.hy iom328p.h).

[Advertencia: Escritura técnica por delante, preste mucha atención] Por ejemplo, PORTB se define como _SFR_IO8(0x05) en iom328p.h . En sfr_defs.h , _SFR_IO8(io_addr) se define como _MMIO_BYTE((io_addr) + __SFR_OFFSET) . __SFR_OFFSET es 0x20 , la ubicación justo después de los registros. El espacio después de esta dirección y antes de RAMSTART (0x100) se usa para los periféricos. Volviendo a nuestro ejemplo, _MMIO_BYTE(mem_addr) se define como (*(volatile uint8_t *)(mem_addr)) . Por lo tanto, cuando escribe PORTB , realmente está escribiendo *(volatile uint8_t *)(0x25) , que define un puntero de byte a la ubicación en la memoria 0x25 . [/ Advertencia]

Entonces, cuando (en C) escribes PORTB | = 0x01, realmente estás escribiendo el valor 1 en el periférico en el byte 0x25, o el puerto B pin 0. Si este pin está configurado como salida (usando DDRB, que está en 0x24), PORTB | = 0x01 hará que el pin 0 del puerto B pase a nivel alto. ¡Uf!

Por lo tanto, si usa las instrucciones de ensamblaje (SBI - Establecer bit en el registro de E / S):

sbi  0x24,1 ;Data direction set to output
sbi  0x25,1 ;Set port B pin 0 high

Pondrás el pin alto.

Por supuesto, use el ensamblador en línea con GCC y #include <avr/io.h> para obtener los nombres convencionales y simplificar su tarea.

Tenga en cuenta que todos de los periféricos usan este esquema, no solo los pines IO. Lea iom328p.h si está interesado en las ubicaciones de otros periféricos.

    
respondido por el Kevin Vermeer
1

Algo como esto:

    #define LED PB3

    sbi    DDRB,LED     ;PB3 output (LED)

loop:
    sbi     PORTB,LED       ;LED on
    rcall   dly
    cbi     PORTB,LED       ;LED off
    rcall   dly
    rjmp    loop

He omitido muchas otras cosas que se necesitan para un programa que funcione.

    
respondido por el Leon Heller
0
.device ATmega168
.equ  DDRB       = 0x04
.equ  PORTB      = 0x05

.org 0x0000
    rjmp RESET

RESET:
    ldi R16,0x20
    out DDRB,R16

    ldi R18,0x00
    ldi R17,0x00
    ldi R20,0x20
Loop:

    ldi R19,0xE8
aloop:
    inc R17
    cpi R17,0x00
    brne aloop

    inc R18
    cpi R18,0x00
    brne aloop

    inc R19
    cpi R19,0x00
    brne aloop

    eor R16,R20
    out PORTB, R16
    rjmp Loop
    
respondido por el old_timer

Lea otras preguntas en las etiquetas