Search code examples
cembeddedpic

why LCD does not display anything



#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <string.h>
#include <stdint.h>  
#include "config.h"
#include "Uart.h"
#define _XTAL_FREQ 20000000
#define RS RC0
#define EN RC1
#define D4 RC2
#define D5 RC3
#define D6 RC4
#define D7 RC5

/*
 * 
 */

void Lcd_Port(char a)
{
    if(a & 1)
        D4 = 1;
    else
        D4 = 0;

    if(a & 2)
        D5 = 1;
    else
        D5 = 0;
    
    if(a & 4)
        D6 = 1;
    else
        D6 = 0;

    if(a & 8)
        D7 = 1;
    else
        D7 = 0;
}
void Lcd_Cmd(char a)
{
    RS = 0;             // => RS = 0
    Lcd_Port(a);
    EN  = 1;             // => E = 1
       __delay_ms(4);
    EN  = 0;             // => E = 0
}

int Lcd_Clear()
{
    Lcd_Cmd(0);
    Lcd_Cmd(1);
}

void Lcd_Set_Cursor(char a, char b)
{
    char temp,z,y;
    if(a == 1)
    {
      temp = 0x80 + b - 1;
        z = temp>>4;
        y = temp & 0x0F;
        Lcd_Cmd(z);
        Lcd_Cmd(y);
    }
    else if(a == 2)
    {
        temp = 0xC0 + b - 1;
        z = temp>>4;
        y = temp & 0x0F;
        Lcd_Cmd(z);
        Lcd_Cmd(y);
    }
}

void Lcd_Init()
{
  Lcd_Port(0x00);  // clear latches before enabling TRIS bits
   __delay_ms(20);
  Lcd_Cmd(0x03);
   __delay_ms(5);
  Lcd_Cmd(0x03);
   __delay_ms(11);
  Lcd_Cmd(0x03);
  /////////////////////////////////////////////////////
  Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
  Lcd_Cmd(0x02);
  Lcd_Cmd(0x08);//Select Row 1
  Lcd_Cmd(0x00);//Clear Row 1 Display
  Lcd_Cmd(0x0C);//Select Row 2
  Lcd_Cmd(0x00);//Clear Row 2 Display
  Lcd_Cmd(0x06);
}

void Lcd_Write_Char(char a)
{
   char temp,y;
   temp = a&0x0F;
   y = a&0xF0;
   RS = 1;             // => RS = 1
   Lcd_Port(y>>4);             //Data transfer
   EN = 1;
   __delay_us(40);
   EN = 0;
   Lcd_Port(temp);
   EN = 1;
   __delay_us(40);
   EN = 0;
}


void Lcd_Write_String(char *a)
{
    int i;
    for(i=0;a[i]!='\0';i++)
       Lcd_Write_Char(a[i]);
}

void Lcd_Shift_Right()
{
    Lcd_Cmd(0x01);
    Lcd_Cmd(0x0C);
}

void Lcd_Shift_Left()
{
    Lcd_Cmd(0x01);
    Lcd_Cmd(0x08);
}

