Programando microcontrolador ARM: 4 - Primer programa, blink con registros de memoria (stm32f103c8)

Este primer ejercicio consiste en aprender y practicar el comportamiento mas básico que podemos obtener en nuestro ARM. Y es el punto de partida para posteriormente ampliar nuestros conocimientos sobre la programación de un microcontrolador ARM y así poder hacer cosas más complejas.


STM32f103
A través de los registros de memoria encenderemos y apagaremos un LED. Para ello usaremos los pines digitales que disponemos en nuestro microcontrolador.


¿Qué son los registros de memoria?

Todos los microcontroladores tienen una porción de memoria reservada exclusivamente para el funcionamiento del microcontrolador. Estas porciones de memoria se denominan registros.

El microcontrolador observará el estado y la información de esas cedas de memoria para funcionar de un modo u otro. El fabricante a través de los documentos que nos facilita nos indica todos los registros que tenemos disponibles, ademas de como escribir en ellos y como usarlos. Necesitamos tener esta información debido a que no todos los microcontroladores tienen las mismas posiciones de memoria ni se configuran de igual manera.

Por ejemplo, la funcionalidad de todos los pines (GPIO), de nuestro micro funcionan en base a la información de los registros.

Nosotros podemos escribir directamente en estos registros y modificarlos a nuestro antojo. Y esto es lo que veremos, cómo escribir información en los registros.


Blink


En este caso lo primero que vamos a hacer es programar nuestro microcontrolador de tal manera que nos permita hacer parpadear un LED. Usaremos el LED que viene en nuestra placa, pero podemos usar un LED externo usando cualquier pin.

Para poder usar nuestro pin debemos realizar una serie de pasos previos.
  1. Iniciar el reloj para el puerto correspondiente a nuestro pin.
  2. Configurar el comportamiento de nuestro pin.
  3. Poner en HIGH o LOW nuestro pin.

1. Iniciar el reloj para el puerto correspondiente a nuestro pin.

En nuestra placa (Blue pill), el led está conectado al pin PC13. Esto corresponde al pin 13 del puerto C. Los puertos son un conjunto de pines.

Sabiendo esto necesitamos activar el reloj para el puerto C. Es muy importante tener presente el diagrama de memoria de nuestro microcontrolador.
Arquitectura del sitema
En el podemos encontrar el reset and clock control (RCC) y observamos que el GPIOC se encuentra en la sección APB2.

Sabiendo esto en el index vamos a buscar donde encontrar la informacion para configurar esos registros.



Vamos a la pagina y el fabricante nos explica la disposición del registro.


Esto quiere decir que necesitamos escribir un 1 en el bit 4 de este registro para activar el reloj del puerto C.

Por lo tanto tenemos que escribir el siguiente numero binario en este registro.

Configuración registro
0000 0000 0000 0000 0000 0000 0001 0000

Para escribir directamente en el registro necesitamos escribir lo siguiente:
RCC -> APB2ENR |= 0x00000010;

Además necesitamos crear una función llamada Delay que nos permitirá pausar la ejecución durante un determinado tiempo.


2. Configurar el comportamiento de nuestro pin.

En cuanto a se refiere a los pines GPIO pueden ser configurados de diferente manera. Del mismo modo que antes, el fabricante nos explica como funcionan los pines de nuestro microcontrolador.  Nos indica hasta 8 manera diferentes de funcionar. 

  1. Input floating
  2. Input pull-up
  3. Input-pull-down
  4. Analog
  5. Output open-drain
  6. Output push-pull
  7. Alternate function push-pull
  8. Alternate function open-drain
En nuestro caso nos interesa Output push-pull. Para comprender más como funciona esta configuración podemos estudiar un cuadro que nos facilita el fabricante. 

Estructura GPIO

Para configurar nuestro pin tenemos que modificar el registro que hace referencia al funcionamiento de nuestro pin. En nuestro caso este registro es GPIOC_CRH.
En la documentación encontramos el siguiente cuadro explicativo.

Información registros dada por el fabricante 

Aquí podemos ver que necesitamos modificar los bites 23 y 23 que hacen referencia a CNF13, aqui tendremos que poner dos ceros (00), de tal manera que lo configuramos como General purpose output push-pull. Por otro lado tenemos que configurar los pines 21 y 22 que hacen referencia a MODE13, aqui vamos  aponer dos unos (11) de tal manera que configuramos el pin a la mayor velocidad, 50 MHz.

Por lo tanto el registro que tenemos que escribir queda de la siguiente manera.

Configuración registro pin 13
0000 0000 0011 0000 0000 0000 0000 0000

Para escribir directamente en el registro necesitamos escribir lo siguiente:
GPIOC-> CRH |= 0x00300000;

Por el momento ya estamos listos para usar nuestro pin, de tal manera que de momento el código queda de al siguiente manera.
int main void ){
    // Activa el reloj para el puerto C
    RCC -> APB2ENR |= 0x00000010;
    // Configura el pin 13 como push-pull y a una velocidad de 50 MHZ
    GPIOC-> CRH |= 0x00300000;
    // Funcion que se repertira contunuadamente
    while(1){
    }
}


Antes de continuar con el tema de los registros para poder poner nuestro pin HIGH or LOW vamos a crear una función Delay, esta función nos va a permitir pausar la ejecución durante un determinado tiempo.

Primeramente tenemos que declara la función al inicio de nuestro programa.
void delay ( long cycles );

A continuación ya podemos crear nuestra función y así usarla en cualquier momento. Vamos a crear una función a la que se le pasa un numero y en función de ese numero el código espera el numero de ciclos deseado.

