Vhodná knihovna pro LCD 20x4 (Atmega32)

zdravím, chci se zeptat jestli někdo nemáte nějakou jednoduchou knihovnu pro ovládání tohoto displaye : gme.cz/lcd-alfanumericky-dis … t-p513-227 má ovladač ST7066 , podle toho co jsem četl je zpětně kompatibilní s HD44780, co jsem hledal knihovnu tak nikde sem pro toto rozlišení displaye 20x4 nic nenašel, nebo asi špatně hledám. Programovat v Céčku se teprve učím, ve škole nás učili jenom v assembleru, jinak bych si knihovnu napsal svojí.
Díky

Jo, něco jsem našel. Není to sice nic extra, ale pro začátek by ti to mohlo stačit.

44780.h


#ifndef __DRIVERS_HD44780_H
#define __DRIVERS_HD44780_H

#define Radku		4
#define Sloupcu		20

#define CLRSCR		0x01
#define HOME		0x02

#define MOD			0x04	
	#define MODR	0x02
	#define MODS	0x01

#define	DISON		0x0C
#define	DISOFF		0x08
#define CURON		0x0E
#define CURBLIK		0x0F
#define CURHIDE		0x0C

#define MOVCURLEFT	0x10
#define MOVCURRIGHT	0x14

#define FUN4BIT		0x28	
#define FUN8BIT		0x38
	#define FONT2	0x04

#define SETCGRAM	0x40
#define SETDDRAM	0x80
	#define FIRSTLINE	0x00
	#define SECLINE 	0x40
	#define THIRDLINE	0x14
	#define FOURTHLINE	0x54


#define LCDport		PORTC
#define LCDddr		DDRC

#define DDRwrite	0xFF
#define DDRread		0x7F
#define RSpin		PC0
#define RWpin		PC1
#define Epin		PC2

#define LCD_data	LCDport |= _BV(RSpin)
#define LCD_cmd		LCDport &= ~_BV(RSpin)
#define LCD_reading	LCDport |= _BV(RWpin)
#define LCD_writing	LCDport &= ~_BV(RWpin)
#define E_UP		LCDport |= _BV(Epin)
#define E_DOWN		LCDport &= ~_BV(Epin)

unsigned char DisplayTexts[Radku][Sloupcu];

void DispInit(void);
void Write_command (unsigned char cmd);
void Write_data (unsigned char cmd);
void gotoXY (unsigned char x, unsigned char y);
void Write_screen (void);
void Write_string (unsigned char *string);
#endif /* __DRIVERS_HD44780_H */

44780.c


#if !defined (F_CPU)
#define F_CPU 4000000
#endif

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

#define sleep() asm volatile ("nop")

void Write_string (unsigned char  *string)
{
unsigned char pom;
for (pom=0; pom<Sloupcu; pom++)
  if (string[pom]) Write_data(string[pom]);
  else break;
}

void Write_screen (void)
{
Write_command(CLRSCR); 			//Vymazání displeje 
_delay_ms(1);
Write_command(SETDDRAM | FIRSTLINE ); //Začátek druhého řádku
_delay_us(40);
Write_string (&DisplayTexts[0][0]);
Write_command(SETDDRAM | SECLINE ); //Začátek druhého řádku
_delay_us(40);
Write_string (&DisplayTexts[1][0]);
Write_command(SETDDRAM | THIRDLINE); //Začátek třetího řádku
_delay_us(40);
Write_string (&DisplayTexts[2][0]);
Write_command(SETDDRAM | FOURTHLINE ); //Začátek čtvrtého řádku
_delay_us(40);
Write_string (&DisplayTexts[3][0]);
}

void Write_half_cmd (unsigned char cmd)
{
LCD_cmd;
_delay_us(40);
LCD_writing;
_delay_us(40);
E_UP;
LCDport = (LCDport & 0x0F) | (cmd<<4);
_delay_us(40);
E_DOWN;
}

void Write_command (unsigned char cmd)
{
Write_half_cmd (cmd >> 4);
_delay_us(40);
Write_half_cmd (cmd & 0x0F);
_delay_us(100);
}

void Write_half_data (unsigned char cmd)
{
LCD_data;
_delay_us(40);
LCD_writing;
_delay_us(40);
E_UP;
LCDport = (LCDport & 0x0F) | (cmd<<4);
_delay_us(40);
E_DOWN;
}

void Write_data (unsigned char cmd)
{
Write_half_data (cmd >> 4);
_delay_us(40);
Write_half_data (cmd & 0x0F);
_delay_us(100);
}

