
0. Antes de leer el artículo
Este artículo tiene los siguientes objetivos:
- mostrar cómo trabajar específicamente con este tablero;
- muestra el enfoque mediante el cual puede escribir un programa LED parpadeante, basándose únicamente en la documentación y la lógica;
- presentar el material en un lenguaje que sea comprensible para una persona que no esté familiarizada con los microcontroladores.
El código resultará minimalista en términos de uso de archivos adicionales: no incluiremos un solo archivo, excepto aquellos que son necesarios para construir un firmware vacío pero válido. Es decir basado en el código de firmware, que funciona, pero no hace nada útil.
Necesitaremos la siguiente documentación:
- Hoja de datos STM32F030x4 (uso el documento de enero de 2017 DocID024849 Rev 3);
- RM0360 Manual de referencia STM32F030x4 / x6 / x8 / xC (uso el documento de abril de 2017 DocID025023 Rev 4);
- placa de circuito
Puede descargar estos documentos desde la
nube .
El temporizador en el artículo
no será considerado y
no estará involucrado en el código.
El programador ST-LINK
no fue utilizado. Para trabajar con la placa, se utilizó un adaptador USB-COM (RS232 basado en PL2303HX), que emula un puerto COM.
Todo se recopiló en una máquina virtual Windows XP Professional 2002 SP3 que se ejecuta a través de VirtualBox versión 5.2.22r126460 en un host Windows X.
1. Instalación del controlador para el adaptador USB-COM
Windows no es de ayuda, descargue desde el sitio oficial
Prolific (el primer enlace a la solicitud "controlador prolífico" en Google) controlador USB a UART / Serial / Printer
PL2303 Controlador de Windows (necesita el
controlador estándar ) O puedes descargar desde mi
nube .
Instale el controlador, reinicie y vea el nuevo puerto COM.
Captura de pantalla con el nombre del instalador y el nuevo puerto COM La configuración del puerto dejó el estándar. Puede cambiar el número de puerto COM a su discreción. En mi experiencia, solo una vez en mi vida he visto un programa ver solo los primeros 4 puertos COM, si no me equivoco, era algún tipo de terminal Bluetooth en Windows.
Configuraciones de puerto COM 2. Llenado de firmware dentro y fuera del tablero
2.0 Utilidad de descarga para trabajar con la placa
Descargamos la utilidad
FLASHER-STM32 del sitio web de
STM (en la descripción se llama STM32 Flash loader demostrador (UM0462)), tendrá que registrarse para esto, pero no da miedo; al final, soltaremos el archivo zip con el instalador; Siguiente-> Siguiente-> Siguiente ... y todo está instalado. Para mayor comodidad, creo un acceso directo a esta aplicación en la carpeta de trabajo.
Aquí está la utilidad (captura de pantalla del sitio) De manera predeterminada, la ruta a la utilidad
C: Archivos de programa \ STMicroelectronics \ Software \ Flash Loader Demo \ STMFlashLoader Demo.exe .
2.1 matiz de arranque
Hay un puente BOOT en el tablero.
- Cuando el puente está cerrado , el microcontrolador cargará las instrucciones de su memoria (es decir, un programa escrito por un programador).
- Cuando el puente está abierto , el microcontrolador recibirá información sobre las líneas RX y TX, es decir. Será flasheado desde el puerto COM (desde el adaptador en mi caso).
2.2 Configurar la utilidad

