Зеркало сайта: vivacious-stockings-frog.cyclic.app

HD44780 + ATmega8: таймер с крупными цифрами

разделы: AVR , HD44780 , дата: 15 сентября 2015г.


макет цифр

Небольшая демо-программа, таймер для ATmega8 с дисплеем HD44780. В качестве отправной точки использовал исходник из предыдущего поста. Идея была почерпнута здесь: LCD "Bigfont" Numbers over 2 or 4 lines".

Исходник:

/* for ATmega8/168/328 display HD44780 support
site: http://countzero.weebly.com

avr-gcc -mmcu=atmega8 -Wall -Os -o lcd.elf lcd.c
avr-objcopy -O ihex lcd.elf lcd.hex*/

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

#define LCD_RS	2
#define LCD_E	3
#define LCD_D4	4
#define LCD_D5	5
#define LCD_D6	6
#define LCD_D7	7

#define LCD_PORT DDRD
#define LCD	 PORTD

#define CMD 0 // command
#define DTA 1 // data

#define LCD_CLEAR	0x01
#define LCD_OFF    	0x08
#define LCD_ON    	0x0C
/10/#define LCD_ON    	0x0F
#define LCD_RETURN    	0x02

uint8_t one[8]=
{
  0b11111,
  0b11111,
  0b11111,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
};

uint8_t two[8]=
{
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b11111,
  0b11111,
  0b11111,
};

uint8_t three[8]=
{
  0b11111,
  0b11111,
  0b11111,
  0b00000,
  0b00000,
  0b00000,
  0b11111,
  0b11111,
};

uint8_t four[8]=
{
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
};

uint8_t zero[8]={
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b01110,
  0b01110,
  0b01110,
  0b00000,
};

// for 4bit mode
static int  send_lcd(uint8_t value, uint8_t mode)
{
	LCD&=0x03; // clear
	LCD|=(value&0xF0)|(mode<<LCD_RS)|(1<<LCD_E);
	LCD&=0x03;

	LCD|=(value<<4)|(mode<<LCD_RS)|(1<<LCD_E);
	LCD&=~(1<<LCD_E);
	if (value == LCD_CLEAR || value == LCD_RETURN)
		_delay_ms(2);
	else
		_delay_us(50);

	return 0;
}

static int print_lcd(char* str)
{
	uint8_t i;
	i=0;
	while(str[i] !=0 && i<255)
	{
		send_lcd(str[i],DTA);
		i++;
	};

	return i;
};

static void write_custom_char(uint8_t  ch)
{
	uint8_t i;
	if (ch == 1) for (i=0; i <8; i++) send_lcd(one[i],DTA);
	else if (ch == 2) for (i=0; i <8; i++) send_lcd(two[i],DTA);
	else if (ch == 3) for (i=0; i <8; i++) send_lcd(three[i],DTA);
	else if (ch == 4) for (i=0; i <8; i++) send_lcd(four[i],DTA);
	else if (ch == 0) for (i=0; i <8; i++) send_lcd(zero[i],DTA);

}

static void print_big_dg(uint8_t pos,uint8_t digit)
{
	send_lcd(0x80|pos, CMD); //first line
  	switch (digit)
	{
	    	case 0:
    		print_lcd("\4\1\4");break;
		case 1:
    		print_lcd("\1\4 "); break;
	    	case 2:
    		case 3:
    		print_lcd("\3\3\4");break;
	    	case 4:
	    	print_lcd("\4\2\4");break;
	    	case 5:
	    	case 6:
	    	print_lcd("\4\3\3");break;
	    	case 7:
	    	print_lcd("\1\1\4");break;
    		case 8:
	    	case 9:
    		print_lcd("\4\3\4");
  	}
	send_lcd(0xC0|pos,CMD); //second line
	switch (digit)
	{
		case 0:
		case 8:
		case 6:
		print_lcd("\4\2\4"); break;
    		case 1:
		print_lcd("\2\4\2"); break;
		case 2:
		print_lcd("\4\2\2");break;
		case 3:
		case 5:
    		case 9:
		print_lcd("\2\2\4"); break;
		case 4:
		print_lcd("  \4"); break;
    		case 7:
    		print_lcd(" \4 ");
  	}

}

static int init_lcd()
{
	LCD_PORT=0xFC; // pin 2,3,4,5,6,7 in OUTPUT mode
	_delay_ms(50);

	// 4bit mode
	LCD&=0b11; // clear
	LCD |=(1<<LCD_D5)|(1<<LCD_E);
	LCD&=0b11; // clear
	LCD |=(1<<LCD_D5);
	_delay_ms(5);

	send_lcd(0x28,CMD); // mode: 4bit, 2 lines
	send_lcd(LCD_OFF,CMD);
	send_lcd(LCD_CLEAR,CMD);
	send_lcd(0x06,CMD); // seek mode: right
	send_lcd(LCD_ON,CMD);
	return 0;
}

int main(void)
{

	init_lcd();
	send_lcd(0x40,CMD);
	write_custom_char(0);
	write_custom_char(1);
	write_custom_char(2);
	write_custom_char(3);
	write_custom_char(4);
	send_lcd(0x80,CMD);

	uint8_t min; min=0;
	uint8_t sec; sec=0;
	for(;;)
	{
		print_big_dg(0, min/10);
		print_big_dg(4, min%10);
		print_big_dg(9, sec/10);
		print_big_dg(13, sec%10);
		if (sec%2)
		{
			send_lcd(0x87,CMD);
			send_lcd(0,DTA);
			send_lcd(0xC7,CMD);
			send_lcd(0,DTA);
		} else
		{
			send_lcd(0x87,CMD);
			send_lcd(0x20,DTA);
			send_lcd(0xC7,CMD);
			send_lcd(0x20,DTA);
		}
		if (sec >= 60) { sec=0; min++;} else sec++;
		if (min >= 99) min=0;
		_delay_ms(950);
	};
	return 0;
}

Прошивка весит около 860 байт.

Результат: