AnsweredAssumed Answered

stm32f101x lcd interfacing using SPI

Question asked by r_s.adarsh on Jan 30, 2015
hello everyone,
  I am trying to interface stm32f101ret6 with lcd using SPI.I am using mainly 3 pins NSS,CLK and MOSI of SPI1. After interfacing nothing is displayed on the LCD and I checked in CRO I am not getting any signal across SPI1 pins at controller.
please find the attached code below and please do rectify it if anything wrong.

MAIN.C

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "STM32vldiscovery.h"
#include "stm32_eval_lcd.h"

/** @addtogroup Examples
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
//GPIO_InitTypeDef GPIO_InitStructure;

/* Private function prototypes -----------------------------------------------*/
void PrintLogo(void);
void Delay(uint32_t nCount);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */    
      
  /* Configure all unused GPIO port pins in Analog Input mode (floating input
     trigger OFF), this will reduce the power consumption and increase the device
     immunity against EMI/EMC *************************************************/
 
  uint8_t i = 0;
  STM32_EVAL_LCD_Init();

  /* Clear LCD */
  LCD_Clear();

  LCD_SetCursorPos(LCD_LINE1, 0);
  LCD_Print("SPI-LCD example");  
 
  /* Display "moving" ST logo */
  for (i = 1; i < 8; i++)
  {
    PrintLogo();
    Delay(0xFFFF);
  }
 
  LCD_SetCursorPos(LCD_LINE2, 0);
  LCD_Print("               ");

  LCD_DisplayLogo(0x93);
  Delay(600);
  while(1)
  {}

}

/**
  * @brief  Inserts a delay time.
  * @param  nCount: specifies the delay time length.
  * @retval None
  */
void Delay(uint32_t nCount)
{
    /* Decrement nCount value */
    while (nCount != 0)
    {
        nCount--;
    }
}

void PrintLogo(void)
{
  static uint8_t logo_pos = 0x90;
  static int8_t logo_pos_index = 1;

  LCD_SetCursorPos(LCD_LINE2, 0);
  LCD_Print("               ");

  LCD_DisplayLogo(logo_pos);
  logo_pos += logo_pos_index;
  if (logo_pos > 0x95)
  {
    logo_pos -= 2;
    logo_pos_index = -1;
  }
  if (logo_pos < 0x90)
  {
    logo_pos += 2;
    logo_pos_index = 1;
  }
}
#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

STM32_eval_lcd.c

/* Includes ------------------------------------------------------------------*/
#include "stm32_eval_lcd.h"
#include "stm32f10x_spi.h"

/** @addtogroup Utilities
  * @{
  */

/** @defgroup STM32_EVAL_LCD
  * @{
  */

/** @defgroup STM32_EVAL_LCD_Private_Types
  * @{
  */
/**
  * @}
  */

/** @defgroup STM32_EVAL_LCD_Private_Defines
  * @{
  */
void RCC_Configuration(void);
void GPIO_Configuration(void);
#define STATUS_TYPE 0xFC

/* This table contains the "S" of ST logo */
const uint8_t S_CGRAM[] =
  {
    /* 0~7 */
    0x03, 0xff,
    0x02, 0x00,
    0x04, 0x00,
    0x04, 0x00,
    0x0c, 0x7f,
    0x0c, 0x7f,
    0x1c, 0x3f,
    0x1e, 0x1f,
    /* 8~15 */
    0x3f, 0x0f,
    0x3f, 0x87,
    0x7f, 0xc3,
    0x7f, 0xe3,
    0x00, 0x03,
    0x00, 0x03,
    0x00, 0x07,
    0xff, 0xfe,
  };

/* This table contains the "T" of ST logo */
const uint8_t T_CGRAM[] =
  {
    /* 0~7 */
    0xff, 0xff,
    0x00, 0x00,
    0x00, 0x00,
    0x00, 0x00,
    0xf8, 0xf8,
    0xf0, 0xf8,
    0xf0, 0xf0,
    0xf0, 0xf0,
    /* 8~15 */
    0xe1, 0xe0,
    0xe3, 0xe0,
    0xc3, 0xc0,
    0xc7, 0xc0,
    0x87, 0xc0,
    0x8f, 0x80,
    0x0f, 0x80,
    0x1f, 0x00
  };