Ejecute esta aplicación, en realidad es la más simple (contiene un mínimo de configuraciones). En la primera ventana, seleccione:
- interfaz (tengo COM-3);
- la velocidad con la cual la computadora y el microcontrolador se comunicarán (en mi humilde opinión, valor normal 9600);
- el número de bits de datos (por alguna razón, esta ventana no está disponible para mí, pero hasta ahora esto no es importante);
- paridad (no tengo paridad, es decir, ninguna);
- echo (tengo apagado);
- tiempo de espera (tengo 10 segundos).
Haga clic en Siguiente, y si todo está en orden, veremos una luz verde y "El objetivo es legible"; Si vemos una luz roja, la computadora no podría conectarse.
El objetivo es legible si el microcontrolador se detecta con éxito El orden de los pasos que siempre ayudan:
- En primer lugar, debe verificar si el puente BOOT en el tablero está cerrado.
- En segundo lugar, en cualquier caso, apague el microcontrolador y preferiblemente las líneas TX y RX que vienen del adaptador a la placa (no puede desconectar la tierra).
- En tercer lugar, en el programa, presione Volver al final, es decir a la primera página, o incluso cerrarla y reiniciarla (en general, a veces se congela). Es importante comenzar siempre desde la primera página antes de cada conexión a la placa a través de este programa.
- Cuarto, recoja los cables del adaptador a la placa e intente conectarse nuevamente en el programa (¡asegúrese desde la primera página!).
Si todo lo demás falla, puede intentar apagar todo, reiniciar la computadora e intentar volver a conectarse a la placa.
Porque Trabajo a través de una máquina virtual, tengo que volver a conectar el adaptador USB-COM varias veces para que la máquina virtual lo detecte y la máquina host no tenga tiempo para instalar controladores dañados.
Otra opción que encontré trabajando mientras escribía este artículo es presionar un botón en el tablero en lugar de tirar constantemente de los cables. Sin embargo, deberá cerrar y abrir el puente BOOT en cualquier caso. Esta opción funciona porque el botón se coloca al pie del restablecimiento
NRST externo.
En la siguiente ventana, seleccione el dispositivo de destino. Por cierto, a veces aquí puede ver (tal vez un error) el dispositivo izquierdo en general, por ejemplo, en lugar de STM32, vea STM8: en algún lugar hubo algún tipo de falla, el procedimiento de tratamiento se describe anteriormente. Por lo tanto, en este paso no puede apresurarse a hacer clic en Siguiente, pero siempre preste atención al hecho de que el dispositivo deseado está seleccionado en Target.
Selección de dispositivo de destino ¿Cómo determinar qué dispositivo tenemos? - miramos el chip y reescribimos todo lo que está escrito en él. Abrimos la
hoja de
datos en nuestro chip, la sección
Información de pedido describe qué carta es responsable de qué. En mi caso es:


