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