Warning
This page is located in archive. Go to the latest version of this course pages.

Lab08 - LCD display and HAL libraries

The previous examples used StdPeriph (standard peripheral) libraries to control the basic functionality of the Nucleo board. All the future projects will use HAL (hardware abstraction layer) and BSP (board support package) libraries.

The sample project provides the basic functionality demonstration over:

  • Serial line (ST Link)
  • Joystick (Adafruit)
  • LCD and drawing (Adafruit)
  • Timers (HAL)
  • String manipulation (C lib)

The demo application works in the following way:

  • Joystick press - clears the display and sends data over serial line.
  • Joystick movements - displays pictorgams in display corners.
  • Reception of character '0' sent from PC to Nucleo causes the system to draw a circle in the middle of the display. The parameters for this circle are scanned from a sample string representing a command received over serial line.
  • Elapsed time is drawn on the display every second.

How to use the template project

The template project is available as new boards: prjcpl_lcd_newlcd_eddited_working.zip old boards old_boards_-_.zip. The recomended solution to make it work is as follows:

  • Create a new workspace in Eclipse (System Workbench) - select File > Switch workspace > other and create a new one.
  • Download the project and copy the prjCPL_LCD folder into the workspace folder.
  • Import the project into the workspace through: File > Import, select General > Existing Projects into Workspace. Then select the project root directory (locate the prjCPL_LCD folder on your filesystem) and press Finish button.
    • Build the project through: Project > Build All.
  • And upload the project into the board with Run > Debug as > Ac6 C/Cpp Application.

The exercise objective

  • Make the template project working with your board.
  • Start writing the code to receive data from serial line into a buffer to be able to parse commands from PC

The code

This is the content of the main.c file for above mentioned functionality. This code will work only with HAL libraries. How to import the project into the workspace is described above.

//
//  ******************************************************************************
//  @file    main.c
//  @author  CPL (Pavel Paces, based on STM examples and HAL library)
//  @version V0.0
//  @date    02-November-2016
//  @brief   Adafruit 802 display shield and serial line over ST-Link example
//           Nucleo STM32F401RE USART2 (Tx PA.2, Rx PA.3)
//
//  ******************************************************************************
//
 
//
// Basic framework
#include "stm32f4xx.h"
#include "stm32f4xx_nucleo.h"
 
#include "stm32_adafruit_lcd.h"
 
#include <string.h>
 
 
/* Definition for I2Cx clock resources */
/*
#define I2Cx                            I2C1
#define I2Cx_CLK_ENABLE()               __HAL_RCC_I2C1_CLK_ENABLE()
#define I2Cx_SDA_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_SCL_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE()
 
#define I2Cx_FORCE_RESET()              __HAL_RCC_I2C1_FORCE_RESET()
#define I2Cx_RELEASE_RESET()            __HAL_RCC_I2C1_RELEASE_RESET()
*/
 
/* Definition for I2Cx Pins */
/*
#define I2Cx_SCL_PIN                    GPIO_PIN_8
#define I2Cx_SCL_GPIO_PORT              GPIOB
#define I2Cx_SDA_PIN                    GPIO_PIN_9
#define I2Cx_SDA_GPIO_PORT              GPIOB
#define I2Cx_SCL_SDA_AF                 GPIO_AF4_I2C1
*/
 
#define I2C_ADDRESS        0x0F
 
 
typedef enum
{
  SHIELD_NOT_DETECTED = 0,
  SHIELD_DETECTED
}ShieldStatus;
 
/* I2C handler declaration */
I2C_HandleTypeDef I2cHandle;
I2C_InitTypeDef  I2C_InitStructure;
 
 
 
#define TFTSHIELD_I2C_ADDR (0x2E << 1)
 
#define TFTSHIELD_RESET_PIN (1ul << 3)
 
 
#define TFTSHIELD_BUTTON_UP_PIN 6
#define TFTSHIELD_BUTTON_UP (1UL << TFTSHIELD_BUTTON_UP_PIN)
 
#define TFTSHIELD_BUTTON_DOWN_PIN 9
#define TFTSHIELD_BUTTON_DOWN (1UL << TFTSHIELD_BUTTON_DOWN_PIN)
 