Selecciono mi chip (16K) en Target y sigo adelante. Se ofrece una opción de 4 acciones con un chip:
- borrar memoria (completa o seleccionar un área específica);
- escribir firmware en el dispositivo;
- leer el firmware del dispositivo;
- activar / desactivar la protección contra escritura o lectura.
2.3 Leer firmware de la placa
Cuando conecté la placa por primera vez, decidí mantener el firmware original, una especie de respaldo; lo haremos ahora. Será necesario indicar dónde guardar este firmware y qué páginas de memoria guardar, también se propone utilizar un formato de archivo
hexadecimal ,
bin o
s19 para
elegir .
Seleccione páginas de memoria para leer Si solo carga el firmware en la placa o lee el firmware desde la placa, entonces no hay diferencia entre estos formatos de archivo. La siguiente es una página de progreso, en la que a veces el proceso se congela en un 99% durante mucho tiempo (no necesariamente 99), pero después de unos segundos supuestamente se completa con éxito; de hecho, después de eso, la placa no dio el comportamiento que correspondería al firmware cargado. En pocas palabras, debe volver a conectar todo y volver a llenar el firmware, no hay nada crítico al respecto.
El archivo de firmware se guardó y, en el futuro, se puede cargar en la placa.
Sin embargo, si la protección contra lectura está instalada, el firmware no se puede leer.
2.4 Destellando el tablero
Ahora complete el archivo de firmware, cuya escritura del código fuente se proporciona a continuación. Mirando hacia el futuro, diré que subiremos archivos
bin y
hexadecimales , porque el entorno de desarrollo los emitirá. Las configuraciones adicionales para
s19 y archivos
hexadecimales son idénticas; a diferencia de ellos, en el archivo
bin , puede seleccionar la dirección desde la que se grabará el firmware, de forma predeterminada en la utilidad es 8000000 (adecuado para nosotros).
Antes de grabar, puede borrar la memoria flash del microcontrolador eligiendo una de tres opciones:
- Borre las páginas necesarias (borre las secciones de memoria necesarias);
- Sin borrado (sin purificación);
- Borrado global (limpieza completa).
De hecho, la limpieza es el proceso de escribir ceros en la memoria.
Todavía hay bytes opcionales, pero hasta ahora no puedes tocarlos. Haga clic en Siguiente, espere a que se complete el proceso y listo.
En caso de que desee grabar mi firmware, puede encontrarlo en la nube, el archivo
blink.bin . Al usar este firmware, el LED incorporado que parpadea desde el pie PA4 debería parpadear.
3. Redacción de códigos
3.0 Instalación del entorno de desarrollo CooCox CoIDE
Puede descargar el IDE desde
SoftPedia.com , anteriormente era posible descargarlo desde el sitio web de STM y desde el sitio del propio IDE, pero como el IDE ya no era compatible, se ha vuelto imposible. No hay nada crítico en que el IDE ya no sea compatible, no, porque para escribir código, lo principal es el compilador. Descargué ambas versiones, pero uso la versión 1.7.8.
El primer lanzamiento del entorno está bien descrito
aquí , Siguiente-> Siguiente-> Siguiente ... y nada complicado. Solo agregaré que primero es mejor crear un proyecto y luego todo lo demás.
Y, sin embargo, si perdió la pestaña Repositorio, puede encontrarla en el menú
Ver -> Repositorio .
Puede descargar herramientas (compilador) para el entorno
aquí o pedirle a Google "herramientas gnu para armar"; Descargué una opción que tiene sha1.exe al final.
3.1 Marco fuente
Entonces, el proyecto ha sido creado, el chip ha sido seleccionado, ahora agregaremos el conjunto mínimo de fuentes al proyecto, sin el cual no podrá vivir en absoluto.
Así es como debería verse el proyecto cuando se acaba de crear, es decir solo está el archivo main.c principal y nada más Seleccione CMSIS BOOT y el entorno
seleccionará automáticamente
M0 Cmsis Core , porque las dependencias requieren esto.
Ahora tenemos el conjunto mínimo de fuentes Ensamble el proyecto (icono de construcción o tecla F7). Por razones desconocidas para mí, el archivo hexadecimal no se recopiló (hay una advertencia en la consola); Reinstalé el IDE y el compilador varias veces, volví a crear el proyecto, pero por alguna razón ese resultado en la máquina virtual; en otra computadora (no virtual, pero real) todo es uno a uno y la salida funciona de forma hexadecimal. Afortunadamente, hay bin.
El proyecto fue ensamblado exitosamente Le aconsejo que preste atención al tamaño del archivo, se puede ver al final de la salida en la consola, o puede verlo por medios estándar (aquí, por cierto, puede ver que el hex está vacío); Al mismo tiempo, esta captura de pantalla muestra que los archivos de firmware están en la carpeta del proyecto, luego Debug / bin / Aunque el código no hace nada, lo subo al tablero para asegurarme de que pueda cargarlo (lo cual, por ejemplo, la utilidad no lo rechaza). Aconsejo al lector que haga esto. Si no funciona, inténtalo una y otra vez y escribe comentarios.
3.2 Algoritmo de dedo
Para comenzar, bosquejamos un algoritmo de cómo, desde un punto de vista humano, el microcontrolador parpadeará un LED. Y para esto un pequeño razonamiento.
Cada equipo funciona debido a la energía almacenada, por ejemplo, algunos motores pueden funcionar con diferentes tipos de combustible, pero para esto el motor debe ajustarse al tipo de combustible con el que vamos a alimentarlo. Del mismo modo, el microcontrolador debe ajustarse (sintonizarse) para la fuente de energía; este será el
primer bloque del algoritmo.
Razonamos más. La computadora de escritorio tiene un monitor, parlantes, teclado, mouse ... y puede ver que algunos dispositivos nos brindan información, y con la ayuda de otros le brindamos información a la computadora, pero todos están conectados a una caja común a todos ellos (la unidad del sistema). Puede adivinar que el microcontrolador puede recibir y proporcionar información, lo que significa que sus patas pueden recibir una señal o emitir una señal; este será el
siguiente bloque del algoritmo.
Luego, el microcontrolador debe encender el LED, esperar un momento, apagar el LED, esperar un momento y encenderlo, esperar, apagar ...
Como resultado, el algoritmo se verá así

