AnsweredAssumed Answered

LCD init problem

Question asked by novak.matej on Nov 17, 2011
Latest reply on Nov 22, 2011 by ah_teck.tan
Hello,

I'm trying to run a sharp LM20A21 lcd display with the HD44780 controller. I've looked at all the lcd discussions that are present here, but none solved my problem. My program implements USART/LCD interface, but the lcd itself is the problem. Basically, it acts really weird. Sometimes it inits after i power it down and up again, but mostly it does nothing or fills the whole screen with one character that I tried to write.

I'm using the 8 bit mode, cursor flash on. DB0-7 are on pins PA0-7, RS is on PC2, E is on PC3. R/W is grounded, since I only need to perform write operations. Outputs are configured to 10MHz. The cortex m3 runs at 24MHz.

I've commented or left out the irrelevant parts of my code. Here are the revelant bits of my code:
[CODE]
/* Control codes for LCD_INST */
#define LCD_FUNC         0x38 /* set the lcd function - 8bit, dual line*/
#define LCD_DIS_MOD    0xF  /* set lcd mode -cursor on,cursor flash on, display on */
#define LCD_DAT_INP    0x6     /* set lcd data input config - cursor increment*/
#define    mS               1598    /* empirical constant for one ms*/
#define DEBOUNCE_TIME  1
#define LCD_CHAR_NUMBER 40
#define DECADIC_PERIOD 200000

#define LCD_D4 GPIO_Pin_3  // PC3

typedef enum { LCD_DATA,LCD_INSTR} lcd_regimes;
typedef enum { SETUP,READY,RUNNING} program_status;

unsigned char display_contents[LCD_CHAR_NUMBER];
lcd_regimes current_regime;
program_status current_status;
unsigned char    set_time;
unsigned char    time_mem = 5;

static void RCC_Configuration(void);
static void GPIO_Configuration(void);
static void USART_Configuration(void);
static void LCD_Configuration(void);
static void delay_ms(unsigned int);
static void delay_us(unsigned int);

static void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
static uint8_t USART_ReceiveData(void);
static void sendData(unsigned char*,lcd_regimes*);
static void LCD_Clear(void);
static void Display(void);
static void Read_and_Handle_Buttons(void);
static void Read_and_Handle_USART(void);
static void fill_lcd_contents(void);
static void decadic_shift(int);
static unsigned char button_is_pressed(unsigned char button_id);

int main(void){

    int i, p_flag = 0;
    current_regime = LCD_DATA;
    current_status = SETUP;

    RCC_Configuration();

    GPIO_Configuration();
   
    USART_Configuration();

    CLEAR_BIT(GPIOC->ODR, 0x8);    /*set E to low*/

    LCD_Configuration();
    
    set_time = 5;         /*Initial time value*/

    for (i = 0; i < LCD_CHAR_NUMBER; i++){

        display_contents[i] = ' ';
    }
    

    fill_lcd_contents();
    Display();

    while(1){
        
        switch (current_status){
            case SETUP:
                //do stuff 
            break;
            case READY:
                //do stuff
            break;
            case RUNNING:
               ...// do stuff
            break;
        }
    }
}

static void Display(void){

    int i;

    LCD_Clear();
    current_regime = LCD_DATA;
    for (i = 0; i < LCD_CHAR_NUMBER; i++){
                
        sendData(&display_contents[i],&current_regime);
        delay_ms(1);
    }
}

/*DELAY TIMES ARE HIGLY EXAGGERATED SINCE I'M GETTING DESPERATE*/
static void LCD_Configuration(void){

    unsigned char    init_data = LCD_FUNC;    /* set the lcd function - 8bit, dual line*/
    current_regime = LCD_INSTR;
       
    delay_ms(60);
    /*LCD inicialization sequence*/
    sendData(&init_data,&current_regime);
    init_data = LCD_DIS_MOD;                   /* set lcd mode -cursor on,cursor flash on, display on */
    delay_ms(60);    
    sendData(&init_data,&current_regime);
    init_data = LCD_DAT_INP;                /* set lcd data input config - cursor increment*/
    delay_ms(60);
    sendData(&init_data,&current_regime);
    delay_ms(60);
    LCD_Clear();
    delay_ms(60);
}

static void LCD_Clear(void){

    unsigned char    init_data = 0x1;
    current_regime = LCD_INSTR;
       
    /*Clears the LCD display*/
    sendData(&init_data,&current_regime);
    delay_ms(2);
}

/*Sends data or an instruction the LCD*/
static void sendData(unsigned char *data,lcd_regimes *regime){

    if (*regime == LCD_INSTR){
            
        CLEAR_BIT(GPIOC->ODR, 0x1);   /*set RS to low*/    
    }
    else{
 
        SET_BIT(GPIOC->ODR, 0x1);    /*set RS to high*/        
    }

    if ( (*data & 0x1 ) == 0x1) SET_BIT(GPIOA->ODR, 0x1);      /*set data bit 0*/
    else CLEAR_BIT(GPIOA->ODR, 0x1);
    if ( (*data & 0x2 ) == 0x2) SET_BIT(GPIOA->ODR, 0x2);      /*set data bit 1*/
    else CLEAR_BIT(GPIOA->ODR, 0x2);
    if ( (*data & 0x4 ) == 0x4) SET_BIT(GPIOA->ODR, 0x4);      /*set data bit 2*/
    else CLEAR_BIT(GPIOA->ODR, 0x4);
    if ( (*data & 0x8 ) == 0x8) SET_BIT(GPIOA->ODR, 0x8);      /*set data bit 3*/
    else CLEAR_BIT(GPIOA->ODR, 0x8);
    if ( (*data & 0x10 ) == 0x10) SET_BIT(GPIOA->ODR, 0x10);      /*set data bit 4*/
    else CLEAR_BIT(GPIOA->ODR, 0x10);
    if ( (*data & 0x20 ) == 0x20) SET_BIT(GPIOA->ODR, 0x20);      /*set data bit 5*/
    else CLEAR_BIT(GPIOA->ODR, 0x20);
    if ( (*data & 0x40 ) == 0x40) SET_BIT(GPIOA->ODR, 0x40);      /*set data bit 6*/
    else CLEAR_BIT(GPIOA->ODR, 0x40);    
    if ( (*data & 0x80 ) == 0x80) SET_BIT(GPIOA->ODR, 0x80);      /*set data bit 7*/
    else CLEAR_BIT(GPIOA->ODR, 0x80);
    
    
    SET_BIT(GPIOC->ODR, 0x8);    /*set E to high*/    
    delay_us(30);
    CLEAR_BIT(GPIOC->ODR, 0x8);    /*set E to low*/
    
}

static void delay_ms(unsigned int ms)
{
    int tms;
    tms = 9000*ms;
    while (tms--);
}

static void delay_us(unsigned int us)
{
    int tus;
    tus = 9*us;
    while(tus--);
}
[/CODE]

I'd be very grateful for any kind of advice since I'm getting desperate. I've measured that the pins give the proper voltage levels at the right time, so I'm out of ideas.

Outcomes