#define TFTSHIELD_BUTTON_LEFT_PIN 8
#define TFTSHIELD_BUTTON_LEFT (1UL << TFTSHIELD_BUTTON_LEFT_PIN)
 
#define TFTSHIELD_BUTTON_RIGHT_PIN 5
#define TFTSHIELD_BUTTON_RIGHT (1UL << TFTSHIELD_BUTTON_RIGHT_PIN)
 
#define TFTSHIELD_BUTTON_IN_PIN 7
#define TFTSHIELD_BUTTON_IN (1UL << TFTSHIELD_BUTTON_IN_PIN)
 
#define TFTSHIELD_BUTTON_1_PIN 10
#define TFTSHIELD_BUTTON_1 (1UL << TFTSHIELD_BUTTON_1_PIN)
 
#define TFTSHIELD_BUTTON_2_PIN 11
#define TFTSHIELD_BUTTON_2 (1UL << TFTSHIELD_BUTTON_2_PIN)
 
#define TFTSHIELD_BUTTON_3_PIN 14
#define TFTSHIELD_BUTTON_3 (1UL << TFTSHIELD_BUTTON_3_PIN)
 
#define TFTSHIELD_BUTTON_ALL (TFTSHIELD_BUTTON_UP | TFTSHIELD_BUTTON_DOWN | TFTSHIELD_BUTTON_LEFT \
                            | TFTSHIELD_BUTTON_RIGHT | TFTSHIELD_BUTTON_IN | TFTSHIELD_BUTTON_1 \
                            | TFTSHIELD_BUTTON_2 | TFTSHIELD_BUTTON_3)
 
 
 
UART_HandleTypeDef hUART2;
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* User may add here some code to deal with this error */
 
  while(1)
  {
  }
}
 
/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow :
  *            System Clock source            = PLL (HSI)
  *            SYSCLK(Hz)                     = 84000000
  *            HCLK(Hz)                       = 84000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            HSI Frequency(Hz)              = 16000000
  *            PLL_M                          = 16
  *            PLL_N                          = 336
  *            PLL_P                          = 4
  *            PLL_Q                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale2 mode
  *            Flash Latency(WS)              = 2
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
 
  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
 
  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
 
  /* Enable HSI Oscillator and activate PLL with HSI as source */
  RCC_OscInitStruct.OscillatorType          = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState                = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue     = 6; //0x10;
  RCC_OscInitStruct.PLL.PLLState            = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource           = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM                = 16;
  RCC_OscInitStruct.PLL.PLLN                = 336;
  RCC_OscInitStruct.PLL.PLLP                = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ                = 7;
  if( HAL_RCC_OscConfig( &RCC_OscInitStruct ) != HAL_OK )
  {
    Error_Handler();
  }
 
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers */
  RCC_ClkInitStruct.ClockType               = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource            = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider           = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider          = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider          = RCC_HCLK_DIV1;
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
 
  /*
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  */
 
}
 
/**
  * @brief  Serial port settings
  * @param  None
  * @retval None
  */
static void initUSART( void )
{
    GPIO_InitTypeDef GPIO_InitStruct;
 
    __GPIOA_CLK_ENABLE();
    __USART2_CLK_ENABLE();
 
    // **USART2 GPIO Configuration
    // PA2     ------> USART2_TX
    // PA3     ------> USART2_RX
 
    GPIO_InitStruct.Pin         = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode        = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull        = GPIO_NOPULL;
    GPIO_InitStruct.Speed       = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate   = GPIO_AF7_USART2;
    HAL_GPIO_Init( GPIOA, &GPIO_InitStruct );
 
 
    hUART2.Instance             = USART2;
    hUART2.Init.BaudRate        = 9600;//115200;
    hUART2.Init.WordLength      = UART_WORDLENGTH_8B;
    hUART2.Init.StopBits        = UART_STOPBITS_1;
    hUART2.Init.Parity          = UART_PARITY_NONE;
    hUART2.Init.Mode            = UART_MODE_TX_RX;
    hUART2.Init.HwFlowCtl       = UART_HWCONTROL_NONE;
    hUART2.Init.OverSampling    = UART_OVERSAMPLING_16;
    if (HAL_UART_Init( &hUART2 ) != HAL_OK)
    {
        Error_Handler();
    }
 
} // END void initUSART( void )
 
 
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 
  /* Infinite loop */
  while (1)
  {
  }
}
#endif
 