El propósito de este diagrama de flujo es mostrar claramente lo que hace el algoritmo; En primer lugar, el esquema está escrito para usted, por lo que todos son libres de escribirlo / dibujarlo como quieran (para sí mismos). Creo que el esquema debe ser tan simple, legible e intuitivo como sea posible, para tener un alto nivel de abstracción.
De acuerdo con este algoritmo, escribiremos código.
3.3 Trabajando con documentación
Recomiendo leer esta parte del artículo con el archivo abierto
stm32f0xx.h , que se encuentra en la carpeta
cmsis_boot de nuestro proyecto, y la documentación abierta.
3.3.1 Seleccionar una fuente de reloj
Primero, debe proporcionar energía al microcontrolador. El microcontrolador recibe 5 voltios del adaptador (medido con un multímetro), pero surge la pregunta de "a qué frecuencia funciona el microcontrolador", porque se sabe que la electrónica funciona a diferentes frecuencias. Primero, abra la
hoja de datos , en el contenido puede ver dos secciones que son relevantes en significado:
administración de energía ,
relojes y arranque . El primero es sobre los modos de voltaje y baja potencia. La segunda sección esconde lo que nos interesa en este momento. Ya en la primera oración dice "el oscilador interno RC de 8 MHz se selecciona como reloj predeterminado de la CPU al reiniciar", lo que significa que,
después de reiniciar el MC, la cadena interna de RC de 8 MHz se selecciona como la
fuente principal del reloj .
Luego viene un esquema de árbol de reloj incomprensible, que consideraremos un poco más adelante.
Hablando estrictamente, puede confiar en la frase "por defecto después de restablecer el MK ..." y leer esta parte del artículo en diagonal.
Ahora debe distraerse con la placa y buscar el LED interno. Sé que los diodos en los circuitos se denotan por
D1 ,
D2 ..., es decir
D == diodo , en mi placa cerca de la resistencia
R7 está el diodo
D1 .
Quizás, después de haber examinado cuidadosamente la placa, puede rastrear a qué pata está conectado el diodo, pero pasaré a la placa de circuito. Desafortunadamente, los elementos de la placa no coinciden exactamente con los elementos del circuito en su ubicación; pero me alegro de haber encontrado ese esquema en Internet (de lo contrario, no pude encontrar nada durante mucho tiempo).

En el diagrama vemos que el cátodo del diodo está conectado a tierra a través del puente
J2 , y el ánodo está conectado al pin
PA4 a través de una resistencia.
PA4 significa la cuarta salida del puerto
A , lo que significa que para encender y apagar el LED, será necesario suministrar voltaje a la salida de
PA4 .
A continuación, debe determinar cómo aplicar voltaje a esta salida. Esto no fue intuitivo para mí en absoluto, y durante mucho tiempo revisé la documentación a lo largo y ancho hasta que encontré el
diagrama de Bloques en la sección
Descripción al comienzo de la hoja de datos. Y en él vi la preciada pista
PA [15: 0] <=> puerto GPIO A <=> decodificador AHB <=> Matriz de bus <=> Cortex-M0 , es decir El puerto
A es un puerto de E / S de propósito general y está conectado al bus
AHB .
Diagrama de bloques(Se puede hacer clic en la imagen)

