Search code examples
embeddedstm32ldiscovery

Initialize SSD1305 OLED with STM32f3discovery


I'm trying to run a OLED WEX012864GL based on SSD1305 OLED controller with a stm32f3discovery board. I've conntected the board with a 31 pin row with first pin binding on the 3V and the last on the PD9 (this is the top-left pin row of the board). The code is looking like that:

#include "stm32f30x.h"

/*--------- PORT-A ----------------------------*/
#define D1      GPIO_Pin_1
#define D1_PORT GPIOA
#define D2      GPIO_Pin_3
#define D2_PORT GPIOA
#define D4      GPIO_Pin_5
#define D4_PORT GPIOA
#define D5      GPIO_Pin_7
#define D5_PORT GPIOA

/*-------- PORT-B ----------------------------*/
#define D7      GPIO_Pin_1
#define D7_PORT GPIOB
#define RD      GPIO_Pin_11 //8080 Mode RD  Display-Pin:14  PD3
#define RD_PORT GPIOB
#define DISP GPIO_Pin_15
#define DISP_PORT GPIOB

/*-------- PORT-C ----------------------------*/
#define D0    GPIO_Pin_3
#define D0_PORT GPIOC
#define D6      GPIO_Pin_5
#define D6_PORT GPIOC

/*-------- PORT-E ----------------------------*/
#define CS      GPIO_Pin_7  //PORT-D    Display-Pin:19          PD6
#define CS_PORT GPIOE
#define RES     GPIO_Pin_11 //PORT-B    Display-Pin:20                  PC10
#define RES_PORT GPIOE
#define WR      GPIO_Pin_13 //8080 Mode WR      Display-Pin:15  PD2
#define WR_PORT GPIOE
#define D_C     GPIO_Pin_15 //PORT-C    Display-Pin:18          PC12
#define D_C_PORT GPIOE

/*-------- PORT-F ----------------------------*/
#define D3      GPIO_Pin_4
#define D3_PORT GPIOF



#define GPIO_PINS_PORTA_OUT (D1 | D2 | D4 | D5 )
#define GPIO_PINS_PORTB_OUT (D7 | RD| DISP)
#define GPIO_PINS_PORTC_OUT (D0 | D6  )
#define GPIO_PINS_PORTE_OUT (CS| D_C | RES | WR)
#define GPIO_PINS_PORTF_OUT (D3)

#define GPIO_PINS_PORTA_IN (D1 | D2 | D4 | D5 )
#define GPIO_PINS_PORTB_IN  (D7)
#define GPIO_PINS_PORTC_IN  (D0 | D6 )
#define GPIO_PINS_PORTF_IN  (D3)

#define GET_BIT(cmd,bitps) (BitAction)((((uint8_t)cmd&((uint8_t)1)<<bitps))>>bitps)
#define GET_INPUT_BIT(port,pin,pos) ((uint8_t)(GPIO_ReadOutputDataBit(port,pin)<<pos))

#define MOD_GPIO_WRITE(cmd) GPIO_WriteBit(D0_PORT,D0,GET_BIT(cmd,0)); \
                GPIO_WriteBit(D1_PORT,D1,GET_BIT(cmd,1)); \
                GPIO_WriteBit(D2_PORT,D2,GET_BIT(cmd,2)); \
                GPIO_WriteBit(D3_PORT,D3,GET_BIT(cmd,3)); \
                GPIO_WriteBit(D4_PORT,D4,GET_BIT(cmd,4)); \
                GPIO_WriteBit(D5_PORT,D5,GET_BIT(cmd,5)); \
                GPIO_WriteBit(D6_PORT,D6,GET_BIT(cmd,6)); \
                GPIO_WriteBit(D7_PORT,D7,GET_BIT(cmd,7))  \

#define MOD_GPIO_READ() GET_INPUT_BIT(D0_PORT,D0,0)| GET_INPUT_BIT(D1_PORT,D1,1) | GET_INPUT_BIT(D2_PORT,D2,2)| \
                                    GET_INPUT_BIT(D3_PORT,D3,3) | GET_INPUT_BIT(D4_PORT,D4,4) | GET_INPUT_BIT(D5_PORT,D5,5) | \
                                    GET_INPUT_BIT(D6_PORT,D6,6) | GET_INPUT_BIT(D7_PORT,D7,7)

//proto
void Delay(uint32_t nTime);
void TimingDelay_Decrement(void);


static __IO uint32_t TimingDelay;
//Init the used Ports
static void Init_Ports_Write( void ) {
    //D7-0 outputs
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTA_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTB_OUT;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTC_OUT;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTE_OUT;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTF_OUT;
    GPIO_Init(GPIOF, &GPIO_InitStructure);

}