/**
  * @brief  Initialize I2C
  * @param  None
  * @retval None
  */
static void i2c_init(void)
{
 
    GPIO_InitTypeDef GPIO_InitStruct;
 
    __GPIOB_CLK_ENABLE();
 
    GPIO_InitStruct.Pin         = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode        = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull        = GPIO_PULLUP;
    GPIO_InitStruct.Speed       = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate   = GPIO_AF4_I2C1;
    HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
 
    // Peripheral clock enable
    __HAL_RCC_I2C1_CLK_ENABLE();
 
    I2cHandle.Instance             = I2C1;
    I2cHandle.Init.DutyCycle       = I2C_DUTYCYCLE_2;
    I2cHandle.Init.ClockSpeed      = 100*1000;
    I2cHandle.Init.OwnAddress1     = I2C_ADDRESS;
    I2cHandle.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;
    I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    I2cHandle.Init.OwnAddress2     = 0xFF;
    I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    I2cHandle.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLE;
 
    if(HAL_I2C_Init(&I2cHandle) != HAL_OK) {
          // Initialization Error
          Error_Handler();
    }
 
} // END static void i2c_init(void)
 
 
/**
  * @brief  Check the availability of adafruit 1.8" TFT shield on top of STM32NUCLEO
  *         board. This is done by reading the state of IO PF.03 pin (mapped to
  *         JoyStick available on adafruit 1.8" TFT shield). If the state of PF.03
  *         is high then the adafruit 1.8" TFT shield is available.
  * @param  None
  * @retval SHIELD_DETECTED: 1.8" TFT shield is available
  *         SHIELD_NOT_DETECTED: 1.8" TFT shield is not available
  */
static ShieldStatus TFT_ShieldDetect(void)
{
  GPIO_InitTypeDef  GPIO_InitStruct;
 
  /* Enable GPIO clock */
  NUCLEO_ADCx_GPIO_CLK_ENABLE();
 
  GPIO_InitStruct.Pin = NUCLEO_ADCx_GPIO_PIN ;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(NUCLEO_ADCx_GPIO_PORT , &GPIO_InitStruct);
 
  if(HAL_GPIO_ReadPin(NUCLEO_ADCx_GPIO_PORT, NUCLEO_ADCx_GPIO_PIN) != 0)
  {
    return SHIELD_DETECTED;
  }
  else
  {
    return SHIELD_NOT_DETECTED;
  }
}
 
 
/**
  * @brief  Check the availability of adafruit 1.8" TFT shield V2 on top of STM32NUCLEO
  *         board. This is done by writing I2C bus. If it fails the shield is not present
  * @param  None
  * @retval SHIELD_DETECTED: 1.8" TFT shield V2 is available
  *         SHIELD_NOT_DETECTED: 1.8" TFT shield V2 is not available
  */
static ShieldStatus TFT_V2_ShieldDetect(void)
{
 
    uint8_t i2c_d [3];
    uint8_t status = 0;
    uint32_t timeout = 200;
 
 
    i2c_d[0] = 0x00;
    i2c_d[1] = 0x7F;
    i2c_d[2] = 0xFF;
 
    do {
        status = HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 3, 1000);
    } while ( (status != HAL_OK) && (timeout--) );
 
 
    if ( status || !timeout ) {
        return SHIELD_NOT_DETECTED;
    }
 
    return SHIELD_DETECTED;
 
}
 
 
/**
  * @brief  Returns the Joystick key pressed of adafruit 1.8" TFT shield V2.
  * @retval JOYState_TypeDef: Code of the Joystick key pressed.
  */