Observo que en electrónica es habitual dividir las salidas del microcontrolador en puertos, y generalmente el puerto tiene 16 salidas. El diagrama muestra que los puertos
A ,
B y
C tienen solo 16, pero los puertos
D y
F tienen menos (menos de 16 pines pueden ser, más - no).
Volvamos al esquema del
árbol del
reloj y encontremos la salida firmada por
AHB . Averiguaremos con qué frecuencia funciona esta salida. Para el
AHB está la señal
HCLK , que sale del divisor
HPRE . Este divisor recibe la señal
SYSCLK del interruptor
SW . ¿Cuál de las señales en la entrada de
SW se usará cuando
SYSCLK se
configura mediante programación ? Luego lo configuraremos en el código. La elección se ofrece:
- HSI : una señal de un generador interno de alta frecuencia, es producida por un resonador de cuarzo de 8 MHz, que solde antes de trabajar con esta placa;
- PLLCLK - señal del multiplicador de frecuencia PLLMUL ;
- HSE - señal de un generador externo de alta frecuencia.
Cualquier opción es adecuada para nuestra tarea, sugiero elegir la más simple y asequible:
HSI .
Entraremos en el
Manual de referencia y abriremos la sección
7 Restablecimiento y control del reloj (RCC) , específicamente
7.2.6 Selección del reloj del sistema , donde una vez más nos encontramos con una redacción similar que se encuentra en la hoja de datos: "después de un restablecimiento del sistema, el oscilador
HSI se selecciona como sistema reloj "- es decir ni siquiera tenemos que hacer nada, MK comenzará con
HSI .
Para asegurarme de que MK realmente funcione desde esta fuente, escribiré esto explícitamente en el programa; Desplácese a los registros responsables de restablecer y marcar (sección
7.4 Registros RCC ). El primer registro descrito en la documentación es el
registro de control del reloj (RCC_CR) ; A continuación se muestra una descripción de los bits, que es responsable de qué.
Registro de control del reloj Estamos interesados en el
bit cero
HSION , que es responsable de encender el resonador (
0 - apagado,
1 - encendido).
Por lo tanto, será necesario escribir uno en el registro
RCC_CR . (cero bit es uno, o 2
0 = 1).
Ahora encontramos en el archivo
stm32f0xx.h la definición de
RCC (
#define RCC ).
Como puede ver, esta es la estructura ubicada en
RCC_BASE ; dirección
0x40021000 , si expande todas las
definiciones , la misma dirección se puede ver en el
Manual de referencia en la sección
2.2.2 Mapa de memoria y direcciones de límite de registro y en la hoja de datos en la sección
5 Mapa de memoria (área
AHB ).
Para escribir una unidad para habilitar
HSI en el registro
CR de bloque
RCC , necesita una línea de código
RCC->CR |= 0x1;
3.3.2 Ajuste de las piernas
Enviar una señal a la pata del microcontrolador para encender el LED y detener la señal para que el LED se apague son acciones simples y, por lo tanto, esto se refiere a las funciones
GPIO (puertos de entrada-salida de propósito general).
Por defecto, las patas MK no están conectadas, es decir El resultado es la incertidumbre. Es necesario conectar un puerto, cuya pata alimentará el LED. Anteriormente, determinamos que los puertos
GPIO están conectados al bus
AHB : debe conectar este bus. Continuando con la sección
7.4 Registros RCC (
registros de control de control y restablecimiento), encontramos la sección
7.4.6 Registro de habilitación de reloj periférico AHB (
RCC_AHBENR ,
registro de habilitación de reloj de bus
AHB ). Anteriormente, determiné que mi LED está conectado a la pata
PA4 ; en consecuencia, necesito escribir una unidad en el bit 17 del registro para conectar el puerto
A.Registro de habilitación de reloj periférico AHB En consecuencia, el código debe ser
RCC->AHBENR |= (1 << 17);
o, que es lo mismo
RCC->AHBENR |= 0x20000;
ya sea usando el archivo
#define stm32f0xx.h write
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
Hemos alimentado el puerto
A , ahora debemos informarle a MK que
PA4 funcionará en la
salida : leeremos la sección
8 E / S de propósito general (GPIO) ; la introducción de la sección ya dice "Cada puerto de E / S de propósito general tiene cuatro registros de configuración de 32 bits (
GPIOx_MODER ,
GPIOx_OTYPER ,
GPIOx_OSPEEDR y
GPIOx_PUPDR ), dos registros de datos de 32 bits (
GPIOx_IDR y
GPIOx_ODR ) ..." -
para cada GPIO Hay 4 registros de sintonización y 2 registros de datos en el puerto : esto es lo que necesitamos (configurar el puerto
A , o más bien la salida
PA4 , y periódicamente enviarle
0 y
1 ). Para una mejor comprensión (teoría) de lo que está sucediendo, puede leer esta sección, pero me desplazo hacia la sección
8.4 Registros GPIO y configuro el puerto de acuerdo con las descripciones.
- modo puerto - salir. De acuerdo con la documentación, es necesario escribir 01 en el área correspondiente ( MODER4 ) del registro correspondiente ( GPIOA_MODER ), es decir bits 9 y 8 : en el noveno bit debe ser cero, en la octava unidad:
GPIOA->MODER |= (1 << 8); //
GPIOA->MODER |= 0x100; //
GPIOA->MODER |= GPIO_MODER_MODER4_0;
Registro de modo de puerto GPIO
- tipo de salida. Honestamente, todavía no he descubierto completamente los circuitos de este caso (lo entenderé, volveré a leer los foros nuevamente, etc.), pero estudiar otros recursos sobre la configuración de la salida MK, así como la lógica y la intuición, sugiere que debería haber un impulso -pull y luego debe ser pull-up . En cualquier caso, el código está escrito, todo funciona y no se quema nada. Existe un riesgo real de quemarse si selecciona el tipo de drenaje abierto y cortocircuita esta salida con otro dispositivo, como Esta es una salida abierta y no está protegida por nada. Además, tenemos una resistencia limitadora de corriente frente al diodo; ciertamente no arderá aquí.
Siguiendo la documentación, es necesario escribir cero en el cuarto bit; la documentación también establece que después del reinicio habrá cero.
GPIOA->OTYPER &= ~(1 << 4); //
GPIOA->OTYPER &= ~0x10; //
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_4;
Registro de tipo de salida de puerto GPIO
- velocidad de salida. En nuestro caso, no importa, pero en aras de la fidelidad escribiré aquí cero.
GPIOA->OSPEEDR &= ~(1 << 8); //
GPIOA->OSPEEDR &= ~0x100; //
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR4_0;
Registro de velocidad de salida del puerto GPIO
- Un ascensor . Porque la salida alimentará el LED, debe subirlo a la potencia, es decir pull-up
Es necesario apretar el cuarto pin del puerto A ; la documentación dice que para esto es necesario escribir cero y uno en 9 y 8 bits, respectivamente.
GPIOA->PUPDR |= (1 << 8); //
GPIOA->PUPDR |= 0x100; //
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR4_0;
Registro desplegable / desplegable de puertos GPIO
3.3.3 LED encendido / apagado y retraso
Anteriormente leímos que cada puerto tiene registros, incluidos los registros de datos
IDR y
ODR , registros de datos de entrada y salida, respectivamente. Ceros lógicos y unos en el tramo MK: ¿son estos datos? - Sí, datos. Los datos pueden provenir del exterior del microcontrolador (
entrada ) y salir del microcontrolador e ir a otro dispositivo (
salida ). La unidad en la pata MK es la presencia de un nivel de alto voltaje, es decir Si lleva uno a la salida, habrá voltaje, y este LED puede alimentar nuestro LED. La salida de una unidad a la pata del microcontrolador es algo más que escribir esta unidad en el registro de salida
ODR .
Registro de datos de salida del puerto GPIO De acuerdo con la documentación, vemos que para cada puerto (
A ,
B ,
C ,
D ,
F ) hay un registro de 32 bits, sin embargo. el puerto no puede tener más de 16 pines, entonces solo se usan los primeros 16 bits del registro. Cada bit corresponde a un número de puerto (pin). Para generar una unidad en el tramo
PA4 , es necesario escribir una unidad en el cuarto bit, para generar un cero: escriba un cero en el cuarto bit, es decir eliminar el voltaje de la salida.