int main(int argc, char** argv) {
    OSCCONbits.IRCF = 0b1111; //set operating frequency to 31kHz (0b1111) for 16MHz
    UART_init();
    Lcd_Init();
    
  // ->Setare Pini
    //Pini motor DC
    
    ANSELAbits.ANSA0 = 0; //set to digital pin
    ANSELAbits.ANSA1 = 0; //set to digital pin
    
    TRISAbits.TRISA0 = 0; //set as output
    TRISAbits.TRISA1 = 0; //set as output
    
    PORTAbits.RA0 = 0;
    PORTAbits.RA1 = 0;
    //Butoane
    ANSELAbits.ANSA2 = 0; //set to digital pin
    ANSELAbits.ANSA4 = 0; //set to digital pin
    ANSELBbits.ANSB4 = 0; //set to digital pin
    
    
    TRISAbits.TRISA2 = 1; //set as input
    TRISAbits.TRISA4 = 1; //set as input
    TRISBbits.TRISB4 = 1; //set as input
    
    //LEDuri
    //RC6 - RIGHT
    //RC6 LEFT
    
    TRISCbits.TRISC6 = 0; 
    TRISCbits.TRISC7 = 0; 
    
    
    //Set as digital
    ANSELCbits.ANSC6 = 0; 
    ANSELCbits.ANSC7 = 0; 
    
    //Folosire LCD
    TRISCbits.TRISC0 = 0; //set as output
    TRISCbits.TRISC1 = 0; //set as output
    TRISCbits.TRISC2 = 0; //set as output
    TRISCbits.TRISC3 = 0; //set as output
    TRISCbits.TRISC4 = 0; //set as output
    TRISCbits.TRISC5 = 0; //set as output
    
    //pull up
    //pull upurile
    OPTION_REGbits.nWPUEN = 0;
    WPUAbits.WPUA2 = 1;
    WPUAbits.WPUA4 = 1;
    WPUAbits.WPUA0 = 1;
    WPUAbits.WPUA1 = 0;
    WPUAbits.WPUA3 = 0;
    WPUAbits.WPUA5 = 0;
    WPUBbits.WPUB4 = 1;
    
    char introducere;
    UART_write_string("1. Move to right ");
    UART_write('\r');
    UART_write_string("2. Move to left");
    UART_write('\r');
    UART_write_string("4. Stop UART");
    UART_write('\r');
   
    PORTCbits.RC6 = 0; 
    PORTCbits.RC7 = 0; 
    
    while(1){
        
        introducere = UART_read();
        
        
        
        if (introducere == '1'){
            PORTAbits.RA0 = 1;
            PORTAbits.RA1 = 0;
            
            PORTCbits.RC6 = 1; 
            PORTCbits.RC7 = 0;
        
        Lcd_Clear();
        Lcd_Set_Cursor(1,1); //Go to the first line
        Lcd_Write_String("helo"); //Display String
        

        }
        
        if (introducere == '2' ){
            PORTAbits.RA0 = 0;
            PORTAbits.RA1 = 1;
            
            PORTCbits.RC6 = 0; 
            PORTCbits.RC7 = 1;
        }
        if(PORTAbits.RA2 == 0){ //Right
            PORTAbits.RA0 = 1;
            PORTAbits.RA1 = 0;
            
            PORTCbits.RC6 = 1; 
            PORTCbits.RC7 = 0;
        }
         if(PORTAbits.RA4 == 0){ //left
           PORTAbits.RA0 = 0;
            PORTAbits.RA1 = 1;
        }
        
         if(introducere =='4'){
            CREN = 0; //disable receiver
            UART_write('\r');
            UART_write_string("disable UART!");
            UART_write('\r');
        }
        
        if(PORTBbits.RB4 == 0){
            CREN = 1; //enable receiver
            UART_write('\r');
            UART_write_string("enable UART!");
            UART_write('\r');
        }
    }
    return (EXIT_SUCCESS);
}


The purpose of the project is to create a Dc motor which when we press 1 to rotate to the right and display on the LCD "rotated right", and if we press 2 to rotate to the left and display on the LCD "rotate left". Used: pic16f1828 LCD: LM016L I connected: RS (LCD) -> RC0 (pic), EN -> RC1, D4 -> RC2, D5 -> RC3, D6 -> RC4, D7 -> RC5