JOYState_TypeDef TFT_V2_Shield_JOY_GetState(void)
{
    JOYState_TypeDef state;
    uint8_t i2c_d[4];
    uint32_t btn_state;
 
    i2c_d[0] = 0x01;
    i2c_d[1] = 0x04;
 
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 2, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
    while(HAL_I2C_Master_Receive(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 4, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
 
    btn_state = ~( (uint32_t)i2c_d[0] << 24 | (uint32_t)i2c_d[1] << 16 | (uint32_t)i2c_d[2] << 8 | (uint32_t)i2c_d[3] );
 
    if( btn_state & TFTSHIELD_BUTTON_DOWN ) {
        state = JOY_DOWN;
    } else if ( btn_state & TFTSHIELD_BUTTON_RIGHT ) {
        state = JOY_RIGHT;
    } else if ( btn_state & TFTSHIELD_BUTTON_IN ) {
        state = JOY_SEL;
    } else if ( btn_state & TFTSHIELD_BUTTON_UP ) {
        state = JOY_UP;
    } else if ( btn_state & TFTSHIELD_BUTTON_LEFT ) {
        state = JOY_LEFT;
    } else {
        state = JOY_NONE;
    }
 
    return state;
}
 
 
 
 
/**
  * @brief  Initialize SeeSaw chip on adafruit 1.8" TFT shield V2
  * @param  None
  * @retval None
  */
static void TFT_V2_ShiedInit(void)
{
    uint8_t i2c_d [6];
 
    // reset all seesaw regs to defaults
    i2c_d[0] = 0x00;
    i2c_d[1] = 0x7F;
    i2c_d[2] = 0xFF;
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 3, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
    HAL_Delay(500);
 
    // read ID
#if 0
    i2c_d[0] = 0x00;
    i2c_d[1] = 0x01;
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 2, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
    while(HAL_I2C_Master_Receive(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 1, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
#endif
 
 
    // enable backlight
    i2c_d[0] = 0x08;
    i2c_d[1] = 0x01;
    i2c_d[2] = 0x00;
    i2c_d[3] = 0xFF;
    i2c_d[4] = 0xFF;
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 5, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
 
 
    // set reset pin as output
    i2c_d[0] = 0x01;
    i2c_d[1] = 0x02;
    i2c_d[2] = (uint8_t)(TFTSHIELD_RESET_PIN >> 24);
    i2c_d[3] = (uint8_t)(TFTSHIELD_RESET_PIN >> 16);
    i2c_d[4] = (uint8_t)(TFTSHIELD_RESET_PIN >> 8);
    i2c_d[5] = (uint8_t)(TFTSHIELD_RESET_PIN);
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 6, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
 
 
    // LCD reset
    i2c_d[0] = 0x01;
    i2c_d[1] = 0x05;
    i2c_d[2] = (uint8_t)(TFTSHIELD_RESET_PIN >> 24);
    i2c_d[3] = (uint8_t)(TFTSHIELD_RESET_PIN >> 16);
    i2c_d[4] = (uint8_t)(TFTSHIELD_RESET_PIN >> 8);
    i2c_d[5] = (uint8_t)TFTSHIELD_RESET_PIN;
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 6, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
 
    HAL_Delay(20);
 
    // set seesaw pins as inputs - buttons and JOY
    i2c_d[0] = 0x01;
    i2c_d[1] = 0x03;
    i2c_d[2] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 24);
    i2c_d[3] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 16);
    i2c_d[4] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 8);
    i2c_d[5] = (uint8_t)(TFTSHIELD_BUTTON_ALL);
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 6, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
 
    // set pin val to high, buttons are active in low level
    i2c_d[0] = 0x01;
    i2c_d[1] = 0x05;
    i2c_d[2] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 24);
    i2c_d[3] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 16);
    i2c_d[4] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 8);
    i2c_d[5] = (uint8_t)(TFTSHIELD_BUTTON_ALL);
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 6, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
 
    // enable internal PULLUPs
    i2c_d[0] = 0x01;
    i2c_d[1] = 0x0B;
    i2c_d[2] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 24);
    i2c_d[3] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 16);
    i2c_d[4] = (uint8_t)(TFTSHIELD_BUTTON_ALL >> 8);
    i2c_d[5] = (uint8_t)(TFTSHIELD_BUTTON_ALL);
    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)TFTSHIELD_I2C_ADDR, i2c_d, 6, 1000) != HAL_OK) {
        if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF) {
            Error_Handler();
        }
    }
 
}
 
 
 
