es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Problema al configurar los GPIO en STM32F103 utilizando ensamblador

Mi objetivo es escribir un código de ensamblaje de metal desnudo para STM32F103 que encienda el LED PB1.
Los pasos que sigo se enumeran a continuación:
1. Habilitar el bit IOPB 3 en el registro RCC_APB2ENR, que tiene una dirección de 0x18, restablecido desde la dirección base de RCC, 0x40021000. (El valor de reinicio de este registro es 0x00000000)
2. Habilitar los bits CNF1 (00): 7-6 y MODE1 (10): 5-4 para PB1 en el registro GPIO_CRL, cuyos valores de reinicio son 0x44444444 y su dirección es un desplazamiento de 0x0 desde la dirección base de GPIO_BASE, 0x40010C00. Esta configuración establece el puerto como salida de propósito general de empuje-pull con una velocidad máxima de 2 MHz.
3. Configurar el bit 1 – ODR1 en el registro GPIOx_ODR, que es un desplazamiento de 0x0C desde GPIO_BASE y su valor de reinicio es 0x00000000.

   stack_size      EQU      0x400 ; 0x400 = 1024 byte = 1kB
   stack_start     EQU      0x20000000 + stack_size
   gpiob_base      EQU      0x40010C00
   rcc_base        EQU      0x40021000
   rcc_apb2enr     EQU      rcc_base+0x18
   gpio_crl        EQU      gpiob_base
   gpiob_odr       EQU      gpiob_base+0x0C


            PRESERVE8
            THUMB 

            AREA RESET, DATA, READONLY
            DCD stack_start 
            DCD __mainCode              
            AREA |.text|, CODE, READONLY 
            ENTRY   
   __mainCode   PROC 
                LDR R0, =rcc_apb2enr
                LDR R1, [R0]
                LDR R2, =0x4
                ORR R1, R2
                STR R1, [R0]

                ; Configure GPIO_CRL
                LDR R0, =gpio_crl
                LDR R1, [R0]
                LDR R2, =0xFFFFFF00
                AND R1,R1,R2
                ORR R1, R1, #0x20
                STR R1, [R0] ; Reset register

                ; Configure GPIOB_ODR
                LDR R0, =gpiob_odr
                LDR R1, [R0]
                ORR R1, #0x2
                STR R1, [R0]
                NOP
            ENDP 
            ALIGN
            END

Desafortunadamente, el código no enciende el LED. He depurado el código y notado lo siguiente:
1. Después de restablecer, el valor de GPIO_CRL debería ser 0x44444444, pero es 0x44444844.

enter image description here

  1. El valor del registro GPIO_ODR debe ser 0x00000000, pero también es 0x00000001. Después de realizar la operación ORR con 0x2 y querer almacenarlo de nuevo en la dirección de registro 0x40010C0C, su valor permanece sin cambios (0x00000001).

enter image description here

Por favor, aconseje qué está mal en mi código y cómo puedo solucionarlo?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Posibles errores en el código:

    1. La dirección de GPIO_CRL debería ser especificada como un desplazamiento desde GPIOB_BASE (0x40010C00), no como GPIOB_BASE en sí mismo.
      gpio_crl EQU gpiob_base+0x00
    2. Los bits de configuración para CNF1 y MODE1 deberían ser desplazados a la posición correcta antes de ORear con el valor existente en GPIO_CRL.
      ORR R1, R1, #(0b0010<<4) ; configurar MODE1 en modo de salida
      ORR R1, R1, #(0b00<<6) ; configurar CNF1 en push-pull

      Alternativamente, los valores pueden ser definidos como constantes:
      mode_output EQU 0b0010
      cnf_pushpull EQU 0b00
      ...
      ORR R1, R1, #(mode_output<<4)
      ORR R1, R1, #(cnf_pushpull<<6)
    3. La dirección del registro para GPIOB_ODR debería ser especificada como un desplazamiento desde GPIOB_BASE (0x40010C00), no como una dirección absoluta.
      gpiob_odr EQU gpiob_base+0x0C
    4. Es posible que el LED no se encienda si está conectado incorrectamente o si su polaridad está invertida (es decir, se enciende cuando la salida está baja).

    Soluciones sugeridas en el código:

       ; Definir constantes para direcciones de registro y valores de configuración
       rcc_apb2enr EQU rcc_base+0x18
       gpiob_base   EQU 0x40010C00
       gpio_crl     EQU gpiob_base+0x00
       gpiob_odr    EQU gpiob_base+0x0C
       mode_output  EQU 0b0010
       cnf_pushpull EQU 0b00
    
       ; Configurar PB1 como salida
       LDR R0, =rcc_apb2enr
       LDR R1, [R0]
       ORR R1, #(1<<3) ; habilitar el clock de GPIOB
       STR R1, [R0]
    
       LDR R0, =gpio_crl
       LDR R1, [R0]
       AND R1, #(0xFFFFFF00) ; limpiar los bits CRL1-4
       ORR R1, #(mode_output<<4) ; configurar MODE1 como modo de salida
       ORR R1, #(cnf_pushpull<<6) ; configurar CNF1 en push-pull
       STR R1, [R0]
    
       ; Encender el LED de PB1
       LDR R0, =gpiob_odr
       LDR R1, [R0]
       ORR R1, #(1<<1) ; configurar ODR1 como alto
       STR R1, [R0]
    
       ; Fin del programa
    

Comments are closed.