void gotoXY (unsigned char x, unsigned char y)
{
unsigned char pom;
if (x>Sloupcu) pom=0;
else pom=x;
switch (y)
	{
	case 1: Write_command((SETDDRAM | SECLINE )+ pom);
			break;
	case 2: Write_command((SETDDRAM | THIRDLINE )+ pom);
			break;
	case 3: Write_command((SETDDRAM | FOURTHLINE )+ pom);
			break;
	default: Write_command((SETDDRAM | FIRSTLINE )+ pom);
			break;
	}
}


void DispInit(void)
{
LCDddr = DDRwrite;

_delay_ms(20);					//Čas potřebný pro ustálení a náběh LCD

Write_half_cmd(3);
_delay_ms(5);	
Write_half_cmd(3);
_delay_ms(1);
Write_half_cmd(3);
_delay_ms(1);
Write_half_cmd(2);
_delay_ms(1);

Write_command(FUN4BIT); 
Write_command(DISOFF); 
Write_command(DISON); 			//Zapnout displej bez kurzoru

Write_command(MOD | MODR); 		//Posuv kurzoru vpravo

Write_command(CLRSCR); 			//Vymazání displeje 
Write_command(HOME);			//kurzor to HOME
_delay_ms(10);
}

main.c

#if !defined (F_CPU)
#define F_CPU 4000000
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
#include <util/delay.h>
#include "hd44780.h"

int main()
{
DispInit();	
strcpy((char*)&DisplayTexts[0][0]," Zobrazovany  ");
strcpy((char*)&DisplayTexts[1][0]," text  ");
strcpy((char*)&DisplayTexts[2][0]," pres vsechny  ");
strcpy((char*)&DisplayTexts[3][0]," radky  ");
Write_screen ();
return 0;
}

mno zkusil sem to přeložit, a teda nesedí názvy použitých knihoven a v tom main.c není ani ten soubor 44780.c vloženej, tak to sem si tam všechno dodělal, ale nějak sem nepochopil na jaký piny mam připojit datový vodiče, ty řídící sem tam našel jsou to PC0 až PC3 ale ty datový kam ? a pracuje to jako 4 nebo 8mi bitová linka ?

V tomhle případě jde o 4bit. Datové linky jsou nad těmi řídícími na portu PORTC.
Jinak řečeno:
PC7 = dat3
PC6 = dat2
PC5 = dat1
PC4 = dat0
PC3 = nepoužito
PC2 = E
PC1 = RW
PC0 = RS

data 0-3 ? myslel sem že pro 4bit se používaj 4-7, no a vyzkoušel sem oboje, vždycky zbývající datové vodiče sem připojil na zem, a nic na displeji svítí furt dva řádky kostičkama, první a třetí, svítí celá matice v celém řádku, zajímavé je že když odpojim všechno nechám jenom připojený + a - a kontrast na mínusu tak to svítí taky :smiley: takže si myslím že je problém v SW v inicializaci nebo v HW v propojení :smiley: nebo doufám že není KO display…

Soubory .c se do souborů .c nevkládají.
Jenom se přidají do “Source files” v AvrStudiu.

nevím jestli to myslíš takhle, ale teda holí zdroják mam takhle:

[code]#if !defined (F_CPU)
#define F_CPU 16000000
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
#include <util/delay.h>
#include “D:\PRS\testmyho\LCDTEST/hd44780.h”
#include “D:\PRS\testmyho\LCDTEST/hd44780.c”