#define TFTSHIELD_VERSION 2
 
/**
  * @brief  main function
  * @param  None
  * @retval None
  */
void main(void)
{
    // timer settings
    uint32_t uiTicks, uiSec;
    // display tmp variables
    uint32_t uiDispCentX, uiDispCentY;
    // joystick operation
    JOYState_TypeDef oJoyState;
 
    // serial port i/o and status
#define cREVC_MAX 8
    uint8_t chArr[cREVC_MAX];
    HAL_StatusTypeDef oRecvStatus;
 
    // data reception
    uint32_t uiSerRecv;
 
    //
    // initialization of variables
    uiSec = 0;
    uiSerRecv = 0;
 
    //
    // System init
    HAL_Init();
    // Configure the System clock to 84 MHz
    SystemClock_Config();
    // serial port
    initUSART();
 
#if (TFTSHIELD_VERSION == 2)
  /* I2C init, 100kHz, 7b addressing */
  i2c_init();
 
  LCD_IO_Init();
#endif
 
#ifndef test
 
#if (TFTSHIELD_VERSION == 1)
  if(TFT_ShieldDetect() == SHIELD_DETECTED) {
 
    (void)BSP_JOY_Init();
 
#elif (TFTSHIELD_VERSION == 2)
  if (TFT_V2_ShieldDetect() == SHIELD_DETECTED) {
    TFT_V2_ShiedInit();
#endif
    /* light the LED od TFTSHIELD presence */
    //LED1_On();
 
    /* Initialize the LCD */
//  BSP_LCD_Init();
 
  }
#endif
 
//  TFT_V2_ShiedInit();
//  BSP_LCD_Init();
 
    // Nucleo User LED init
//  BSP_LED_Init( LED2 );
    // and usage
//  BSP_LED_Off( LED2 );
//  HAL_Delay( 1000 );
//  BSP_LED_On( LED2 );
//  HAL_Delay( 1000 );
//  BSP_LED_Toggle( LED2 );
 
    // Nucleo user button init
//  BSP_PB_Init( BUTTON_USER, BUTTON_MODE_GPIO );
 
    // Adafruit joystick init
//  (void)BSP_JOY_Init();
 
    //
    // Adafruit LCD init
    BSP_LCD_Init();
    uiDispCentX = BSP_LCD_GetXSize()/2;
    uiDispCentY = BSP_LCD_GetYSize()/2;
 
    //
    // some drawings
    BSP_LCD_Clear( LCD_COLOR_GREEN );
    BSP_LCD_DrawLine( 10, 10, 128-10, 10 );
    BSP_LCD_SetFont( &Font24 );
    BSP_LCD_SetTextColor( LCD_COLOR_RED );
    BSP_LCD_DisplayStringAtLine( 1, (uint8_t *)" Welcome to Nucleo! " );
 
 
    while(1) // main loop
    {
 
        //
        // Receive serial data example
        oRecvStatus = HAL_UART_Receive( &hUART2, chArr, 1, 100 );
        if( oRecvStatus == HAL_OK )
        {
            uiSerRecv = chArr[0];
        } // END if( oRecvStatus == HAL_OK )
 
        //
        // Joystick reading example
#if (TFTSHIELD_VERSION == 1)
        oJoyState = BSP_JOY_GetState();
#elif (TFTSHIELD_VERSION == 2)
        oJoyState = TFT_V2_Shield_JOY_GetState();
#endif
 
        switch( oJoyState )
        {
        default:
        case JOY_NONE:
            break;
        case JOY_SEL:
            BSP_LCD_Clear( LCD_COLOR_WHITE );
            {
                char *msg = "Welcome to Nucleo!\n\r";
                HAL_UART_Transmit( &hUART2, (uint8_t*)msg, strlen(msg), 0xFFFF);
            }
            BSP_LED_Toggle( LED2 );
            break;
        case JOY_DOWN:
            BSP_LCD_SetTextColor( LCD_COLOR_BLUE );
            BSP_LCD_DrawLine( uiDispCentX, uiDispCentY, uiDispCentX, uiDispCentY + 40 );
            BSP_LCD_DrawCircle(BSP_LCD_GetXSize() - 15, BSP_LCD_GetYSize() - 15, 10);
            break;
        case JOY_LEFT:
            BSP_LCD_SetTextColor( LCD_COLOR_BLUE );
            BSP_LCD_DrawLine( uiDispCentX - 40, uiDispCentY, uiDispCentX, uiDispCentY );
            BSP_LCD_DrawCircle(15, BSP_LCD_GetYSize() - 15, 10);
            break;
        case JOY_RIGHT:
            BSP_LCD_SetTextColor( LCD_COLOR_BLUE );
            BSP_LCD_DrawLine( uiDispCentX, uiDispCentY, uiDispCentX + 40, uiDispCentY);
            BSP_LCD_DrawCircle( BSP_LCD_GetXSize() - 15, 15, 10);
            break;
        case JOY_UP:
            BSP_LCD_SetTextColor( LCD_COLOR_BLUE );
            BSP_LCD_DrawLine( uiDispCentX, uiDispCentY, uiDispCentX, uiDispCentY - 40 );
            BSP_LCD_DrawCircle(15, 15, 10);
            break;
        } // end switch( oJoyState )
 
        //
        // Button reading - the button is hidden under the display
        // uiButtState = BSP_PB_GetState( BUTTON_USER );
 
        //
        // Timming - second counter
        if( (HAL_GetTick() - uiTicks) > 1000)
        {
            uint8_t chArr[40];
            uiTicks = HAL_GetTick();
            uiSec++;
 
            BSP_LCD_SetFont( &Font8 );
            BSP_LCD_SetTextColor( LCD_COLOR_RED );
            sprintf( (char *)chArr, (char *)"  %d   ", (int)uiSec );
            BSP_LCD_DisplayStringAtLine( 14, chArr);
        } // END if( (HAL_GetTick() - uiTicks) > 1000)
 
        //
        // string manipulation example
        if( uiSerRecv == 0x30 )
        {
            int iResult;
            char chArrTmpData[] = "DRAW:CIRCLE 64,80,30";
 
            // !! has to be here
            uiSerRecv = 0;
 
            iResult = strstr(chArrTmpData, "DRAW");
            if( iResult )
            {
                int iXs, iYs, iRad;
                int iResult;
 
                iResult = sscanf( chArrTmpData, "DRAW:CIRCLE %d,%d,%d", &iXs, &iYs, &iRad );
                if( iResult > 2 )
                {
                    BSP_LCD_DrawCircle( iXs, iYs, iRad );
                }
            }
        } // END string manipulation example
 
    } // END while(1)
 
} // END main

Old code working only with the old version of the display.

//
//  ******************************************************************************
//  @file    main.c
//  @author  CPL (Pavel Paces, based on STM examples and HAL library)
//  @version V0.0
//  @date    02-November-2016
//  @brief   Adafruit 802 display shield and serial line over ST-Link example
//           Nucleo STM32F401RE USART2 (Tx PA.2, Rx PA.3)
//
//  ******************************************************************************
//
 
//
// Basic framework
#include "stm32f4xx.h"
#include "stm32f4xx_nucleo.h"
 
#include "stm32_adafruit_lcd.h"
 
#include <string.h>
 
 
UART_HandleTypeDef hUART2;
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* User may add here some code to deal with this error */
 
  while(1)
  {
  }
}
 
