Pic16F877a 16x2 LCD Program Code

 In the previous blog post Interfacing LCD with PIC16F877A: Displaying Sensor Data it was shown how to interface a 16x2 LCD with PIC16F877A and alike PIC microcontroller. In that post, circuit diagram and program code for communicating with the LCD was provided. Here I just wanted to post an alternative C program code for inter-connecting LCD and the PIC microcontroller.

C program code

#define _XTAL_FREQ 16000000 // Define operating frequency
#include <xc.h>
#include <stdio.h> // For sprintf()

// CONFIGURATION BITS
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF


// LCD pin configuration
#define RS RB0
#define EN RB1
#define D4 RB2
#define D5 RB3
#define D6 RB4
#define D7 RB5
#define delay for(j=0;j<1000;j++)

int j;

void lcd_init();
void lcd_cmd(unsigned char cmd);
void lcd_data(unsigned char data);
void lcd_write_4bits(unsigned char data);
void print(unsigned char *s);
void adc_init();
unsigned int read_adc();
void display_temperature(unsigned int temp);

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_OFF & CP_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF);

void main() {
    unsigned int adc_value;
    unsigned int temperature;
    
    // Configure LCD pins
    TRISB = 0x00; // Set PORTB as output for LCD control and data lines
    
    lcd_init(); // Initialize the LCD
    adc_init(); // Initialize ADC

    lcd_cmd(0x80); // Set cursor at beginning of first line
    print("Temperature:"); // Display label
    
    while (1) {
        adc_value = read_adc(); // Read ADC value from AN0 (LM35)
        temperature = adc_value * 0.488; // Convert ADC value to temperature (LM35 gives 10mV/°C)
        display_temperature(temperature); // Display the temperature on the LCD

        __delay_ms(1000); // Delay 1 second before next reading
    }
}

void lcd_init() {
    lcd_cmd(0x33); // Initialization sequence for 4-bit mode
    lcd_cmd(0x32); // Initialization sequence for 4-bit mode
    lcd_cmd(0x28); // 4-bit mode, 2-line display, 5x7 font
    lcd_cmd(0x0C); // Display on, cursor off
    lcd_cmd(0x06); // Entry mode, increment cursor
    lcd_cmd(0x01); // Clear display
}

void lcd_cmd(unsigned char cmd) {
    RS = 0; // Command mode
    lcd_write_4bits(cmd >> 4); // Send higher nibble
    lcd_write_4bits(cmd & 0x0F); // Send lower nibble
}

void lcd_data(unsigned char data) {
    RS = 1; // Data mode
    lcd_write_4bits(data >> 4); // Send higher nibble
    lcd_write_4bits(data & 0x0F); // Send lower nibble
}

void lcd_write_4bits(unsigned char data) {
    D4 = (data >> 0) & 1;
    D5 = (data >> 1) & 1;
    D6 = (data >> 2) & 1;
    D7 = (data >> 3) & 1;
    
    EN = 1; // Enable pulse
    delay;
    EN = 0; // Disable pulse
}

void print(unsigned char *s) {
    while (*s) {
        lcd_data(*s++);
    }
}

void adc_init() {
    ADCON0 = 0x41; // ADCON0: ADON = 1 (ADC enabled), Channel 0 (AN0)
    ADCON1 = 0x80; // ADCON1: Right Justified, A/D Port Configuration Bits
}

unsigned int read_adc() {
    __delay_ms(2); // Acquisition time
    GO_nDONE = 1; // Start conversion
    while (GO_nDONE); // Wait for conversion to finish
    return (ADRESH << 8) + ADRESL; // Combine 8-bit high and low registers
}

void display_temperature(unsigned int temp) {
    lcd_cmd(0x8C); // Set cursor to position to display temperature
    lcd_data((temp / 100) + 48); // Hundreds place
    lcd_data(((temp / 10) % 10) + 48); // Tens place
    lcd_data((temp % 10) + 48); // Units place
    lcd_data(0xDF); // Degree symbol
    lcd_data('C'); // 'C' for Celsius
}

The following is the circuit diagram.

Interfacing LCD with PIC16F877A circuit diagram

Post a Comment

Previous Post Next Post