int main()
{
DispInit();
strcpy((char*)&DisplayTexts[0][0]," Zobrazovany “);
strcpy((char*)&DisplayTexts[1][0],” text “);
strcpy((char*)&DisplayTexts[2][0],” pres vsechny “);
strcpy((char*)&DisplayTexts[3][0],” radky ");
Write_screen ();
}
[/code]

Stačí takto:

[code]#if !defined (F_CPU)
#define F_CPU 16000000
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
#include <util/delay.h>
#include “hd44780.h”

int main()
{
DispInit();
strcpy((char*)&DisplayTexts[0][0]," Zobrazovany “);
strcpy((char*)&DisplayTexts[1][0],” text “);
strcpy((char*)&DisplayTexts[2][0],” pres vsechny “);
strcpy((char*)&DisplayTexts[3][0],” radky ");
Write_screen ();
} [/code]

Když je soubor v uvozovkách, hledá linker v tom samém adresáři, kde se nachází main.c.

P.S. Jen doufám, že máš ty soubory hd44780.h a hd44780.c importovány v projektu.

importované ??? já myslel že pomocí include se tam přidaj, jinak by to nešlo přeložit né ? popř. jak je mam importovat do toho projektu ? sorry za možná tak triviální otázky, ale v céčku dělám fakt poprvé, dělal jsem jenom v C++ programy pro PC a to je uplně o něčem jinym :smiley:

edit: už jsem na to přišel, takže pokud sem to pochopil správně, do include se píšou pouze hlavičkový soubory, a zdrojové kody se dávaj vedle na pravo do toho okna tam je seznam zdrojáků použitý v tom projektu, tak tam sem dal ten hd78.c a teď to du skusit naprogramovat…

Vyřešeno !! vzal sem led diodu a jel po jednotlivých pinech a sledoval jak dioda bliká, a na nějakých jenom slabě svítila, na některých silně svítivě blikala, tak jsem knihovnu předělal na port D a ejhle najednou to chodí, akorát teda 4tý řádek na displayi je takový slabě viditelný, asi je to způsobeno nižším napětím 4,8V -> nepřesný stabilizátor, i tak děkuji za knihovnu, tahle je celkem jednoduchá tak pro mě půjde lehce použít. Proč ale display nešel na portu C ? Odprásklej by neměl bejt, ještě jsem k němu nic kromě displaye nepřipojil.

Edit: posláblí jas na konci displaye je vedlejší vliv rychlého přepisování, stačí dát do smyčky zpoždění a je to OK…

Gratuluji. Na to, že to byl tvůj první projekt, jsi to vyřešil docela rychle.
Hodně štěstí v dalším bastlení.

Nepises aky mcu pouzivas, ale na C-cku to mohlo neist preto, lebo si si pravdepodobne nezakazal JTAG interface. AK by si si ho v poistkach vypol, potom by to asi slo aj na tom C-cku.

mno používám Atmega32-16PU, kouknu na to, protože v těch pojistkách jsem jenom navolil externí krystal, na nic dalšího sem nešahal, je možný že ten JTAG bude aktivní…

edit: opravdu, vypnul jsem Jtag a už display chodí na portu C vpohodě, díky za radu :wink:
ještě se chci zeptat jak převedu int na string ? chci zobrazit obsah OCR1A na displayi ale ta rutina bere jenom string, díky.

nech je cislo v rozsahu 0-255


//...
uint8_t znak[3], cislo, pom_prem;

pom_prem = cislo/100;
znak[0] = pom_prem + "0";
cislo = cislo - pom_prem * 100;
pom_prem = cislo / 10;
cislo = cislo - pom_prem * 10;

znak[1] = pom_prem + "0";
znak[2] = cislo + "0";
//...

/*
ak bude hodnota cisla 167

znak[0] = "1";
znak[1] = "6";
znak[2] = "7";

tieto potom postupne posles na display. Program som pisal z hlavy a netestoval som ho. Mozno sa to spravit aj inak, ale tomu rozkladu v zasade neujdes. 

alebo mozes pouzit aj funkciu z avr-lib itoa() alebo utoa(), ale to uz budes musiet vediet ako tak pouzivat ukazatele
*/
// cislo moze by int16 alebo uint16

//...

#include <stdlib.h>

uint8_t znak[5], cislo, pom_prem;

// funkcia Ti naplni pole znakmi, ktore interpretuju cislo v danej ciselnej sustave. Program bude samozrejme vacsi, kedze sa vklada funkcia ktora vie kde co vsetko, dokonca zobrazit cislo v 18, alebo 36-tkovej ciselnej sustave

utoa((uint16_t)cislo,(char *)&znak[0],(uint8_t)10);

// alebo aj pre znamienko
itoa((int16_t)cislo,(char *)&znak[0],(uint8_t)10);

//...

jj díky už sem to vyřešil právě přes funkci itoa :smiley:

ještě sem se chtěl zeptat, jak se řeší desetinná místa když chci měřit napětí ? použil jsem datový typ float, jenže ten zase nevezme display, je třeba ho převést, když použiju funkci sprintf jak se píše všude na internetu tak mi to na displayi ukáže otazník. Co s tím ?
Díky

co skusit pouzit dtostrf
popis je na nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

díky moc funguje to :smiley:

nevíte někdo, jak přepínat mezi adc kanálama ? přepnu je v ADMUX, potom pustim převod, všechno jde, jeden kanál mi funguje, ale jakmile začnu přepínat na další tak se to začne nějak tlouct a ve výsledku to ukazuje nesmysly všude, nevadí že pokaždý výsledek převodu dám do stejný proměnný ? mam v úmyslu měřit 3 teploty + napětí sítě, termistory mam NTC 10K, s pullup rezistorem 10K. Termistory PA0 - PA2 napětí PA7
je tam nějaká záludnost nebo mám chybu v programu ? díky