/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow :
  *            System Clock source            = PLL (HSI)
  *            SYSCLK(Hz)                     = 84000000
  *            HCLK(Hz)                       = 84000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            HSI Frequency(Hz)              = 16000000
  *            PLL_M                          = 16
  *            PLL_N                          = 336
  *            PLL_P                          = 4
  *            PLL_Q                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale2 mode
  *            Flash Latency(WS)              = 2
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
 
  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
 
  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
 
  /* Enable HSI Oscillator and activate PLL with HSI as source */
  RCC_OscInitStruct.OscillatorType 			= RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState 				= RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue 	= 6; //0x10;
  RCC_OscInitStruct.PLL.PLLState 			= RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource 			= RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM 				= 16;
  RCC_OscInitStruct.PLL.PLLN 				= 336;
  RCC_OscInitStruct.PLL.PLLP 				= RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ 				= 7;
  if( HAL_RCC_OscConfig( &RCC_OscInitStruct ) != HAL_OK )
  {
    Error_Handler();
  }
 
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers */
  RCC_ClkInitStruct.ClockType 				= (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource 			= RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider 			= RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider 			= RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider 			= RCC_HCLK_DIV1;
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
 
  /*
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  */
 
}
 
/**
  * @brief  Serial port settings
  * @param  None
  * @retval None
  */
