Comenzamos a estudiar microcontroladores usando el ejemplo de STM32F030f4p6



0. Antes de leer el artículo


Este artículo tiene los siguientes objetivos:

  1. mostrar cómo trabajar específicamente con este tablero;
  2. muestra el enfoque mediante el cual puede escribir un programa LED parpadeante, bas√°ndose √ļnicamente en la documentaci√≥n y la l√≥gica;
  3. 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:

  1. Hoja de datos STM32F030x4 (uso el documento de enero de 2017 DocID024849 Rev 3);
  2. RM0360 Manual de referencia STM32F030x4 / x6 / x8 / xC (uso el documento de abril de 2017 DocID025023 Rev 4);
  3. 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.

Adaptador de foto

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:

  1. interfaz (tengo COM-3);
  2. la velocidad con la cual la computadora y el microcontrolador se comunicarán (en mi humilde opinión, valor normal 9600);
  3. 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);
  4. paridad (no tengo paridad, es decir, ninguna);
  5. echo (tengo apagado);
  6. 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:

  1. En primer lugar, debe verificar si el puente BOOT en el tablero est√° cerrado.
  2. 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).
  3. 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.
  4. 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:

  1. borrar memoria (completa o seleccionar un área específica);
  2. escribir firmware en el dispositivo;
  3. leer el firmware del dispositivo;
  4. 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.

Ventana de progreso


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).

Preparando para grabar


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.


√Ārbol de reloj

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 .

Foto del tablero


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:

  1. 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;
  2. PLLCLK - se√Īal del multiplicador de frecuencia PLLMUL ;
  3. 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 ).

RCC-> RC


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; 

RCC-> AHBENR


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.

  1. 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


    GPIOA-> MODER


  2. 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


  3. 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


  4. 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


    GPIOA-> PUPDR



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.



GPIOA-> ODR


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.

Source: https://habr.com/ru/post/437234/


All Articles