<< Zpět

 

  Česky: , English:

Jednoduchý stejnosměrný voltmetr

Pomocí A/D převodníku se snímají 2 vstupy (rozsahy 10V a 100V) a zobrazují se jako 2 údaje na LCD displeji EL1602B. Plošňák není, jen schéma, zůstalo to jen ve formě vrabčího hnízda. :-)


#define	B0	0x1
#define	B1	0x2
#define	B2	0x4
#define	B3	0x8
#define	B4	0x10
#define	B5	0x20
#define	B6	0x40
#define	B7	0x80
typedef signed char s8;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long int u32;
typedef char BOOL;
#define TRUE 1
#define FALSE 0

/*=============================================================================

            LCD display EL1602B (controller Hitachi HD44780, KS0066)

=============================================================================*/

/*
Running at internal RC 8 MHz

Fuses: high=0xd9, low=0xe4 to 8 MHz (use 0xef on external crystal)

(Normal: high=0xc1, low=0x1f, calibration byte 0xc3)

default: high=0xd9, low=0xe1
*/

/*
http://joshuagalloway.com/lcd.html
http://robo.fe.uni-lj.si/~kamnikr/sola/urac/vaja3_display/How%20to%20control%20HD44780%20display.pdf
http://www.bipom.com/documents/appnotes/LCD%20Interfacing%20using%20HD44780%20Hitachi%20chipset%20compatible%20LCD.pdf

EL1602B-FL-YTS (Y=yellow LED) - japan character set
EL1602B-FL-YBS
EL1602A-FL-YBW
ATM1602B-NL-BBW (B=blue LED)

GDM1602B-FL-YBW

2 rows with 16 rows

Pins and connection:

1 VSS (GND) .... GND (board 1)
2 VDD (+5 V) .... +5V (board 2 with +5V wire)
3 V0 (contrast adjustment)
4 RS (H/L register select signal) ... PC0 (CPU 23, board 3)
5 R/W (H/L Read/Write signal) ... PC1 (CPU 24, board 6)
6 E (H/L Enable signal)	... PC2 (CPU 25, board 4)
7 DB0 (H/L Data bus line) .... PB0 (CPU 12, board 12)
8 DB1 (H/L Data bus line) .... PB1 (CPU 13, board 13)
9 DB2 (H/L Data bus line) .... PB2 (CPU 14, board 14 - last)
10 DB3 (H/L Data bus line) .... PD3 (CPU 1, board 7)
11 DB4 (H/L Data bus line) .... PD4 (CPU 2, board 8)
12 DB5 (H/L Data bus line) .... PD5 (CPU 9, board 9)
13 DB6 (H/L Data bus line) .... PD6 (CPU 10, board 10)
14 DB7 (H/L Data bus line) .... PD7 (CPU 11, board 11)
15 K LED- (0V for back light)
16 A LED+ (+4.2V for back light)

Commands:
00000001 Clear Display and Home the Cursor
0000001* Return Cursor and LCD to Home Position
000001IS Set Cursor Move Direction (I: increment/decrement; S: shift display)
00001DCB Enable Display/Cursor (D: display on, C: cursor on, B: blink on)
0001SR** Move Cursor/Shift Display (S: diplay shift, R: direction right)
001DNF** Set Interface Length (D: 8 bit interface, N: 2 rows, F: big font)
01AAAAAA Move Cursor into CGRAM (A: address)
1AAAAAAA Move Cursor to Display (A: address)

*/

#include <avr/io.h>
#include <util/delay.h>

/* set ENABLE state ON */
#define EN_ON PORTD |= B5

/* set ENABLE state OFF */
#define EN_OFF PORTD &= ~B5

/* set DATA mode */
#define DATA_MODE PORTD |= B4

/* set COMMAND mode */
#define CMD_MODE PORTD &= ~B4

/* output data byte */
#define DataOut(d) { PORTD = (PORTD & 0xf0) | ((d) & 0xf); }

/* write data byte */
void WriteData(unsigned char data)
{
	DATA_MODE;
	DataOut(data>>4);
	EN_ON;
	_delay_us(5);
	EN_OFF;
	_delay_us(5);
	DataOut(data);
	EN_ON;
	_delay_us(5);
	EN_OFF;
	_delay_us(100);
}

/* write command byte, some commands need additional waiting */
void WriteCmd(unsigned char cmd)
{
	CMD_MODE;
	DataOut(cmd>>4);
	EN_ON;
	_delay_us(5);
	EN_OFF;
	_delay_us(5);
	DataOut(cmd);
	EN_ON;
	_delay_us(5);
	EN_OFF;
	_delay_us(100);
}

/* clear display */
void LCD_Clear() { WriteCmd(1); _delay_ms(5); }

/* return to home position */
void LCD_Home() { WriteCmd(2); _delay_ms(5); }

/* set entry mode: right=shift cursor right, shift=shift entire display */
inline void LCD_Entry(BOOL right, BOOL shift)
	{ WriteCmd(4 + (right ? 2 : 0) + (shift ? 1 : 0)); }

/* set display on: disp=display on, cur=cursor on, blink=blinking on */
inline void LCD_DispOn(BOOL disp, BOOL cur, BOOL blink)
	{ WriteCmd(8 + (disp ? 4 : 0) + (cur ? 2 : 0) + (blink ? 1 : 0)); }

