====== Interfaces básicas STM32 DISCO-L476VG ======
====== Plataforma de evaluación HW para STM32L4 ======
===== DISCO-L476VG =====
Placa de desarrollo STM32 Discovery kit [[https://www.st.com/en/evaluation-tools/32l476gdiscovery.html|//32L476GDISCOVERY//]] con MCU STM32L476VG
* Depurador/programador en PCB ST-LINK/V2-1 con conector SWD
* Alimentación (4x opciones):
* ST-LINK/V2-1
* Conector USB FS
* Externa 5 V
* Batería CR2032
* 2x LEDs de usuario: LD4 (rojo), LD5 (verde)
* 2x botón pulsador: USER y RESET
* 1x puerto USB OTG FS con conector micro-AB, capacidad de re-enumeración USB y 3x interfaces USB:
* VCP (Virtual Com port)
* Almacenamiento masivo (USB Disk drive) para programación por arrastre
* Depuración (Debug port)
* 1x Joystick de 4x direcciones y selección central
* SAI Audio DAC, estéreo, con conector Jack de salida
* Micrófono digital MEMS
* Acelerómetro y magnetómetro MEMS
* Giróscopo MEMS
* 128-Mbit memoria Quad-SPI Flash
* Amperímetro de corriente del MCU con 4 rangos y auto calibración
{{:silab2:image1.png?566x425}}
==== MCU STM32L476VGT6 (encapsulado LQFP100) ====
* ARM®32-bit Cortex®-M4 CPU con FPU y acelerador ART
* 80 MHz frecuencia máxima de CPU
* VDD de 1.71V a 3.6 V
* 1 MB Flash
* 128 KB SRAM
* 114x GPIOs con capacidad de interrupción externa
* 3x 12-bit ADCs con 16 canales
* 2x 12-bit DAC
* 3x USART
* 2x UART
* 1x LPUART
* 2x SAI
* 3x I2C
* 3x SPI
* 1x Quad SPI
* 7x temporizadores (Timers) de propósito general, 2x básicos y 2x avanzados
* 2x temporizadores de bajo consumo (low-power)
* 2x temporizadores tipo Watchdog
* 1x CAN
* USB OTG FS
* SDMMC
* SWPMI
* LCD COM x SEG
* RTC
* TRNG (generador de aleatorios por HW)
* 21x sensores capacitivos
* 2x comparadores analógicos
* 2x amplificadores operacionales
==== LEDs de usuario ====
{{:silab2:image2.png?554x191}}
==== Pulsadores (JoyStick) ====
{{:silab2:image3.jpeg}}
==== Pulsador de RESET ====
{{:silab2:image5.png?473x410}}
==== Controlador de LCD en el STM32L476 ====
{{:silab2:image6.jpeg}}
{{:silab2:image7.jpeg}}
{{:silab2:image12.png}}
==== Display LCD en DISCO-L476VG ====
* 24 segmentos
* 4 comunes ® excitación multiplexada (1/4 duty)
* polarización 1/3 (bias) ® 3+1 = 4 voltajes de polarización
{{:silab2:image18.png}}
{{:silab2:image19.jpeg}}
{{:silab2:image20.png}}
====== Desarrollo SW: interfaces E/S básicas ======
El **objetivo** del tutorial es el de crear interfaces de usuario con los recursos de **E/S básicas** de la plataforma HW haciendo uso de los **recursos BSP** proporcionados por el fabricante, incluyendo LEDs, pulsadores (JoyStick) y LCD.
===== Creación del proyecto con STM32CubeMX =====
Desde ventana principal acceder a la **selección de placas STBoard** e iniciar un nuevo proyecto (Start Project) para la DISCO-L476VG:
Aparecerá la ventana emergente para la **inicialización de periféricos** a su modo por defecto y en este caso contestaremos que **Si** para //evitar la definición manual de un número elevado de pines individuales asociados al LCD//, y eliminaremos los periféricos que no vamos a usar:
{{:silab2:image24.png?274x90}}
Desde la **System View**, eliminando los periféricos sobrantes debería quedar así:
{{:silab2:image25.png?553x224}}
Quedando definidos los pines para el LCD, JoyStick y LEDs, como se puede comprobar en la **Pinout view**:
{{:silab2:image26.png?377x373}}
Verificamos que la **interfaz de depuración** está establecida a //Serial Wire// en la categoría **SYS** y el temporizador base del sistema el //SysTick//; en **RCC** verificamos que al menos esté incluido el **reloj externo** de baja velocidad (**LSE**), pines PC14 y PC15, asociado a un cristal de 32.768 KHz (X1), ya que se utiliza como reloj base de entrada al display LCD del PCB.
En la categoría **LCD** del apartado Multimedia, ajustamos los parámetros del display del PCB, de acuerdo a las fórmulas señaladas y especificaciones concretas, si bien pretendemos hacer uso de las librerías BSP de nuestro PCB, y vienen ya predefinidos en la función //BSP_LCD_GLASS_Init()//
{{:silab2:image27.png?458x429}}
En la **configuración de reloj** asignamos la entrada LSE (32.768 KHz) en el multiplexor para el LCD, y ajustamos la frecuencia del reloj principal si es necesario, p.ej. a la máxima (HCLK) = //80 MHz// para que recalcule la ruta de encaminamiento de señales más adecuada.
{{:silab2:image28.png?442x135}}
Comprobamos que todos los pines necesarios aparezcan en **GPIO** y pasamos a la generación de código en Project Manager exportando al espacio de trabajo donde operará la herramienta de Atollic TrueSTUDIO™:
{{:silab2:image29.png?577x389}}
===== Edición de código =====
Importamos el código generado por CubeMX (File→Import→General→Existing Projects into Workspace) y comprobamos las funciones generadas en este proyecto, que en principio sólo serán las correspondientes a GPIO y LCD.
Como el propósito aquí es utilizar funciones del BSP procedemos a la importación de las fuentes proporcionados en el FW; para ello, primero debemos localizar la BSP, que se encuentra en el siguiente directorio relativo a la carpeta de instalación de CubeMX:
//**[carpeta_STMCubeMX-version]/Repository/STM32Cube_FW_L4_V1.13.0/Drivers/BSP** //
Como en el caso de los sensores MEMS, arrastramos y copiamos (Copy files and folders) la carpeta BSP a nuestro proyecto en Eclipse, dentro de Drivers, posteriormente iremos eliminando archivos y carpetas innecesarias de otras PCBs y dispositivos hasta que queden únicamente los necesarios, como se muestra a continuación:
{{:silab2:image30.png?718x241}}
Ajustamos los caminos a los archivos de cabecera dentro de las propiedades del proyecto, clic derecho sobre el mismo en el explorador de Eclipse, y click izquierdo sobre la opción //Properties// e incluimos la ruta relativa al espacio de trabajo:
{{:silab2:image31.png?515x368}}
Pasamos a la edición del código donde incorporamos las nuevas cabeceras del BSP:
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "stm32l4xx_hal.h"
#include "stm32l476g_discovery.h"
#include "stm32l476g_discovery_glass_lcd.h"
/* USER CODE END Includes */
Y en la rutina principal modificamos las **secciones de usuario 2 y 3** según el siguiente código a modo de demostración donde se hace uso de llamadas a las funciones BSPs de las interfaces de E/S básicas propuestas.
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_LCD_Init();
/* USER CODE BEGIN 2 */
BSP_LCD_GLASS_Init();
BSP_LCD_GLASS_DisplayChar((uint8_t *)"8",POINT_ON,DOUBLEPOINT_ON,LCD_DIGIT_POSITION_2);
HAL_Delay(500);
BSP_LCD_GLASS_DisplayChar((uint8_t *)"A",POINT_OFF,DOUBLEPOINT_OFF,LCD_DIGIT_POSITION_3);
HAL_Delay(500);
BSP_LCD_GLASS_DisplayBar(LCD_BAR_2);
HAL_Delay(500);
BSP_LCD_GLASS_ClearBar(LCD_BAR_2);
HAL_Delay(500);
BSP_LCD_GLASS_BarLevelConfig(BATTERYLEVEL_OFF);
HAL_Delay(250);
BSP_LCD_GLASS_BarLevelConfig(BATTERYLEVEL_1_4);
HAL_Delay(250);
BSP_LCD_GLASS_BarLevelConfig(BATTERYLEVEL_1_2);
HAL_Delay(250);
BSP_LCD_GLASS_BarLevelConfig(BATTERYLEVEL_3_4);
HAL_Delay(250);
BSP_LCD_GLASS_BarLevelConfig(BATTERYLEVEL_FULL);
HAL_Delay(500);
BSP_LCD_GLASS_BlinkConfig(LCD_BLINKMODE_ALLSEG_ALLCOM, LCD_BLINKFREQUENCY_DIV512);
HAL_Delay(500);
BSP_LCD_GLASS_Clear();
BSP_LCD_GLASS_BlinkConfig(LCD_BLINKMODE_OFF, LCD_BLINKFREQUENCY_DIV512);
BSP_LCD_GLASS_DisplayString((uint8_t *)"123456");
HAL_Delay(500);
BSP_LCD_GLASS_ScrollSentence((uint8_t *)" SISTEMAS INTEGRADOS ",1,SCROLL_SPEED_MEDIUM);
HAL_Delay(500);
BSP_LCD_GLASS_Contrast(LCD_CONTRASTLEVEL_0);
BSP_LCD_GLASS_ScrollSentence((uint8_t *)" CONTRASTE MIN", 1, SCROLL_SPEED_MEDIUM);
HAL_Delay(500);
BSP_LCD_GLASS_Contrast(LCD_CONTRASTLEVEL_7);
BSP_LCD_GLASS_ScrollSentence((uint8_t *)" CONTRASTE MAX", 1, SCROLL_SPEED_MEDIUM);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
JOYState_TypeDef JoyState = BSP_JOY_GetState();
switch(JoyState)
{
case JOY_LEFT:
BSP_LED_Toggle(LED4);
BSP_LCD_GLASS_DisplayString((uint8_t *)" LEFT");
HAL_Delay(1000);
break;
case JOY_RIGHT:
BSP_LED_Toggle(LED5);
BSP_LCD_GLASS_DisplayString((uint8_t *)" RIGHT");
break;
case JOY_UP:
BSP_LED_Toggle(LED4);
BSP_LED_Toggle(LED5);
BSP_LCD_GLASS_DisplayString((uint8_t *)" UP");
break;
case JOY_DOWN:
BSP_LED_Toggle(LED4);
BSP_LED_Toggle(LED5);
BSP_LCD_GLASS_DisplayString((uint8_t *)" DOWN");
break;
case JOY_SEL:
BSP_LED_On(LED4);
BSP_LED_On(LED5);
BSP_LCD_GLASS_DisplayString((uint8_t *)" SEL");
break;
default:
break;
}
}
/* USER CODE END 3 */
}
Realizar la depuración y ejecución del código atendiendo al uso de las distintas funciones del BSP.
===== Ejercicios propuestos =====
**P1: Activación de LEDs con Joystick**
* Crear un proyecto nuevo llamado “**p1_cubemx_leds_joystick**” usando STM32 CubeMX
* Funcionamiento:
* Encender LED rojo al pulsar JOY_UP
* Encender LED verde al pulsar JOY_DOWN
* Encender ambos LEDs al pulsar JOY_CENTER
* Parpadear LED rojo con retardo de 100 ms al pulsar JOY_RIGHT
* Parpadear LED verde con retardo de 100 ms al pulsar JOY_LEFT
* LEDs apagados si no se pulsa en el joystick
* No olvidar poner comentarios en el código
* Elementos de ayuda:
* **UM1884 User Manual – Description of STM32L4/L4+ HAL and low-layer drivers** (PDF)
* archivo ..\Drivers\STM32L4xx_HAL_Driver\Src\**stm32l4xx_hal_gpio.c**
**P2: Activación de LED por Interrupciones**
* Crear un proyecto nuevo llamado “**p2_int_led**” usando STM32 CubeMX
* Configurar temporizador TIM6 para producir interrupciones cada 100 ms
* Funcionamiento:
* LED rojo: parpadear cada 100 ms usando interrupciones del TIM6
* No olvidar poner comentarios en el código
* Elementos de ayuda:
* UM1884 User Manual – Description of STM32L4/L4+ HAL and low-layer drivers (PDF)
* descripción detallada de las funciones de la HAL
* RM0351 Reference Manual – STM32L4x5-L4x6 advanced ARM-based 32-bit MCUs (PDF)
* descripción detallada de los temporizadores
**P2: Activación de LEDs por Interrupciones Priorizadas**
* Crear un proyecto nuevo llamado “**p2_int_leds_prioridades**” usando CubeMX
* Configurar los temporizadores TIM6 y TIM7 para producir interrupciones
* prioridad TIM6 **<** prioridad TIM7
* Funcionamiento:
* LED rojo: parpadear cada 1000 ms usando interrupciones del TIM6
* LED verde: parpadear cada 1000 ms usando interrupciones del TIM7. Dentro de la ISR, realizar un retardo de 250 ms después de conmutar y antes de salir de la ISR
* Arrancará primero el TIM7 y después de 10 ms el TIM6. Comprobar como el LED rojo (menor prioridad) se retrasa con respecto al LED verde (» 250 + 10 ms)
**P2: Activación de LEDs por Interrupciones Priorizadas (2)**
* Crear un proyecto nuevo llamado “**p2_int_leds_prioridades2**” usando CubeMX
* Funcionamiento:
* todo igual que en el proyecto “**p2_int_leds_prioridades**” pero invirtiendo el orden de las prioridades, es decir, prioridad TIM6 **>** prioridad TIM7
* Comprobar que, a pesar del retardo de 250 ms de la ISR del TIM7 (LED verde), la ISR del TIM6 (LED rojo) es atendida inmediatamente debido a que es más prioritaria. Es decir, que el LED rojo apenas tiene retardo respecto al LED verde (» 10 ms)