El código para encender el LED se verá así
GPIOA->ODR |= (1 << 4); //
GPIOA->ODR |= 0x10; //
GPIOA->ODR |= GPIO_ODR_4;
Código para apagar el LED
GPIOA->ODR &= ~(1 << 4); //
GPIOA->ODR &= ~0x10; //
GPIOA->ODR &= ~GPIO_ODR_4;
Pero si escribe la línea para apagar el LED después de la línea para encender, el LED no parpadeará (si está interesado en lo que sucede, puede intentarlo; nada arderá, esto ya se ha discutido anteriormente), entonces debe retrasarlo. Los temporizadores se usan para retrasar, pero los temporizadores son dignos de un artículo separado (debido a la complejidad), por lo que haremos un retraso de muleta: impulsaremos el ciclo inactivo. Hay un punto:
si la optimización del compilador está habilitada , el
compilador cortará nuestro ciclo de inactividad y no habrá demora. Asegúrese de que la optimización no esté habilitada. Para hacer esto, vayamos a la configuración del proyecto (haga clic derecho en el nombre del proyecto en el árbol del proyecto) y verifique la línea
Compilar cadena de control en la pestaña
Compilar : debe tener el argumento
-O0 ("aproximadamente cero" significa que la optimización está desactivada). Si recolectó todo de acuerdo con mis instrucciones, lo más probable es que también tenga
-O0 , porque fue por defecto y no toqué nada aquí. Los argumentos
-O1 -O2 -O3 significan que la optimización del nivel correspondiente está habilitada.
Comprobación de optimización del compilador Un ciclo inactivo se puede escribir así:
int t = 4000000; while(t > 0) t--;
No configuré el valor de
t como tal, razoné así: si el microcontrolador funciona a 8MHz, entonces ejecutará aproximadamente 8,000,000 de instrucciones en un segundo, si exageras profundamente, entonces por medio segundo de retraso necesitarás ejecutar el ciclo 4,000,000 de veces.
El ciclo de inactividad deberá ejecutarse después de encender el LED, y después de apagarlo, y todo esto junto.
3.4 Escribir código y ejecutar
Vamos a juntar todas las líneas de código que escribimos antes. También debe incluir el archivo de encabezado
stm32f0xx.h , como confiamos en él y tomamos de él definiciones de estructuras, direcciones y valores. El resultado debería ser:
#include "stm32f0xx.h" int main(void) { int t; // '' RCC->CR |= 0x1; // HSI RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // A GPIOA->MODER |= GPIO_MODER_MODER4_0; // PA4 GPIOA->OTYPER &= ~GPIO_OTYPER_OT_4; // push-pull PA4 GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR4_0; // PA4 GPIOA->PUPDR |= GPIO_PUPDR_PUPDR4_0; // pull-up PA4 while(1) { GPIOA->ODR |= GPIO_ODR_4; // PA4 t = 4000000; while(t > 0) t--; // GPIOA->ODR &= ~GPIO_ODR_4; // PA4 t = 4000000; while(t > 0) t--; // } }
Haga clic en Reconstruir y complete el código en el tablero a través de la utilidad.

Para que la placa inicie un nuevo firmware, no olvide cerrar el puente BOOT y reiniciar (RESET).
4. Conclusión
El código está escrito, todo funciona. Fuerzas gastadas sin medida. Me alegra que, en base a la documentación, resultó escribir código de trabajo, en gran parte debido al hecho de que STM tiene documentación de alta calidad.
Los planes son escribir un artículo sobre cómo ensamblar todo a mano, sin un IDE, a través de la consola,
verdadera vieja escuela , idealmente para que todo esto se pueda hacer desde Linux. Ahora estoy trabajando en PWM y ADC (también en este foro). También escribiré un artículo sobre ellos.