7 votos

Mi primer código STM32 - por favor, critícame

Acabo de escribir mi primer código en STM32 - LED parpadeante. Combina un fragmento de diferentes fuentes; por favor, criticar a mí para que pueda aprender a escribir el código adecuado y no aprenden hábitos estúpidos.

#include "stm32f30x.h"

void SysTick_Handler(void);
void TimingDelay_Decrement(void);
void Delay(__IO uint32_t nTime);

static __IO uint32_t TimingDelay;

int main(void)
{
  RCC->AHBENR  |=  ((1UL << 21) );                  // Enable GPIOE clock??
  GPIOE->MODER |= (1 << 2*8);                       // PIN 9 as output

//GPIOE->BSRR = 1 << 9;                             // LED ON
//GPIOE->BSRR = 1 << 9 << 16;                       // LED OFF
//GPIOE->BRR = 1 << 9;                              // LED OFF

    if (SysTick_Config(SystemCoreClock / 1000))
    { 
    /* Capture error */ 
    while (1);
  }

    while(1)
    {
        GPIOE->BSRR = 1 << 8;   
        Delay(50);
        GPIOE->BRR = 1 << 8;
        Delay(50);
    }
}

void SysTick_Handler(void)
{
  TimingDelay_Decrement();
}

void Delay(__IO uint32_t nTime)
{
  TimingDelay = nTime;

  while(TimingDelay != 0);
}

void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  { 
    TimingDelay--;
  }

}

¿Por qué tengo que habilitar el reloj GPIOE? ¿Y cuál es la diferencia entre 1UL << 21 y 1 << 21 ?

10voto

shash Puntos 668

En los STM32, todos los periféricos están desactivados por defecto y no reciben ninguna señal de reloj. Esto ahorra un montón de energía (y te obliga a pensar en las interacciones entre los pines como el código). Si quieres usar GPIOE, tienes que decirle al STM32 que habilite su reloj.

1UL << 21 cambia un unsigned long valor de 1 21 bits a la izquierda. 1 << 21 desplaza algún número valorado en 1, pero es algún tipo por defecto, que puede o no ser unsigned long y no sabes necesariamente la amplitud de tu sistema por defecto. Variará según la plataforma y el compilador. De hecho, UL puede variar por plataforma y compilador también. Es mejor usar los typedefs de la biblioteca, que son cosas seguras.

(uint32_t)1 << 21 y (uint64_t)1 << 21 son inequívocos.

5voto

Matt McMinn Puntos 6067

El enlace que has facilitado ya tenía suficiente información. Pues bien, a diferencia de la dureza, que denota únicamente la resistencia al rayado, la tenacidad o dureza del diamante es de regular a buena.

Es decir, es fácilmente rompible con un martillo. La dureza del diamante es de unos 2,0 MPa, lo que es bueno comparado con otras piedras preciosas, pero pobre comparado con la mayoría de los materiales de ingeniería.

Así que si cojo un martillo y lo golpeo con fuerza, sí que se va a romper. El diamante es duro, estoy de acuerdo, pero no es irrompible.

Me enrollo un poco de los comentarios, una cosa interesante:

¿Un martillo normal golpeando a 10 km/s? Eso aún rompería todos los materiales químicamente unidos conocidos. - Dirk Bruere

3voto

Alex Puntos 1140

En aras de la legibilidad, y para reducir la probabilidad de errores, utilice macros en lugar de números mágicos.

stm32f30x.h contiene macros para (con suerte) todos los valores de los registros. Así que:

RCC->AHBENR  |=  ((1UL << 21) );                  // Enable GPIOE clock??
GPIOE->MODER |= (1 << 2*8);                       // PIN 9 as output

se puede escribir como:

RCC->AHBENR  |= RCC_AHBENR_GPIOEEN;    // Enable GPIOE clock.
GPIOE->MODER |= GPIO_MODER_MODER8_0;   // PIN 8 - not 9! - as output.

(De hecho, el comentario original era erróneo en este caso; el uso de una macro hace que esto sea más evidente).

Del mismo modo, el código de conmutación de pines podría escribirse como:

GPIOE->BSRR = GPIO_BSRR_BS_8;   
Delay(50);
GPIOE->BRR = GPIO_BRR_BR_8;
Delay(50);

Yendo más allá, GPIO_MODER_MODER8_0 no está del todo claro, así que podría añadir una macro propia:

#define GPIO_MODER_MODER8_OUT   GPIO_MODER_MODER8_0

Eso podría ser un poco cansado si estuvieras colocando muchos pines, por lo que podrías hacer:

#define GPIO_MODER_OUT(pin)     (((uint32_t) 1) << (2 * (pin)))

Además la línea anterior asume que esos bits en MODER ya eran 0x0 o 0x1. Si no podemos asumirlo, entonces tenemos que borrarlos primero:

GPIOE->MODER &= ~GPIO_MODER_MODER8;
GPIOE->MODER |= GPIO_MODER_OUT(8);

También:

Si las funciones declaradas en la parte superior del archivo no se utilizan en ninguna otra parte, declárelas static . Esto evita que se utilicen en cualquier otro archivo por error.

Si el compilador lo permite, main debe declararse como void , no devolviendo un int ya que nunca regresa.

Esto es una verdadera chapuza: TimingDelay es sólo un número normal; no se utiliza donde una representación hexadecimal es apropiada. Así que en TimingDelay_Decrement donde se compara con cero, utilice 0 no 0x00 . Esto también lo hace coherente con la comparación en Delay .

Si he entendido bien, __IO marca una variable como volatile y se utiliza, sospecho, para marcar los registros que se pueden leer y escribir. TimingDelay sí necesita ser volatile ya que se actualiza en una interrupción - pero me inclinaría por usar volatile en lugar de __IO , para indicar que no es un registro.

nTime no necesita ser volatile (o __IO ), ya que es sólo un parámetro normal de la función, pasado por valor, que se lee una vez.

1voto

Esto técnicamente debería pertenecer a revisión del código .

Mi única recomendación es que el enmascaramiento/desplazamiento de bits debe ser macros o funciones que describan lo que está pasando. Los comentarios están bien, pero no funcionan y, en última instancia, lo que digan los comentarios no significa nada; lo que cuenta es el código (y se desincronizarán). Haz que el código SEA los comentarios con descomposición funcional:

RCC->AHBENR  |=  ((1UL << 21) );  

se convierte en

enableGpioe() {
    RCC->AHBENR  |=  (1UL << 21);  
}

y esto

GPIOE->BSRR = 1 << 9; 

se convierte en

void setLEDStatus(LED led, Status status) {
     led = 1 << status;     // I don't know your struct members.
}

cuando

Led

y

Estado

son enums. Como mínimo, puede convertirlos en MACROS. Esto te aliviará de tener que recordar el enmascaramiento de bits correcto para hacer la tarea.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X