/**
  * @}
  */

/** @defgroup STM32_EVAL_LCD_Private_Macros
  * @{
  */
/**
  * @}
  */

/** @defgroup STM32_EVAL_LCD_Private_Variables
  * @{
  */
/**
  * @}
  */

/** @defgroup STM32_EVAL_LCD_Private_Function_Prototypes
  * @{
  */

static void LCD_DisplayCGRAM0(uint8_t address, uint8_t *ptrTable);
static void LCD_DisplayCGRAM1(uint8_t address, uint8_t *ptrTable);
/**
  * @brief  The delay function implemented in this driver is not a precise one,
  *         however it allows the insertion of 1ms delay when Fcpu is 16Mhz if
  *         the passed parameter is 0x4000.
  *         Any change in system clock frequency will impact this delay duration.
  *        
  *         User is given the possibility to develop a customized and accurate
  *         delay function by the mean of timers for example.
  *         Uncommenting " #define USE_Delay" line in the stm8s_eval_lcd.h file
  *         will allow the consideration of the new function by this driver.
  */     
static void delay(__IO uint32_t nCount);
/**
  * @}
  */

/** @defgroup STM8S_EVAL_LCD_Private_Functions
  * @{
  */

/**
  * @brief  Initialize the LCD
  * @param  None
  * @retval None
  */

void STM32_EVAL_LCD_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
 
 
  GPIO_InitStructure.GPIO_Pin = LCD_NCS_PIN ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 
 
  /* Configure SPI1 pins: SCK and MOSI only to their Alternative (SPI) function */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_SCK | GPIO_Pin_MOSI;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* SPI1 configuration ------------------------------------------------------*/
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
 
  /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);

  /* Set the LCD in TEXT mode */
  LCD_SendByte(COMMAND_TYPE, SET_TEXT_MODE);

  /* Enable the display */
  LCD_SendByte(COMMAND_TYPE, DISPLAY_ON);

  /* Clear the LCD */
  LCD_SendByte(COMMAND_TYPE, DISPLAY_CLR);

  /* Delay required to complete LCD clear command */
  _delay_(0x4000); /* 1ms _delay_ using Fcpu = 16Mhz*/

  /* Select the entry mode type */
  LCD_SendByte(COMMAND_TYPE, ENTRY_MODE_SET_INC);
 
}

 

/**
  * @brief  Set the LCD cursor to the specified location
  * @param  Line : line where the cursor will be set (LCD_LINE1 or LCD_LINE2)
  * @param  Offset : is the position offset (only even position are supported)
  * @retval None
  */
void LCD_SetCursorPos(uint8_t Line, uint8_t Offset)
{
  LCD_SendByte(COMMAND_TYPE, (uint8_t)(Line + Offset));
}

/**
  * @brief  Send a byte to LCD
  * @param  DataType Type of Data to be sent
  * @param  DataToSend Data to be sent
  * @retval None
  */
void LCD_SendByte(uint8_t DataType, uint8_t DataToSend)
{
  /* Enable access to LCD */
  LCD_NCS_HIGH();

  /* Send Synchro/Mode byte */
  //LCD_SPISendByte(DataType);
  SPI_I2S_SendData(SPI1, DataToSend);

  /* Send byte high nibble */
  SPI_I2S_SendData(SPI1,(uint8_t)(DataToSend & (uint8_t)0xF0));

  /* Send byte low nibble */
  SPI_I2S_SendData(SPI1,(uint8_t)((uint8_t)(DataToSend << 4) & (uint8_t)0xF0));
  _delay_(80);

  /* Disable access to LCD */
  LCD_NCS_LOW();
}

/**
  * @brief  Clear the LCD
  * @param  None
  * @retval None
  */
void LCD_Clear(void)
{
  LCD_SendByte(COMMAND_TYPE, DISPLAY_CLR); /* Clear the LCD */

  /* Delay required to complete LCD clear command */
  _delay_(0x4000); /* 1ms _delay_ using Fcpu = 16Mhz*/

}

/**
  * @brief  Display a string from current position of the LCD cursor
  * @param  ptr : Pointer to the string to display
  * @retval None
  */
void LCD_Print(uint8_t *ptr)
{
  __IO uint8_t charindex = 0x00;

  /* Display the string */
  while ((*ptr) && (charindex < 0x0F))
  {
    LCD_SendByte(DATA_TYPE, *ptr++);
    charindex++;
  }
}

/**
  * @brief  Display a string in rolling mode
  * @param  Line : line used for displaying the text (LCD_LINE1 or LCD_LINE2)
  * @param  ptr : Pointer to the text to display
  * @param  speed : Rolling speed
  * @retval
  * None
  */
void LCD_RollString(uint8_t Line, uint8_t *ptr, uint16_t speed)
{

  uint8_t CharPos = 0;
  uint8_t *ptr2;

  /* Set cursor position at beginning of line */
  LCD_SendByte(COMMAND_TYPE, Line);

  ptr2 = ptr;

  /* Display each character of the string */
  while (*ptr2 != 0)
  {
    if (*ptr != 0)
    {
      LCD_SendByte(DATA_TYPE, *ptr);
      ptr++;
    }
    else
    {
      LCD_SendByte(DATA_TYPE, ' ');
    }

    CharPos++;

    if (CharPos == LCD_LINE_MAX_CHAR)
    {
      _delay_(speed);

      /* Select the line to be cleared */
      LCD_SendByte(COMMAND_TYPE, Line);

      /* Clear the selected line */
      for (CharPos = 0; CharPos < LCD_LINE_MAX_CHAR; CharPos++)
      {
        LCD_SendByte(DATA_TYPE, ' ');
      }
      LCD_SendByte(COMMAND_TYPE, Line);
      CharPos = 0;
      ptr2++;
      ptr = ptr2;
    }
  }
}

/**
  * @brief  Display ST logo
  * @param  address : Display address (LINE1:0x80-0x87 and LINE2:0x90-0x97)
  * @retval None
  */
void LCD_DisplayLogo(uint8_t address)
{
  LCD_DisplayCGRAM0(address, (uint8_t*)S_CGRAM);
  LCD_DisplayCGRAM1(address, (uint8_t*)T_CGRAM);
}

/**
  * @}
  */

/** @addtogroup LCD_Private_Functions
  * @{
  */

/**
  * @brief  Display CGRAM on even address
  * @param  address : Display address
  * @param  ptrTable : Pointer a the CGRAM table to be displayed
  * @retval None
  */
static void LCD_DisplayCGRAM0(uint8_t address, uint8_t *ptrTable)
{

  uint8_t u = 32; /* Nb byte in the table */

  /* Set CGRAM Address */
  LCD_SendByte(COMMAND_TYPE, (uint8_t)0x40);

  while (u)
  {
    LCD_SendByte(DATA_TYPE, ptrTable[32 - u]);
    u--;
  }

  /* Setup Display Address */
  LCD_SendByte(COMMAND_TYPE, address);
  LCD_SendByte(DATA_TYPE, (uint8_t)0x00);
  LCD_SendByte(DATA_TYPE, (uint8_t)0x00);

}

/**
  * @brief  Display CGRAM on odd address
  * @param  address : Display address
  * @param  ptrTable : Pointer a the CGRAM table to be displayed
  * @retval None
  */
static void LCD_DisplayCGRAM1(uint8_t address, uint8_t *ptrTable)
{

  uint8_t u = 32; /* Nb byte in the table */

  /* Set CGRAM Address */
  LCD_SendByte(COMMAND_TYPE, (uint8_t)((uint8_t)0x40 | (uint8_t)0x10));

  while (u)
  {
    LCD_SendByte(DATA_TYPE, ptrTable[32 - u]);
    u--;
  }

  /* Setup Display Address */
  LCD_SendByte(COMMAND_TYPE, (uint8_t)(address + 1));
  LCD_SendByte(DATA_TYPE, (uint8_t)0x00);
  LCD_SendByte(DATA_TYPE, (uint8_t)0x02);

}

#ifndef USE_Delay
/**
  * @brief  Inserts a delay time.
  *         The delay function implemented in this driver is not a precise one,
  *         however it allows the insertion of 1ms delay when Fcpu is 16Mhz if
  *         the passed parameter is 0x4000.
  *         Any change in system clock frequency will impact this delay duration.
  *        
  *         User is given the possibility to develop a customized and accurate
  *         delay function by the mean of timers for example.
  *         Uncommenting " #define USE_Delay" line in the stm8s_eval_lcd.h file
  *         will allow the consideration of the new function by this driver.
  *   
  * @param  nCount: specifies the _delay_ time length.
  * @retval None
  */
static void delay(__IO uint32_t nCount)
{
  /* Decrement nCount value */
  while (nCount != 0)
  {
    nCount--;
  }
}
#endif /* USE_Delay*/


STM32_eval_lcd.h

 #define LCD_NCS_PIN                      GPIO_Pin_4
//#define GPIO_Pin_DC                       GPIO_Pin_6
//#define GPIO_Pin_RST                      GPIO_Pin_3
#define GPIO_Pin_SCK                      GPIO_Pin_5
#define GPIO_Pin_MOSI                     GPIO_Pin_7
#define LCD_SPI_GPIO_PORT                 GPIOA
/**
  * @}
  */

/* LCD managed as 2 Lines of 15 characters (2Lines * 15Char) */
#define LCD_LINE_MAX_CHAR    ((uint8_t)15)
#define LCD_LINE1            ((uint8_t)0x80)
#define LCD_LINE2            ((uint8_t)0x90)

/* LCD Commands */
#define COMMAND_TYPE         ((uint8_t)0xF8)
#define DATA_TYPE            ((uint8_t)0xFA)
#define SET_TEXT_MODE        ((uint8_t)0x30) /* 8-Bits Interface, Normal inst., Text mode */
#define SET_EXTENDED_INST    ((uint8_t)0x34)
#define SET_GRAPHIC_MODE     ((uint8_t)0x36) /* 8-Bits Interface, Extended inst., Graphic mode */
#define DISPLAY_ON           ((uint8_t)0x0C) /* Cursor and blink off */
#define DISPLAY_OFF          ((uint8_t)0x08)
#define DISPLAY_CLR          ((uint8_t)0x01)
#define ENTRY_MODE_SET_INC   ((uint8_t)0x06)

/** @defgroup STM8S_EVAL_LCD_Exported_Macros
  * @{
  */

/**
  * @brief  Deselect LCD: ChipSelect pin low : LCD disabled
  */ 
#define LCD_NCS_LOW()     GPIO_ResetBits(LCD_SPI_GPIO_PORT, LCD_NCS_PIN)

/**
  * @brief  Select LCD : ChipSelect pin high : LCD enabled  
  */
#define LCD_NCS_HIGH()     GPIO_SetBits(LCD_SPI_GPIO_PORT,LCD_NCS_PIN)

/**
  * @}
  */
 
/* Exported functions --------------------------------------------------------*/
void STM32_EVAL_LCD_Init(void);
void LCD_BacklightCmd(FunctionalState NewState);
void LCD_SetCursorPos(uint8_t Line, uint8_t Offset);
void LCD_SendByte(uint8_t DataType, uint8_t DataToSend);
void LCD_Clear(void);
void LCD_Print(uint8_t *ptr);
void LCD_DisplayLogo(uint8_t address);
void LCD_RollString(uint8_t Line, uint8_t *ptr, uint16_t speed);

#endif /* __STM32_EVAL_LCD_H */


.

Outcomes