/* set cursor shift: shift=cursor shift, right=shift to right */
inline void LCD_Shift(BOOL shift, BOOL right)
	{ WriteCmd(0x10 + (shift ? 8 : 0) + (right ? 4 : 0)); }

/* set CGRAM (character generator) address */
inline void LCD_CGRAM(u8 addr) { WriteCmd(0x40 + addr); }

/* set DDRAM (display data) address */
inline void LCD_DDRAM(u8 addr) { WriteCmd(0x80 + addr); }

void LCD_Init(void)
{
	/* set port to output mode */
	DDRD |= B5+B4+B3+B2+B1+B0;
	EN_OFF;

	/* wait for more than 20 ms for LCD power up */
	_delay_ms(100);

	/* byte synchronisation to new interface */
	CMD_MODE;

	/* byte synchronisation using 8-bit interface */
	DataOut(0x3);
	EN_ON;
	_delay_us(200);
	EN_OFF;
	_delay_ms(5);

	DataOut(0x3);
	EN_ON;
	_delay_us(200);
	EN_OFF;
	_delay_ms(1);

	DataOut(0x3);
	EN_ON;
	_delay_us(200);
	EN_OFF;
	_delay_ms(1);

	/* switch to 4-bit interface */
	DataOut(0x2);
	EN_ON;
	_delay_us(100);
	EN_OFF;
	_delay_ms(5);

	/* set data interface to 8/4 bit, 2 rows, font 5x7 */
	WriteCmd(0x28);
	_delay_ms(5);

	/* display off, cursor off, blinking off */
	LCD_DispOn(FALSE, FALSE, FALSE);

	/* clear display, home cursor */
	LCD_Clear();

	/* auto move cursor right */
	LCD_Entry(TRUE, FALSE);

	/* display on, cursor on, blinking on */
	LCD_DispOn(TRUE, TRUE, TRUE);

	LCD_CGRAM(0);

	WriteData(0x12);
	WriteData(0);
	WriteData(0xf);
	WriteData(0x1b);
	WriteData(0x1b);
	WriteData(0x0f);
	WriteData(3);
	WriteData(0xe);
}


u8 dispbuf[10];

// display number with 1 decimal digit
void dispnum1(u16 num)
{
	s8 i, j;

	i = 0;
	for (;;)
	{
		dispbuf[i] = (u8)((num % 10) + '0');
		num /= 10;
		if ((num == 0) && (i > 0)) break;
		i++;
	}

	j = 3 - i;
	for (; j > 0; j--) WriteData(' ');
	for (; i > 0; i--) WriteData(dispbuf[i]);
	WriteData('.');
	WriteData(dispbuf[i]);
}

// display number with 2 decimal digits
void dispnum2(u16 num)
{
	s8 i, j;

	i = 0;
	for (;;)
	{
		dispbuf[i] = (u8)((num % 10) + '0');
		num /= 10;
		if ((num == 0) && (i > 1)) break;
		i++;
	}

	j = 3 - i;
	for (; j > 0; j--) WriteData(' ');
	for (; i > 1; i--) WriteData(dispbuf[i]);
	WriteData('.');
	WriteData(dispbuf[i]);
	WriteData(dispbuf[i-1]);
}

void dispV()
{
	WriteData('V');
}

#define CNT 1024
#define CNT_BITS 10

int main(void)
{
	u32 sum1, sum2;
	u16 n, adc;

	LCD_Init();

	// ADC: http://www.robotplatform.com/knowledge/ADC/adc_tutorial_4.html

	// enable ADC, set prescaler to 64 (on 8 MHz we need to be lower than 200kHz)
	ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

	n = CNT;
	sum1 = 0;
	sum2 = 0;

	while (1)
	{

	// --- measure U1

		// select reference voltage to internal 2.56V, right justify, select ADC input to ADC0
		ADMUX = 0 + (1<<REFS0) + (1<<REFS1);

		// start conversion
		ADCSRA |= (1<<ADSC);

		// wait until conversion completes
		while (ADCSRA & (1<<ADSC));

		// read ADC result
		adc = ADCW;

		// sum value
		sum1 += adc;

	// --- measure U2

		// select reference voltage to internal 2.56V, right justify, select ADC input to ADC1
		ADMUX = 1 + (1<<REFS0) + (1<<REFS1);

		// start conversion
		ADCSRA |= (1<<ADSC);

		// wait until conversion completes
		while (ADCSRA & (1<<ADSC));

		// read ADC result
		adc = ADCW;

		// sum value
		sum2 += adc;

	// --- display result

		n--;
		if (n == 0)
		{
			// display U1
			LCD_DDRAM(0);
			dispnum2((u16)(sum1 >> CNT_BITS));
			dispV();

			LCD_DDRAM(0x40+3);
			WriteData('U');
			WriteData('1');

			// display U2
			LCD_DDRAM(8);
			dispnum1((u16)(sum2 >> CNT_BITS));
			dispV();

			LCD_DDRAM(0x40+8+3);
			WriteData('U');
			WriteData('2');

			// set cursor off
			LCD_DDRAM(0x50);

			// new measure
			n = CNT;
			sum1 = 0;
			sum2 = 0;
		}
	}
}

Download zdrojový kód a schéma: AVmeter

Miroslav Němeček

<< Zpět