static void Init_Ports_Read( void ) {
    //D7-0 inputs
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTA_IN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTB_IN;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTC_IN;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTF_IN;
    GPIO_Init(GPIOF, &GPIO_InitStructure);

}

static void Init_Ports( void ) {

    //init the System
    SystemInit();   
    //Takt für IO-Port A & C aktivieren 
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE | RCC_AHBPeriph_GPIOF, ENABLE);

    if (SysTick_Config(SystemCoreClock / 1000000)) { /* Setup SysTick Timer for 1 µsec interrupts (msec/1000000) */
    while (1);                                  /* Capture error */
  } 

  Init_Ports_Write();

    GPIO_ResetBits(GPIOA, GPIO_PINS_PORTA_OUT);
    GPIO_ResetBits(GPIOB, GPIO_PINS_PORTB_OUT);
    GPIO_ResetBits(GPIOC, GPIO_PINS_PORTC_OUT);
    GPIO_ResetBits(GPIOE, GPIO_PINS_PORTE_OUT);
    GPIO_ResetBits(GPIOF, GPIO_PINS_PORTF_OUT);
    //set all neg pins

    GPIO_SetBits(RES_PORT, RES);
    GPIO_SetBits(CS_PORT, CS);
    GPIO_SetBits(WR_PORT, WR);
    GPIO_SetBits(RD_PORT, RD);

  Delay(500000);
}

static void oled_Command_25664(uint8_t cmd){
    //write bit by bit
    MOD_GPIO_WRITE(cmd);
    GPIO_SetBits(RD_PORT, RD);
    GPIO_ResetBits(D_C_PORT, D_C);
    GPIO_ResetBits(CS_PORT, CS);
    GPIO_ResetBits(WR_PORT, WR);
    __nop();__nop();__nop();__nop();__nop();__nop();
  GPIO_SetBits(WR_PORT, WR);
    __nop();__nop();__nop();__nop();__nop();__nop();
    GPIO_SetBits(CS_PORT, CS);
    __nop();

}
static void oled_Data_25664(uint8_t data){
    MOD_GPIO_WRITE(data);
    GPIO_SetBits(RD_PORT, RD);
    GPIO_SetBits(D_C_PORT, D_C);
    GPIO_ResetBits(CS_PORT, CS);
    GPIO_ResetBits(WR_PORT, WR);
    __nop();__nop();__nop();__nop();__nop();__nop();
    GPIO_SetBits(WR_PORT, WR);
    __nop();__nop();__nop();__nop();__nop();__nop();
    GPIO_SetBits(CS_PORT, CS);
    __nop();

}

static uint8_t oled_Read_Data_25664(){
    uint8_t read_data;
    //Set the D7-0 as inputs
    Init_Ports_Read();
    //set WR high
    read_data = MOD_GPIO_READ();
    GPIO_SetBits(WR_PORT, WR);
    GPIO_SetBits(D_C_PORT, D_C);
    GPIO_ResetBits(CS_PORT, CS);
    GPIO_ResetBits(RD_PORT, RD);
    __nop();__nop();__nop();__nop();__nop();__nop();
    GPIO_SetBits(RD_PORT, RD);
    GPIO_ResetBits(RD_PORT, RD);
    __nop();__nop();__nop();__nop();__nop();__nop();
    read_data = MOD_GPIO_READ();
    //Set the D7-0 as outputs
    GPIO_SetBits(RD_PORT, RD);
    __nop();__nop();__nop();__nop();__nop();__nop();
    GPIO_ResetBits(RD_PORT, RD);
    __nop();__nop();__nop();__nop();__nop();__nop();
    //read
    read_data = MOD_GPIO_READ();
    GPIO_SetBits(D_C_PORT, D_C);
    GPIO_SetBits(CS_PORT, CS);
    Init_Ports_Write();

    return read_data;
}

void Delay(uint32_t nTime)
{ 
  TimingDelay = nTime;
  while(TimingDelay != 0);
}
/* Decrements the TimingDelay variable.*/
void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00) TimingDelay--;
}
void SysTick_Handler(void)
{
  TimingDelay_Decrement();
}
/**
  * @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_stm32f30x.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f30x.c file
     */     
    Init_Ports();
    oled_Command_25664(0xAF);//--turn on oled panel
    oled_Command_25664(0xA5);
    oled_Read_Data_25664();

  while(1)
  {
    oled_Command_25664(0xA5);
    Delay(500000);
    oled_Command_25664(0xA4);
    Delay(500000);

  }
}

When I run the code on the board, a very bizarre result is observed - the display is not working, till I press the reset button and the there the screen light up for short and then back down. What could be the reason for that?