static void initUSART( void )
{
	GPIO_InitTypeDef GPIO_InitStruct;
 
	__GPIOA_CLK_ENABLE();
	__USART2_CLK_ENABLE();
 
    // **USART2 GPIO Configuration
    // PA2     ------> USART2_TX
    // PA3     ------> USART2_RX
 
	GPIO_InitStruct.Pin 		= GPIO_PIN_2|GPIO_PIN_3;
	GPIO_InitStruct.Mode 		= GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull 		= GPIO_NOPULL;
	GPIO_InitStruct.Speed 		= GPIO_SPEED_LOW;
	GPIO_InitStruct.Alternate 	= GPIO_AF7_USART2;
	HAL_GPIO_Init( GPIOA, &GPIO_InitStruct );
 
 
	hUART2.Instance 			= USART2;
	hUART2.Init.BaudRate 		= 9600;//115200;
	hUART2.Init.WordLength 		= UART_WORDLENGTH_8B;
	hUART2.Init.StopBits 		= UART_STOPBITS_1;
	hUART2.Init.Parity 			= UART_PARITY_NONE;
	hUART2.Init.Mode 			= UART_MODE_TX_RX;
	hUART2.Init.HwFlowCtl 		= UART_HWCONTROL_NONE;
	hUART2.Init.OverSampling 	= UART_OVERSAMPLING_16;
	if (HAL_UART_Init( &hUART2 ) != HAL_OK)
	{
		Error_Handler();
	}
 
} // END void initUSART( void )
 
 
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 
  /* Infinite loop */
  while (1)
  {
  }
}
#endif
 
 
/**
  * @brief  main function
  * @param  None
  * @retval None
  */
