Introducción
La mayoría de los programas que se usan en los microcontroladores son hechos con librerías que permiten abstraernos del hardware, lo que permite acelerar el tiempo de desarrollo y hacernos la vida más fácil a los programadores.

A estas librerías se les llama HAL (hardware abstraction layer). En este caso para el microcontrolador que usaremos STM32F407VET6 estas librerías son proporcionadas por STMicroelectronics. Básicamente las librerías o también llamadas HAL drivers exponen una API (application programming interface) para que podamos comunicarnos con el hardware desde capas superiores.
En este articulo y en los siguientes no usaremos estas librerías, haremos la parte tediosa, que es la manipulación directa de los registros en el hardware. Ésto, con el fin de aprender más a fondo y entender como funciona un microcontrolador al desnudo.
Ambiente de Desarrollo
Para este ejemplo y los próximos utilizaremos el IDE (integrated development environment) Keil uVision 5 en su versión gratis, proporcionado por ARM. Se descarga de forma gratuita (aquí) después de llenar un formulario.
Necesitaremos para cargar el código a nuestra placa de desarrollo, un programador (hay placas de desarrollo que traen incluido su propio programador), puede ser un ST-LINK o un J-LINK, ambos nos servirán de igual forma.
A programar!
Para entender cada uno de los registros que utilizaremos en nuestro programa, tenemos que que tener a mano e ir leyendo el manual de referencia de nuestro microcontrolador. (aquí)
Ya teniendo Keil vVision 5 instalado en nuestro computador, lo abrimos y nos aparecerá una ventana llamada Pack Installer, que nos muestra todos los Packs instalados. Si no se nos abre automáticamente hacemos click en el ícono correspondiente.

En el cuadro Search, escribimos nuestro microcontrolador e installamos el pack Keil::STM32F4xx_DFP (Device Family Pack) que tienen todo lo necesario para poder programar nuestro microcontrolador.

Cuando esto ya esté instalado, procedemos a crear nuestro nuevo proyecto. Escogemos la carpeta y el nombre que que le pondremos al proyecto, puedes elegir el nombre que desees, lo ideal es que te ayude a saber de qué trata tú programa. En mi caso lo llamé “stm32f4_blinky”.


Escogemos el microcontrolador que necesitamos, que es el STM32F407VETx y damos a OK. Se nos abre la pestaña Manage Run-Time Environment en la que escogemos los componentes de software que se nos agregarán al proyecto que son CORE y Startup(imagen de arriba).
Puedes cambiar los nombres de los elementos de tu proyecto, pero eso ya es opcional. Hacemos click derecho en la carpeta app o Source Group 1 si no le cambiaste el nombre y le damos click a Add New Item Group …

Se nos abre la ventana para escoger el archivo que queremos crear. Escogemos C File (.c) y lo llamamos main.c, este será el archivo que contenga todo nuestro código.

Ahora que tenemos nuestro archivo main.c agregamos la librería principal stm32f4xx.h, en esta librería se encuentran definidos todos los registros necesarios para nuestro proyecto. La agregamos haciendo click con el botón derecho sobre el archivo en blanco y seleccionando Insert ‘#include file’ > stm32f4xx.h .

Todo lo anterior se hace para todos los proyectos, por lo que en los siguientes no se repetirá y se procederá con la pura parte del código. ( 🙂 )
El código que se muestra a continuación lo que hace es “blinkear” (prender y apagar) un led cada 100 ms (mili segundos), para esto usaremos el que dispone la placa de desarrollo en el pin PA7.
Como adelanto dejaremos el código completo y funcional.
#include "stm32f4xx.h" // Device header
void delay_ms(int delay);
int main(void)
{
RCC->AHB1ENR |= 1; // enable GPIOA clock
GPIOA->MODER |= 0x4000; // set GPIO PA7 as output;
// 0b 0100 0000 0000 0000
while(1)
{
GPIOA->BSRR |= 0x800000; // reset PA7 (BR7 of BSRR) (on STM32F4VE board is HIGH)
delay_ms(100);
GPIOA->BSRR |= 0x80; // set PA7 (BS7 of BSRR) (on STM32F4VE board is LOW)
delay_ms(100);
}
}
//pseudo-delay without accuracy (for now!)
void delay_ms(int delay)
{
int i;
for(; delay>0; delay--)
{
for(i=0; i<3000; i++);
}
}
Lo dejaremos hasta acá de momento. Para la segunda parte explicaré cada parte del código, en especial cada uno de los registros utilizados.