Solution

  • The solution was that the DISP signal should be left high-Z or the port is not initialized. The complete code is looking like that:

    #include "stm32f30x.h"
    
    /*--------- PORT-A ----------------------------*/
    #define D1      GPIO_Pin_1
    #define D1_PORT GPIOA
    #define D2      GPIO_Pin_3
    #define D2_PORT GPIOA
    #define D4      GPIO_Pin_5
    #define D4_PORT GPIOA
    #define D5      GPIO_Pin_7
    #define D5_PORT GPIOA
    
    /*-------- PORT-B ----------------------------*/
    #define D7      GPIO_Pin_1
    #define D7_PORT GPIOB
    #define RD      GPIO_Pin_11 //8080 Mode RD  Display-Pin:14  PD3
    #define RD_PORT GPIOB
    #define DISP GPIO_Pin_15
    #define DISP_PORT GPIOB
    
    /*-------- PORT-C ----------------------------*/
    #define D0    GPIO_Pin_3
    #define D0_PORT GPIOC
    #define D6      GPIO_Pin_5
    #define D6_PORT GPIOC
    
    /*-------- PORT-E ----------------------------*/
    #define CS      GPIO_Pin_7  //PORT-D    Display-Pin:19          PD6
    #define CS_PORT GPIOE
    #define RES     GPIO_Pin_11 //PORT-B    Display-Pin:20                  PC10
    #define RES_PORT GPIOE
    #define WR      GPIO_Pin_13 //8080 Mode WR      Display-Pin:15  PD2
    #define WR_PORT GPIOE
    #define D_C     GPIO_Pin_15 //PORT-C    Display-Pin:18          PC12
    #define D_C_PORT GPIOE
    
    /*-------- PORT-F ----------------------------*/
    #define D3      GPIO_Pin_4
    #define D3_PORT GPIOF
    
    
    
    #define GPIO_PINS_PORTA_OUT (D1 | D2 | D4 | D5 )
    #define GPIO_PINS_PORTB_OUT (D7 | RD )
    #define GPIO_PINS_PORTC_OUT (D0 | D6  )
    #define GPIO_PINS_PORTE_OUT (CS| D_C | RES | WR)
    #define GPIO_PINS_PORTF_OUT (D3)
    
    #define GPIO_PINS_PORTA_IN (D1 | D2 | D4 | D5 )
    #define GPIO_PINS_PORTB_IN  (D7)
    #define GPIO_PINS_PORTC_IN  (D0 | D6 )
    #define GPIO_PINS_PORTF_IN  (D3)
    
    #define GET_BIT(cmd,bitps) (BitAction)((((uint8_t)cmd&((uint8_t)1)<<bitps))>>bitps)
    #define GET_INPUT_BIT(port,pin,pos) ((uint8_t)(GPIO_ReadOutputDataBit(port,pin)<<pos))
    
    #define MOD_GPIO_WRITE(cmd) GPIO_WriteBit(D0_PORT,D0,GET_BIT(cmd,0)); \
                    GPIO_WriteBit(D1_PORT,D1,GET_BIT(cmd,1)); \
                    GPIO_WriteBit(D2_PORT,D2,GET_BIT(cmd,2)); \
                    GPIO_WriteBit(D3_PORT,D3,GET_BIT(cmd,3)); \
                    GPIO_WriteBit(D4_PORT,D4,GET_BIT(cmd,4)); \
                    GPIO_WriteBit(D5_PORT,D5,GET_BIT(cmd,5)); \
                    GPIO_WriteBit(D6_PORT,D6,GET_BIT(cmd,6)); \
                    GPIO_WriteBit(D7_PORT,D7,GET_BIT(cmd,7))  \
    
    #define MOD_GPIO_READ() GET_INPUT_BIT(D0_PORT,D0,0)| GET_INPUT_BIT(D1_PORT,D1,1) | GET_INPUT_BIT(D2_PORT,D2,2)| \
                                        GET_INPUT_BIT(D3_PORT,D3,3) | GET_INPUT_BIT(D4_PORT,D4,4) | GET_INPUT_BIT(D5_PORT,D5,5) | \
                                        GET_INPUT_BIT(D6_PORT,D6,6) | GET_INPUT_BIT(D7_PORT,D7,7)
    
    //proto
    void Delay(uint32_t nTime);
    void TimingDelay_Decrement(void);
    
    
    static __IO uint32_t TimingDelay;
    //Init the used Ports
    static void Init_Ports_Write( void ) {
        //D7-0 outputs
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTA_OUT;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTB_OUT;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTC_OUT;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTE_OUT;
        GPIO_Init(GPIOE, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTF_OUT;
        GPIO_Init(GPIOF, &GPIO_InitStructure);
    
    }
    
    static void Init_Ports_Read( void ) {
        //D7-0 inputs
        GPIO_InitTypeDef GPIO_InitStructure;
    
        GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTA_IN;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTB_IN;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTC_IN;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin     = GPIO_PINS_PORTF_IN;
        GPIO_Init(GPIOF, &GPIO_InitStructure);
    
    }
    
    static void Init_Ports( void ) {
    
        //init the System
        SystemInit();   
        //Takt für IO-Port A & C aktivieren 
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE | RCC_AHBPeriph_GPIOF, ENABLE);
    
        if (SysTick_Config(SystemCoreClock / 1000000)) { /* Setup SysTick Timer for 1 µsec interrupts (msec/1000000) */
        while (1);                                  /* Capture error */
      } 
    
      Init_Ports_Write();
    
        GPIO_ResetBits(GPIOA, GPIO_PINS_PORTA_OUT);
        GPIO_ResetBits(GPIOB, GPIO_PINS_PORTB_OUT);
        GPIO_ResetBits(GPIOC, GPIO_PINS_PORTC_OUT);
        GPIO_ResetBits(GPIOE, GPIO_PINS_PORTE_OUT);
        GPIO_ResetBits(GPIOF, GPIO_PINS_PORTF_OUT);
        //set all neg pins
    
        GPIO_SetBits(RES_PORT, RES);
        GPIO_SetBits(CS_PORT, CS);
        GPIO_SetBits(WR_PORT, WR);
        GPIO_SetBits(RD_PORT, RD);
    
      Delay(500000);
    }
    
    static void oled_Command_25664(uint8_t cmd){
        //write bit by bit
        MOD_GPIO_WRITE(cmd);
        GPIO_SetBits(RD_PORT, RD);
        GPIO_ResetBits(D_C_PORT, D_C);
        GPIO_ResetBits(CS_PORT, CS);
        GPIO_ResetBits(WR_PORT, WR);
        __nop();__nop();__nop();__nop();__nop();__nop();
      GPIO_SetBits(WR_PORT, WR);
        __nop();__nop();__nop();__nop();__nop();__nop();
        GPIO_SetBits(CS_PORT, CS);
        __nop();
    
    }
    static void oled_Data_25664(uint8_t data){
        MOD_GPIO_WRITE(data);
        GPIO_SetBits(RD_PORT, RD);
        GPIO_SetBits(D_C_PORT, D_C);
        GPIO_ResetBits(CS_PORT, CS);
        GPIO_ResetBits(WR_PORT, WR);
        __nop();__nop();__nop();__nop();__nop();__nop();
        GPIO_SetBits(WR_PORT, WR);
        __nop();__nop();__nop();__nop();__nop();__nop();
        GPIO_SetBits(CS_PORT, CS);
        __nop();
    
    }
    
    static uint8_t oled_Read_Data_25664(){
        uint8_t read_data;
        //Set the D7-0 as inputs
        Init_Ports_Read();
        //set WR high
        read_data = MOD_GPIO_READ();
        GPIO_SetBits(WR_PORT, WR);
        GPIO_SetBits(D_C_PORT, D_C);
        GPIO_ResetBits(CS_PORT, CS);
        GPIO_ResetBits(RD_PORT, RD);
        __nop();__nop();__nop();__nop();__nop();__nop();
        GPIO_SetBits(RD_PORT, RD);
        GPIO_ResetBits(RD_PORT, RD);
        __nop();__nop();__nop();__nop();__nop();__nop();
        read_data = MOD_GPIO_READ();
        //Set the D7-0 as outputs
        GPIO_SetBits(RD_PORT, RD);
        __nop();__nop();__nop();__nop();__nop();__nop();
        GPIO_ResetBits(RD_PORT, RD);
        __nop();__nop();__nop();__nop();__nop();__nop();
        //read
        read_data = MOD_GPIO_READ();
        GPIO_SetBits(D_C_PORT, D_C);
        GPIO_SetBits(CS_PORT, CS);
        Init_Ports_Write();
    
        return read_data;
    }
    
    void Delay(uint32_t nTime)
    { 
      TimingDelay = nTime;
      while(TimingDelay != 0);
    }
    /* Decrements the TimingDelay variable.*/
    void TimingDelay_Decrement(void)
    {
      if (TimingDelay != 0x00) TimingDelay--;
    }
    void SysTick_Handler(void)
    {
      TimingDelay_Decrement();
    }
    /**
      * @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_stm32f30x.s) before to branch to application main.
           To reconfigure the default setting of SystemInit() function, refer to
           system_stm32f30x.c file
         */     
      Init_Ports();
        oled_Command_25664(0xAF);//--turn on oled panel
        oled_Command_25664(0xA4);
        oled_Read_Data_25664();
    
      while(1)
      {
        oled_Command_25664(0xA5);
             Delay(500000);
            oled_Command_25664(0xA4);
             Delay(500000);
      }
    }