void main(void)
{
	// timer settings
	uint32_t uiTicks, uiSec;
	// display tmp variables
	uint32_t uiDispCentX, uiDispCentY;
	// joystick operation
	JOYState_TypeDef oJoyState;
 
	// serial port i/o and status
#define cREVC_MAX 8
	uint8_t chArr[cREVC_MAX];
	HAL_StatusTypeDef oRecvStatus;
 
	// data reception
	uint32_t uiSerRecv;
 
	//
	// initialization of variables
	uiSec = 0;
	uiSerRecv = 0;
 
	//
	// System init
	HAL_Init();
	// Configure the System clock to 84 MHz
	SystemClock_Config();
	// serial port
	initUSART();
 
	// Nucleo User LED init
	BSP_LED_Init( LED2 );
	// and usage
	BSP_LED_Off( LED2 );
	HAL_Delay( 1000 );
	BSP_LED_On( LED2 );
	HAL_Delay( 1000 );
	BSP_LED_Toggle( LED2 );
 
	// Nucleo user button init
	BSP_PB_Init( BUTTON_USER, BUTTON_MODE_GPIO );
 
	// Adafruit joystick init
	(void)BSP_JOY_Init();
 
	//
	// Adafruit LCD init
	BSP_LCD_Init();
	uiDispCentX = BSP_LCD_GetXSize()/2;
	uiDispCentY = BSP_LCD_GetYSize()/2;
 
	//
	// some drawings
	BSP_LCD_Clear( LCD_COLOR_GREEN );
	BSP_LCD_DrawLine( 10, 10, 128-10, 10 );
	BSP_LCD_SetFont( &Font24 );
	BSP_LCD_SetTextColor( LCD_COLOR_RED );
	BSP_LCD_DisplayStringAtLine( 1, (uint8_t *)" Welcome to Nucleo! " );
 
 
	while(1) // main loop
	{
 
		//
		// Receive serial data example
		oRecvStatus = HAL_UART_Receive( &hUART2, chArr, 1, 100 );
		if( oRecvStatus == HAL_OK )
		{
			uiSerRecv = chArr[0];
		} // END if( oRecvStatus == HAL_OK )
 
		//
		// Joystick reading example
		oJoyState = BSP_JOY_GetState();
 
		switch( oJoyState )
		{
		default:
		case JOY_NONE:
			break;
		case JOY_SEL:
			BSP_LCD_Clear( LCD_COLOR_WHITE );
			{
				char *msg = "Welcome to Nucleo!\n\r";
				HAL_UART_Transmit( &hUART2, (uint8_t*)msg, strlen(msg), 0xFFFF);
			}
			BSP_LED_Toggle( LED2 );
			break;
		case JOY_DOWN:
			BSP_LCD_SetTextColor( LCD_COLOR_GREEN );
			BSP_LCD_DrawLine( uiDispCentX, uiDispCentY, uiDispCentX, uiDispCentY + 40 );
			BSP_LCD_DrawCircle(BSP_LCD_GetXSize() - 15, BSP_LCD_GetYSize() - 15, 10);
			break;
		case JOY_LEFT:
			BSP_LCD_SetTextColor( LCD_COLOR_GREEN );
			BSP_LCD_DrawLine( uiDispCentX - 40, uiDispCentY, uiDispCentX, uiDispCentY );
			BSP_LCD_DrawCircle(15, BSP_LCD_GetYSize() - 15, 10);
			break;
		case JOY_RIGHT:
			BSP_LCD_SetTextColor( LCD_COLOR_GREEN );
			BSP_LCD_DrawLine( uiDispCentX, uiDispCentY, uiDispCentX + 40, uiDispCentY);
			BSP_LCD_DrawCircle( BSP_LCD_GetXSize() - 15, 15, 10);
			break;
		case JOY_UP:
			BSP_LCD_SetTextColor( LCD_COLOR_GREEN );
			BSP_LCD_DrawLine( uiDispCentX, uiDispCentY, uiDispCentX, uiDispCentY - 40 );
			BSP_LCD_DrawCircle(15, 15, 10);
			break;
		} // end switch( oJoyState )
 
		//
		// Button reading - the button is hidden under the display
		// uiButtState = BSP_PB_GetState( BUTTON_USER );
 
		//
		// Timming - second counter
		if( (HAL_GetTick() - uiTicks) > 1000)
		{
			uint8_t chArr[40];
			uiTicks = HAL_GetTick();
			uiSec++;
 
			BSP_LCD_SetFont( &Font8 );
			BSP_LCD_SetTextColor( LCD_COLOR_RED );
			sprintf( (char *)chArr, (char *)"  %d   ", (int)uiSec );
			BSP_LCD_DisplayStringAtLine( 14, chArr);
		} // END if( (HAL_GetTick() - uiTicks) > 1000)
 
		//
		// string manipulation example
		if( uiSerRecv == 0x30 )
		{
			int iResult;
			char chArrTmpData[] = "DRAW:CIRCLE 64,80,30";
 
			// !! has to be here
			uiSerRecv = 0;
 
			iResult = strstr(chArrTmpData, "DRAW");
			if( iResult )
			{
				int iXs, iYs, iRad;
				int iResult;
 
				iResult = sscanf( chArrTmpData, "DRAW:CIRCLE %d,%d,%d", &iXs, &iYs, &iRad );
				if( iResult > 2 )
				{
					BSP_LCD_DrawCircle( iXs, iYs, iRad );
				}
			}
		} // END string manipulation example
 
	} // END while(1)
 
} // END main

courses/be5b99cpl/labs/lab08.txt · Last modified: 2021/12/15 16:33 by amjadara