#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define F_CPU 16000000UL
// Define LCD control pins
#define RS PC4
#define E PC5
// Define macros for setting and clearing bits
#define SET_BIT(port, bit) (port |= (1 << bit))
#define CLEAR_BIT(port, bit) (port &= ~(1 << bit))
void LCD_Command(unsigned char cmd) {
// Send higher nibble
PORTC = (PORTC & 0xF0) | ((cmd >> 4) & 0x0F);
CLEAR_BIT(PORTC, RS); // RS = 0 for command
SET_BIT(PORTC, E); // Enable high
_delay_us(1);
CLEAR_BIT(PORTC, E); // Enable low
_delay_us(200); // Short delay
// Send lower nibble
PORTC = (PORTC & 0xF0) | (cmd & 0x0F);
SET_BIT(PORTC, E); // Enable high
_delay_us(1);
CLEAR_BIT(PORTC, E); // Enable low
_delay_ms(2); // Command execution time
}
void LCD_Char(unsigned char data) {
// Send higher nibble
PORTC = (PORTC & 0xF0) | ((data >> 4) & 0x0F);
SET_BIT(PORTC, RS); // RS = 1 for data
SET_BIT(PORTC, E); // Enable high
_delay_us(1);
CLEAR_BIT(PORTC, E); // Enable low
_delay_us(200); // Short delay
// Send lower nibble
PORTC = (PORTC & 0xF0) | (data & 0x0F);
SET_BIT(PORTC, E); // Enable high
_delay_us(1);
CLEAR_BIT(PORTC, E); // Enable low
_delay_ms(2); // Data write time
}
void LCD_Init() {
// Set control and data lines as output
DDRC = 0xFF;
_delay_ms(20); // LCD power on delay
// Initialization sequence in 4-bit mode
LCD_Command(0x02); // Initialize in 4-bit mode
LCD_Command(0x28); // 2 lines, 5x8 matrix
LCD_Command(0x0C); // Display on, cursor off
LCD_Command(0x06); // Increment cursor
LCD_Command(0x01); // Clear display
_delay_ms(2); // Clear display command delay
}
void LCD_String(char *str) {
while (*str) {
LCD_Char(*str++);
}
}
void LCD_SetCursor(unsigned char row, unsigned char column) {
unsigned char cmd;
if (row == 0) {
cmd = 0x80 + column;
} else {
cmd = 0xC0 + column;
}
LCD_Command(cmd);
}
void ADC_Init(){
//DDRC = 0x00; /* Make ADC port as input */
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<< ADPS0);
/* Enable ADC, with freq/128 */
ADMUX = (1<<REFS0); /* Vref: Avcc, ADC channel: 0 */
}
int ADC_Read(char channel)
{
ADMUX = 0x40 | (channel & 0x07); // set input channel to read
ADCSRA |= (1<<ADSC); // Start ADC conversion
while (!(ADCSRA & (1<<ADIF))); // Wait until end of conversion by polling ADC interrupt flag
ADCSRA |= (1<<ADIF); // Clear interrupt flag
_delay_ms(1); // Wait a little bit
return ADCW; // Return ADC word
}
void FloatToString(float value, char *buffer, int precision) {
// Extract integer part
int intPart = (int)value;
// Extract fractional part
int fracPart = (int)((value - intPart) * pow(10, precision));
// Handle negative values
if (value < 0) {
intPart = -intPart;
fracPart = -fracPart;
}
// Format into buffer
sprintf(buffer, "%d.%*d", intPart, precision, fracPart);
}
int main()
{
LCD_Init();
ADC_Init();
char Voltage[10];
float volt;
while (1) {
volt = (ADC_Read(0)*0.0488759);
volt = (volt/10.00);
_delay_ms(10);
LCD_SetCursor(0, 0);
LCD_String("Voltage:");
dtostrf(volt, 4, 2, Voltage);
LCD_String(Voltage);
}}
/*
int main(void) {
LCD_Init(); // Initialize LCD
ADC_Init(); // Initialize ADC
char buffer[32]; // Increase buffer size to 32 characters
while (1) {
int adc_value = ADC_Read(0); // Read ADC value from channel 0
float voltage = adc_value * (5.0 / 1023.0); // Convert to voltage
LCD_SetCursor(0, 0); // Set cursor to first row, first column
LCD_String("Voltage:");
LCD_SetCursor(1, 0); // Set cursor to second row, first column
FloatToString(voltage, buffer, 2);
strcat(buffer, " V");
LCD_String(buffer);
_delay_ms(100); // Wait for a second
LCD_Command(0x01); // Clear display
_delay_ms(2); // Clear display command delay
}
return 0;
}*/