void delay ( long cycles ){
    while ( cycles > 0 ){
        cycles--;
    }
}


3. Poner en HIGH o LOW nuestro pin.

Ya solo nos queda activar y desactivar nuestro pin. O lo que es lo mismo, ponerlo en HIGH o LOW. HIGH corresponde a poner el pin a 3.3V y LOW a 0V.


Igual que antes todo lo vamos a realizar a través de registros. Para ello vamos a usar el registro BSRR que corresponde a las siglas de bit set/reset register. Este registro nos permite acceder a todos los pines y hacer SET, que correspondería a poner el pin en HIGH y RESET que corresponde a poner el pin el LOW. Igual que antes, en el manual de referencia encontramos toda al información necesaria.



Set/reset regitro


Como podemos ver es un registro de 32 bits (0-32), los 16 primeros, del 0 al 15, corresponden al SET, uno por pin. Y los 16 siguientes, del 16 al 31, corresponden al RESET. Muy importante prestar atención a la nota que nos explica que al poner un 1 en ambos, tanto set como reset, el set tiene prioridad.


Para hacer SET.
// SET: reset 0000 0000 0000 0000 | set 0010 0000 0000 0000
GPIOC -> BSRR |= 0x00002000;

Para hacer RESET
// RESET: reset 0010 0000 0000 0000 | set 0000 0000 0000 0000
GPIOC -> BSRR |= 0x20000000;

Nuestro programa completo queda de la siguiente manera.
#include "stm32f10x.h"

void delay ( long cycles );

void delay ( long cycles ){
    while ( cycles > 0) {
        cycles--;
    }
}
int main void ){
    // Activa el reloj para el puerto C
    RCC -> APB2ENR |= 0x00000010;
    // Configura el pin 13 como push-pull y a una velocidad de 50 MHZ
    GPIOC-> CRH |= 0x00300000;
    // Funcion que se repertira contunuadamente
    while (1){
        // SET: reset 0000 0000 0000 0000 | set 0010 0000 0000 0000
        GPIOC -> BSRR |= 0x00002000;
        delay(5000000); // ciclos de delay

        // RESET: reset 0010 0000 0000 0000 | set 0000 0000 0000 0000
        GPIOC -> BSRR |= 0x20000000;
        delay(5000000); // ciclos de delay
    }
}

Comentarios

  1. buenas! para cargar el programa con el STLink V2 hay que poner la placa en algún modo del bootloader? Estoy tratando de cargar un programa pero no logro que me lo cargue.
    También es cierto que ayer le cargue el bootloader de STM32duino y no sé si ya me lo habré cargado! jajaj

    ResponderEliminar
    Respuestas
    1. Hola,

      Para todas estas practicas no necesitamos ningún bootloader mas que el que viene por defecto, en el micro.

      Haciendo referencia a esta entrada de STM32duino: http://wiki.stm32duino.com/index.php?title=Bootloader

      Aunque pongas un bootloader, el que viene por defecto está guardado en una porción de memoria de solo lectura y no puede ser modificado ni eliminado.

      Al final hace referencia a este documento,que puede serte utíl: http://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf

      Por lo que entiendo tienes que tener la posibilidad de "limpiar" por completo el micro.

      Puedes probar a eliminar toda la memoria del micro. Puedes hacerlo tanto en CooCox CoIDE, Flash -> Flash Erase.

      O también puede probar con el programa del ST-Link Utility en el icono de la goma de borrar (Full chip erase) o en Tarjer -> Erase chip

      Cuéntame si lo consigues o si consigues alguna solución.

      Eliminar
    2. Pues la cosa es que el programa que hago (el que has puesto en el blog) me compila, y cuando le doy a cargar me lo carga sin problema, pero el programa no se ejecuta, al menos el pin no hace el blink. Si lo cargo desde el arduino si que me funciona sin ningún problema, así que me da que va a ser algo de software, estoy cargándolo con atom y usando platformio

      Eliminar
    3. Vale, he podido borrar la flash entera, pero me sigue pasando que al cargar el programa no se ejecuta en el micro. Creo que va a ser un problema del IDE que uso, pero no llego a entender el problema :(

      Eliminar
    4. Vale, si se te cargan sin problemas puede ser que no se te esté reseteando. Prueba a quitar la alimentación y reconectarlo.

      Eliminar
    5. nop, eso tampoco es, ya o he hecho varias veces dándole al reset de la placa, quitando alimentación... jajaj estoy ya desesperado :P

      Eliminar
    6. joe, puesprueba con diferentes configuraciones de los pines de boot, incluso con ninguno puesto. O ya prueba con CoIDE que se instala en un momento y se configura rápido.

      Eliminar
    7. Pues acabo de probar con el CooCox Ido y sin ningún problema la verdad se ha programado a la primera y funciona bien, así que es por tema del IDE que estoy usando, seguiré investigando y te diré! gracias por la ayuda! :D

      Eliminar
    8. De nada! Me alegro. CooCox es muy potente, lo de que vengan las bibliotecas directamente desde mi punto de vista es muy bueno. Yo seguiré poniendo aquí más tutoriales. Los siguientes serán un poco mas de gpio, mas de salidas, botones y tal.

      Eliminar
    9. Si ya veo, lo malo que solo hay para windows :( Voy a ver si me puedo instalar el Eclipse con el ARm con eso y con el STM32Cube MX para generar al proyecto, a ver si consigo hacerlo funcionar!

      Eliminar

Publicar un comentario

Entradas populares de este blog

ARDUINO desde cero: 5 - Comunicación Serial

Evolucionando talado de columna: 1 - Guía laser, planificación y diseño