
Real-Time Temperature Display with LM35 & PIC16F877A
Project Overview
This project uses a PIC16F877A microcontroller to read temperature data from an LM35 temperature sensor and display it on a 16×2 LCD in real-time.
Troubleshooting Tips
- LCD Not Displaying Correctly
- Ensure the contrast pin (V0) is properly adjusted.
- Check LCD connections to PORTD.
- Temperature Not Updating
- Confirm the LM35 sensor is correctly powered (VCC to 5V, GND to GND).
- Verify ADC connections and initialization settings.
- Inaccurate Temperature Readings
- Ensure correct ADC conversion factor (0.488 for 10-bit resolution).
- Shield the sensor from external heat sources.
Let me know if you need modifications or further enhancements! 🚀
/*
Project: Temperature Monitoring System using PIC Microcontroller
Title: Real-Time Temperature Display with LM35 & PIC16F877A
Microcontroller: PIC16F877A
Sensor: LM35
LCD Display: 16×2 LCD (connected in 4-bit mode)
Compiler: MPLAB XC8
*/
#include <xc.h>
#define _XTAL_FREQ 20000000 // Define operating frequency for delay
// Define LCD Pins
#define RS RD0
#define EN RD1
#define D4 RD2
#define D5 RD3
#define D6 RD4
#define D7 RD5
// Function Prototypes
void LCD_Command(unsigned char);
void LCD_Char(unsigned char);
void LCD_Init();
void LCD_String(const char*);
void ADC_Init();
unsigned int ADC_Read(unsigned char);
void main() {
unsigned int adc_value;
float temperature;
char temp_str[10];
TRISA = 0xFF; // Configure PORTA as input (for ADC)
TRISD = 0x00; // Configure PORTD as output (for LCD)
ADC_Init(); // Initialize ADC
LCD_Init(); // Initialize LCD
LCD_String(“Temp: “);
while(1) {
adc_value = ADC_Read(0); // Read ADC value from channel 0
temperature = adc_value * 0.488; // Convert ADC value to temperature
sprintf(temp_str, “%.2f C”, temperature); // Convert float to string
LCD_Command(0x86); // Move cursor to display temperature
LCD_String(temp_str);
__delay_ms(500);
}
}
void ADC_Init() {
ADCON0 = 0x41; // Enable ADC, select channel 0
ADCON1 = 0x80; // Configure result format and voltage reference
}
unsigned int ADC_Read(unsigned char channel) {
ADCON0 &= 0xC5; // Clear existing channel selection
ADCON0 |= (channel << 3); // Select ADC channel
__delay_ms(2); // Acquisition time delay
GO_nDONE = 1; // Start ADC conversion
while(GO_nDONE); // Wait for conversion to finish
return ((ADRESH << 8) + ADRESL); // Return 10-bit ADC result
}
void LCD_Command(unsigned char cmd) {
RS = 0;
D4 = (cmd >> 4) & 1;
D5 = (cmd >> 3) & 1;
D6 = (cmd >> 2) & 1;
D7 = (cmd >> 1) & 1;
EN = 1;
__delay_ms(1);
EN = 0;
D4 = cmd & 1;
D5 = (cmd >> 7) & 1;
D6 = (cmd >> 6) & 1;
D7 = (cmd >> 5) & 1;
EN = 1;
__delay_ms(1);
EN = 0;
}
void LCD_Char(unsigned char data) {
RS = 1;
D4 = (data >> 4) & 1;
D5 = (data >> 3) & 1;
D6 = (data >> 2) & 1;
D7 = (data >> 1) & 1;
EN = 1;
__delay_ms(1);
EN = 0;
D4 = data & 1;
D5 = (data >> 7) & 1;
D6 = (data >> 6) & 1;
D7 = (data >> 5) & 1;
EN = 1;
__delay_ms(1);
EN = 0;
}
void LCD_Init() {
LCD_Command(0x02); // Initialize LCD in 4-bit mode
LCD_Command(0x28); // 2 lines, 5×7 matrix
LCD_Command(0x0C); // Display on, cursor off
LCD_Command(0x06); // Increment cursor
LCD_Command(0x01); // Clear screen
__delay_ms(2);
}
void LCD_String(const char *str) {
while(*str) {
LCD_Char(*str);
str++;
}
}