The program works well, the only problem I have is the fact that when I press "1" I want HELO to appear on LCD (it doesn't matter the arrangement). Till now it does not appear on LCD, is not just about HELLo, nothing is displayed, I can only see that it starts, I don't understand where the problem is.


Solution

  • Your implementation for writing to the HD44780 using a 4-bit parallel interface is wrong.

    This is a complete, builds with MPLABX v5.50 and XC8 v2.32, demo that does display "Hello" on line 1 of the LCD module:

    /*
     * File:   main.c
     * Author: dan1138
     * Target: PIC16F1828
     * Compiler: XC8 v2.32
     * IDE: MPLABX v5.50
     *
     * Created on January 23, 2022, 11:27 AM
     * 
     *                            PIC16F1828
     *                   +-----------:_:-----------+
     *            VDD -> :  1 VDD           VSS 20 : <- VSS
     *            RA5 <> :  2 OSC2          PGD 19 : <> RA0 ICD_PGD
     *            RA4 <> :  3 OSC1          PGC 18 : <> RA1 ICD_PGC/D5
     *    ICD_VPP RA3 -> :  4 VPP/MCLRn         17 : <> RA2 
     *     LCD_D7 RC5 <> :  5                   16 : <> RC0 LCD_RS
     *     LCD_D6 RC4 <> :  6                   15 : <> RC1 LCD_EN
     *     LCD_D5 RC3 <> :  7                   14 : <> RC2 LCD_D4
     *            RC6 <> :  8                   13 : <> RB4 
     *            RC7 <> :  9                   12 : <> RB5 
     *            RB7 <> : 10                   11 : <> RB6 
     *                   +-------------------------+
     *                             DIP-20
     * 
     * Description:
     * 
     *  See: https://stackoverflow.com/questions/70800375/why-lcd-does-not-display-anything
     */
    
    // CONFIG1
    #pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
    #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
    #pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
    #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
    #pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
    #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
    #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
    #pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
    #pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
    
    // CONFIG2
    #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
    #pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
    #pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
    #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
    #pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)
    
    /*
     * Tell compiler what we intend to set the system oscillator frequency as.
     */
    #define _XTAL_FREQ (16000000UL)
    
    #include <xc.h>
    #include <stdio.h>
    
    /* Define the LCD interface and character size */
    #define LCD_FORMAT (FOUR_BIT & LINES_5X7)
    
    /* Define the LCD port pins */
    #define LCD_DATA_BITS_MASK  0x3C
    #define LCD_PORT_OUT        LATC
    #define LCD_PORT_DIR        TRISC
    
    #define LCD_RS_PIN          LATCbits.LATC0
    #define LCD_EN_PIN          LATCbits.LATC1
    #define LCD_D4_PIN          LATCbits.LATC2
    #define LCD_D5_PIN          LATCbits.LATC3
    #define LCD_D6_PIN          LATCbits.LATC4
    #define LCD_D7_PIN          LATCbits.LATC5
    
    #define LCD_RS_PIN_DIR      TRISCbits.TRISC0
    #define LCD_EN_PIN_DIR      TRISCbits.TRISC1
    #define LCD_D4_DIR          TRISCbits.TRISC2
    #define LCD_D5_DIR          TRISCbits.TRISC3
    #define LCD_D6_DIR          TRISCbits.TRISC4
    #define LCD_D7_DIR          TRISCbits.TRISC5
    
    /* Clear display command */
    #define CLEAR_DISPLAY 0b00000001
    
    /* Return home command */
    #define RETURN_HOME 0b00000010
    
    /* Display ON/OFF Control defines */
    #define DON         0b00001111   /* Display on      */
    #define DOFF        0b00001011   /* Display off     */
    #define CURSOR_ON   0b00001111   /* Cursor on       */
    #define CURSOR_OFF  0b00001101   /* Cursor off      */
    #define BLINK_ON    0b00001111   /* Cursor Blink    */
    #define BLINK_OFF   0b00001110   /* Cursor No Blink */
    
    /* Cursor or Display Shift defines */
    #define SHIFT_CUR_LEFT    0b00010011   /* Cursor shifts to the left   */
    #define SHIFT_CUR_RIGHT   0b00010111   /* Cursor shifts to the right  */
    #define SHIFT_DISP_LEFT   0b00011011   /* Display shifts to the left  */
    #define SHIFT_DISP_RIGHT  0b00011111   /* Display shifts to the right */
    
    /* Function Set defines */
    #define FOUR_BIT   0b00101111   /* 4-bit Interface               */
    #define EIGHT_BIT  0b00111111   /* 8-bit Interface               */
    #define LINE_5X7   0b00110011   /* 5x7 characters, single line   */
    #define LINE_5X10  0b00110111   /* 5x10 characters               */
    #define LINES_5X7  0b00111011   /* 5x7 characters, multiple line */
    
    /* Start address of each line */
    #define LINE_ONE    0x00
    #define LINE_TWO    0x40
    
    static void LCD_E_Pulse(void)
    {
        LCD_EN_PIN = 1;
        __delay_us(4);
        LCD_EN_PIN = 0;
        __delay_us(4);
    }
    
    static void LCD_DelayPOR(void)
    {
        __delay_ms(15);
    }
    
    static void LCD_Delay(void)
    {
        __delay_ms(5);
    }
    
    static void LCD_PutByte(unsigned char LCD_Data)
    {
        LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK; /* make LCD data bits outputs */
        
        /* send first(high) nibble */
        LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
        if(LCD_Data & 0x10) LCD_D4_PIN = 1;
        if(LCD_Data & 0x20) LCD_D5_PIN = 1;
        if(LCD_Data & 0x40) LCD_D6_PIN = 1;
        if(LCD_Data & 0x80) LCD_D7_PIN = 1;
        LCD_E_Pulse();
        
        /* send second(low) nibble */
        LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
        if(LCD_Data & 0x01) LCD_D4_PIN = 1;
        if(LCD_Data & 0x02) LCD_D5_PIN = 1;
        if(LCD_Data & 0x04) LCD_D6_PIN = 1;
        if(LCD_Data & 0x08) LCD_D7_PIN = 1;
        LCD_E_Pulse();
    
        LCD_PORT_DIR |= LCD_DATA_BITS_MASK; /* make LCD data bits inputs */
    }
    
    void LCD_SetPosition(unsigned char data)
    {
        LCD_RS_PIN = 0;
        LCD_PutByte((unsigned char)(data | 0x80));
        __delay_us(40);
    }
    
    void LCD_WriteCmd(unsigned char data)
    {
        LCD_RS_PIN = 0;
        LCD_PutByte(data);
        __delay_ms(4);
    }
    
    void LCD_WriteData(unsigned char data)
    {
        LCD_RS_PIN = 1;
        LCD_PutByte(data);
        LCD_RS_PIN = 0;
        __delay_us(40);
    }
    
    void LCD_Init(void) 
    {
        unsigned char LCD_Data;
        
        LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK;    /* make LCD data bits outputs */
        LCD_EN_PIN_DIR = 0;                     /* make LCD Enable strobe an output */
        LCD_RS_PIN_DIR = 0;                     /* make LCD Register select an output */
        LCD_EN_PIN = 0;                         /* set LCD Enable strobe to not active */
        LCD_RS_PIN = 0;                         /* set LCD Register select to command group */
        LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;    /* set LCD data bits to zero */
        LCD_DelayPOR();                         /* wait for LCD power on to complete */
    
        /* Force LCD to 8-bit mode */
        LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;    /* set LCD data bits to zero */
        LCD_D4_PIN = 1;
        LCD_D5_PIN = 1;
        LCD_E_Pulse();
        LCD_Delay();
        LCD_E_Pulse();
        LCD_Delay();
        LCD_E_Pulse();
        LCD_Delay();
        
        /* Set LCD to 4-bit mode */
        LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;    /* set LCD data bits to zero */
        LCD_D5_PIN = 1;
        LCD_E_Pulse();
        LCD_Delay();
    
        /* Initialize LCD mode */
        LCD_WriteCmd(LCD_FORMAT);
    
        /* Turn on display, Setup cursor and blinking */
        LCD_WriteCmd(DOFF & CURSOR_OFF & BLINK_OFF);
        LCD_WriteCmd(DON & CURSOR_OFF & BLINK_OFF);
        LCD_WriteCmd(CLEAR_DISPLAY);
        LCD_WriteCmd(SHIFT_CUR_LEFT);
    
        /* Set first position on line one, left most character */
        LCD_SetPosition(LINE_ONE);
    }
    /*
     * Hook for printf
     */
    void putch(char txData)
    {
        LCD_WriteData(txData);
    }
    /*
     * Main application
     */
    void main(void) 
    {
        OSCCON = 0x7A; //set operating frequency to 16MHz
        ANSELA = 0;
        ANSELB = 0;
        ANSELC = 0;
        
        //pull up
        OPTION_REGbits.nWPUEN = 0;
        WPUAbits.WPUA2 = 1;
        WPUAbits.WPUA4 = 1;
        WPUAbits.WPUA0 = 1;
        WPUAbits.WPUA1 = 0;
        WPUAbits.WPUA3 = 0;
        WPUAbits.WPUA5 = 0;
        
        LCD_Init();
        __delay_ms(100);
    
        LCD_SetPosition(LINE_ONE);
        printf("Hello");
        
        /*
         * Application loop
         */
        for(;;)
        {
            
        }
    }