
 

#include <avr/io.h>

#define RS 2 //RS=PD2
#define E  3 //E=PD3

#define TIME 10	//Константа временной задержки для ЖКИ
//Частота тактирование МК - 4Мгц

#define R_division 3.837524 //=R4/R5 константа

unsigned int u=0; //Глобальная переменная с содержимым преобразования

void pause (unsigned int a)
{
	unsigned int i;
	for (i=a;i>0;i--);
}

void lcd_com (unsigned char lcd) //Передача команды ЖКИ
{
	unsigned char temp;
	
	temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда
	PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E
	asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
	PORTD=temp&~(1<<E); //Сигнал записи команды
	
	temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда
	PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E
	asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
	PORTD=temp&~(1<<E); //Сигнал записи команды
	
	pause(10*TIME); //Пауза для выполнения команды
}

void lcd_dat (unsigned char lcd) //Запись данных в ЖКИ
{
	unsigned char temp;
	
	temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные
	PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E
	asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
	PORTD=temp&~(1<<E); //Сигнал записи данных
	
	temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные
	PORTD=temp;	//Выводим на portD младшую тетраду данных, сигналы RS, E
	asm("nop");	//Небольшая задержка в 1 такт МК, для стабилизации
	PORTD=temp&~(1<<E);	//Сигнал записи данных
	
	pause(TIME);	//Пауза для вывода данных
}

void lcd_init (void)     //Иниализация ЖКИ
{
	lcd_com(0x2c);		//4-проводный интерфейс, 5x8 размер символа
	pause(100*TIME);
	lcd_com(0x0c);		//Показать изображение, курсор не показывать
	pause(100*TIME);
	lcd_com(0x01);		//Очистить DDRAM и установить курсор на 0x00
	pause (100*TIME);
}

unsigned int getADC(void) //Считывание АЦП
{ unsigned int v;
	
	ADCSRA|=(1<<ADSC);	//Начать преобразование
	
	while ((ADCSRA&_BV(ADIF))==0x00) //Дождатся окончания преобразования
	;
	
	v=(ADCL|ADCH<<8);
	return v;
}

void write_data (unsigned int u)
{ unsigned char i;
	double voltage=0;
	
	lcd_com(0x84); 		//Вывод регистра ADC на ЖКИ
	for (i=0;i<10;i++)
	if ((u&_BV(9-i))==0x00) lcd_dat (0x30);
	else lcd_dat (0x31);
	
	lcd_com(0xc2);
	voltage= R_division*2.56*u*1.024; //Расчет напряжения
	
	i=voltage/10000;		   //Выведение напряжения на ЖКИ
	voltage=voltage-i*10000;
	if (i!=0) lcd_dat(0x30+i);
	
	i=voltage/1000;
	voltage=voltage-i*1000;
	lcd_dat(0x30+i);
	
	lcd_dat(',');
	
	i=voltage/100;
	voltage=voltage-i*100;
	lcd_dat(0x30+i);
	
	i=voltage/10;
	voltage=voltage-i*10;
	lcd_dat(0x30+i);
	
	lcd_dat('v');
}

int main(void)
{
	DDRD=0xfc;
	
	pause(3000);		//Задержка для включения ЖКИ
	lcd_init();		//Инициализация ЖКИ
	
	lcd_dat('A');		//Пишем "ADC=" и "U=" на ЖКИ
	lcd_dat('D');
	lcd_dat('C');
	lcd_dat('=');
	lcd_com(0xc0);
	lcd_dat('U');
	lcd_dat('=');
	
	ADCSRA=(1<<ADEN)|(1<<ADPS1)|(1<<ADPS0);
	//Включаем АЦП, тактовая частота бреобразователя =/8 от тактовой микроконтроллера
	ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3);
	//Внутренний источник опорного напряжения Vref=2,56, входом АЦП является PC0
	
	while(1)
	{
		u=getADC();				//Считываем данные
		write_data(u); 			//Выводим их на ЖКИ
		pause(30000);
	}
	
	return 1;
}