16f690 + LCD 4x20 nejde bez programátoru

Zdravím,

mám zajímavý problém na aplikace kde čtu přes i2c z LM75 teplotu a zobrazuju ji na klasickem znakovem LCD 4x20.

Problém spočívá v tom, že pokud mám připojený pickit3 (externí napájení aplikace) tak vše běží jak má. Zresetuju a zase naběhne.
Pokud PK3 odpojím a resetuju, zase to jede korektně. Ale pokud odpojím napájení (bez PK3) a po chvíli připojím, už se to nerozjede - možná tak v 1% pokusů. LCD vypadá jako by neproběhla inicializace, jsou tam pruhy na 1 a 3 řádku. Prostě jako jen po připojení napájení na LCD. Reset aplikace nepomáhá. Stačí však připojit PK3 a vše se rozběhne.

Zkoušel jsem i druhý LCD a trofám si říct, že v něm to nebude… Rovněž jsem zkoušel jiný zdroj. Používám PC zdroj větev 5V. A z baterek se to chová stejně.

Po dlooouhém laborování s LCDinit a pročítání různých fór to vidím na zádrhel s picem. S jeho stavem po připojení napájení - inicializací.

Další věc které jsem si náhodou všimnul je ta, že na jednom výstupu PICu mám pověšenou LEDku která svítí při nule na výstupu. Tenhle pin nastavuju jako output, ale nic na něj neposílám. No a při spojení s PK3 se LEDka rozsvítí, tzn. že na ní příjde nula (já to v programu nědělám). No a když to zapnu bez PK3 tak se ta LEDka nerozsvítí a na LCD není nic. Ale další LEDky mám na ladění i2c kterým obsluhuju čidlo a ty normálně běží. Takže program jede normálně. Jede normálně i když to rozjedu s PK3 a pak ho odpojím, jak píšu výše.

Fakt nevím čím to může být, poradí někdo ?

Chtělo by to schéma, jak máš ošetřen pin MCLR ?

na schématu není nic extra. Dva piny pro komunikaci s cidlem. 6 pinu pro komunikaci s LCD. MCLR pouzivam jako MCLR, 10kohm odpor na +Ucc a pres tlacitko na GND pro reset. A jeden vystup na onu LEDku. Schema je podle mě vpořádku (za jistých podmínek přece běží naprosto korektně), kdybych to měl někde v eaglu tak to postnu, ale je to v nepájivém poli tak jak jsem to postupne oživoval někdy v říjnu. Od té doby jsem nad tím zanevřel. Až se mi dnes dostal do ruky druhý stejný (typově, ale jiný výrobce) displej. Tak jsem to prubnul s ním a zkusil jsem i tu baterku jestli náhodou… ale chyba lávky, žádná změna.

postnu alespon program, je tam určitě pár věcí, které tam být nemusí…

#include "htc.h"
#include "stdlib.h"

__CONFIG (0E4h); //INTOSCIO,MCLR

#define _XTAL_FREQ 4000000
#define Data	RC6	// in/out
#define Clk	RC7
int n,sw,teplminus;
long teplota;
char tepl[10];

void i2c_start(void);
void i2c_stop(void);
void i2c_clk(void);
void i2c_read(unsigned int adresa);
void i2c_write(unsigned int byte);
void Lcd_Gotoxy(unsigned char row,unsigned char col);
void Lcd_Init(void);
void Lcd_Out(const char *str);
void Lcd_smaz(void);

void main (void){
IRCF2 = 1;
IRCF1 = 1;
IRCF0 = 0;	// 4MHz
TRISC0 = 0;	// EN
TRISC1 = 0;	// RW
TRISC2 = 0;	// RS
TRISC3 = 0;	// led
TRISC7 = 0;	// Clk
TRISC6 = 0;	// Data out
TRISB = 0;	//data LCD
ANSEL = 0;	// digital i/o
ANSELH = 0;	// digital i/o
Lcd_Init();
sw = 0;

while (1){

i2c_start ();
if (sw) i2c_read(0b1001000);	//adresa 1001000	in
	else i2c_read(0b1001111);	//adresa 1001111	out

Data = 0;
i2c_clk();			// data = 0 znamena ze zarizeni je pripraveno

TRISC6 = 1;		// Data in
teplota = 0;
teplminus = 0;
for (n = 1; n <= 8; n++)
	{
	if (n == 1) teplminus = Data;
	if (teplminus) switch(n)	{
	case 2:teplota = teplota + 512 * ~Data;break;
	case 3:teplota = teplota + 256 * ~Data;break;
	case 4:teplota = teplota + 128 * ~Data;break;
	case 5:teplota = teplota + 64 * ~Data;break;
	case 6:teplota = teplota + 32 * ~Data;break;
	case 7:teplota = teplota + 16 * ~Data;break;
	case 8:teplota = teplota + 8 * ~Data;break;
				}
		else switch(n)	{
	case 2:teplota = teplota + 512 * Data;break;
	case 3:teplota = teplota + 256 * Data;break;
	case 4:teplota = teplota + 128 * Data;break;
	case 5:teplota = teplota + 64 * Data;break;
	case 6:teplota = teplota + 32 * Data;break;
	case 7:teplota = teplota + 16 * Data;break;
	case 8:teplota = teplota + 8 * Data;break;
				}

		i2c_clk();	
	}
TRISC6 = 0;		// Data out
Data = 0;		// data = 0 znamena ze master chce dalsi byte
i2c_clk();		

TRISC6 = 1;		// Data in
for (n = 1; n <= 8; n++)
	{
	if (teplminus) switch(n)	{
	case 1:teplota = teplota + 4 * ~Data;break;
	case 2:teplota = teplota + 2 * ~Data;break;
	case 3:teplota = teplota + 1 * ~Data + 1;break;	// pricti 1 k dvojkovemu doplnku
				}
		else switch(n)	{
	case 1:teplota = teplota + 4 * Data;break;
	case 2:teplota = teplota + 2 * Data;break;
	case 3:teplota = teplota + 1 * Data;break;
				}

	i2c_clk();	
	}
TRISC6 = 0;		// Data out
Data = 1;		// data = 1 znamena ze master nechce dalsi byte
i2c_clk();	

i2c_stop();

teplota = teplota * 125;

ltoa (tepl,teplota,10);

if (teplota >= 100000){		// stovky
tepl[8] = 'C';
tepl[7] = 223;		// znak stupen
tepl[6] = tepl[5];
tepl[5] = tepl[4];
tepl[4] = tepl[3];
tepl[3] = '.';}

if ((teplota >= 10000) && (teplota < 100000)){		// desitky
tepl[8] = ' ';
tepl[7] = 'C';
tepl[6] = 223;		// znak stupen
tepl[5] = tepl[4];
tepl[4] = tepl[3];
tepl[3] = tepl[2];
tepl[2] = '.';}


if ((teplota < 10000) && (teplota >= 1000)){		// jednotky
tepl[8] = ' ';
tepl[7] = ' ';
tepl[6] = 'C';
tepl[5] = 223;		// znak stupen
tepl[4] = tepl[3];
tepl[3] = tepl[2];
tepl[2] = tepl[1];
tepl[1] = '.';}

if (teplota < 1000){		// desetiny
tepl[8] = ' ';
tepl[7] = ' ';
tepl[6] = 'C';
tepl[5] = 223;		// znak stupen
tepl[4] = tepl[2];
tepl[3] = tepl[1];
tepl[2] = tepl[0];
tepl[1] = '.';
tepl[0] = '0';}

if (teplota == 0){		// nula
tepl[8] = ' ';
tepl[7] = ' ';
tepl[6] = 'C';
tepl[5] = 223;		// znak stupen
tepl[4] = '0';
tepl[3] = '0';
tepl[2] = '0';
tepl[1] = '.';
tepl[0] = '0';}

if (sw)	{
		Lcd_Gotoxy(1,0);
		Lcd_Out("IN");
		if (teplminus){Lcd_Gotoxy(1,4);Lcd_Out("-");}
			else {Lcd_Gotoxy(1,4);Lcd_Out(" ");}
		Lcd_Gotoxy(1,5);
		Lcd_Out(tepl);
		sw = 0;
		}
	
	else 	{
		Lcd_Gotoxy(2,0);
		Lcd_Out("OUT");
		if (teplminus){Lcd_Gotoxy(2,4);Lcd_Out("-");}
			else {Lcd_Gotoxy(2,4);Lcd_Out(" ");}
		Lcd_Gotoxy(2,5);
		Lcd_Out(tepl);
		sw = 1;
			}

	}
}

void i2c_start(void)
	 {
	Clk = 1;
	__delay_ms(10);
	Data = 1;
	__delay_ms(10);
	Data = 0;
	__delay_ms(10);
	Clk = 0;
	__delay_ms(10);
	}


void i2c_stop(void)
	 {
	Data = 0;
	__delay_ms(10);
	Clk = 1;
	__delay_ms(10);
	Data = 1;
	__delay_ms(10);
	}

void i2c_clk(void)
	{
	__delay_ms(10);
	Clk = 1;
	__delay_ms(10);
	Clk = 0;
	__delay_ms(10);
	}

void i2c_read(unsigned int adresa)
	{	
	adresa = (adresa<<1) | 0b00000001;
	signed char i;
	for(i=7; i>=0; i--)
		{
		if ((adresa>>i) & 0x01) Data = 1;
			else Data =0;
		i2c_clk();	
		}
	}

void i2c_write(unsigned int byte)
	{	
	byte = (byte<<1) | 0b00000000;
	signed char i;
	for(i=7; i>=0; i--)
		{
		if ((byte>>i) & 0x01) Data = 1;
			else Data =0;
		i2c_clk();	
		}
	}
-----------------------------------------------------------------------------------
a jěšte ošetreni LCD.. z většiny cizí produkce.. komentáře jsem neupravoval

#include	"htc.h"

#define _XTAL_FREQ 4000000

#define LCD_PORT PORTB
#define LCD_TRIS TRISB

//LCD_D4 - LCD_D7 na PORT4 - PORT7
#define RS RC2
#define EN RC0

#define LCD_HOME 0x02
#define LCD_CLR 0x01 

//=======================================
//	LCD 4bit komunikace
//======================================
void Strobe(void)
{
	//data platná při sestupné hraně EN
	EN = 1;
	__delay_us(100);	
	EN = 0;
	__delay_us(100);
}

//Příkaz
void Lcd_Cmd(unsigned char Cmd)
{	
 LCD_PORT = (Cmd & 0xF0);	//maskuj dolní 4bity	             	
 RS = 0; 						//RS = 0(příkaz)	
 Strobe();

 LCD_PORT = (Cmd & 0x0F)<<4;//maskuj horní 4bity,posun o 4místa vlevo	             	 
 RS = 0;						//RS = 0(příkaz)	
 Strobe();

/*
Pokud je výsledek v podmínce roven nule, jedná se o 
příkaz "Vymaž dislej" nebo "Návrat na začátek", které
vyžadují delší časový interval
*/
 if (Cmd & 0b11111100) __delay_us(100);else __delay_ms(4);
} 

//Data
void Lcd_Chr(unsigned char Chr)
{
 LCD_PORT = (Chr & 0xF0);	                
 RS = 1;						//RS = 1(data)
 Strobe();

 LCD_PORT = (Chr & 0x0F)<<4;	                
 RS = 1;						//RS = 1(data)
 Strobe();
}

//smaz LCD
void Lcd_smaz(void)
{
 RS = 0;
 Lcd_Cmd(LCD_CLR);
__delay_ms(2);
}

//inicializace LCD
void Lcd_Init(void)
{
 RS = 0;			//RS = 0(příkaz)	
 __delay_ms(50);

//Nastavení PORTu na výstup	
 LCD_TRIS = 0b00000000;
 
 LCD_PORT = 0b00110000; 	
 Strobe();	
 __delay_ms(5);		      
 LCD_PORT = 0b00110000; 	
 Strobe();
 __delay_us(100);
 LCD_PORT = 0b00110000; 	
 Strobe();
 __delay_us(100);

LCD_PORT = 0b00100000; 	
 Strobe();
 __delay_us(100);			  

 Lcd_Cmd(0b00101000);		  //2 radky
 __delay_us(100);	
 Lcd_Cmd(0b00001000);		  //vypni LCD
 __delay_us(100);	
 Lcd_Cmd(LCD_CLR);		  	  //smaž LCD
 __delay_ms(4);	
 Lcd_Cmd(0b00000110);		  //incrementace
 __delay_us(100);

 Lcd_Cmd(0b00001100);		  //zapni LCD
 __delay_us(100);
}

//Řetězec
void Lcd_Out(const char *str)
{
	unsigned char x = 0;
	while(str[x]!=0)
  	{
		__delay_us(100);
		Lcd_Chr(str[x]);
		x++;
  	}
}

//Nastavení ukazatele na pozici x(1 - 4),y(0 - 19)
void Lcd_Gotoxy(unsigned char row,unsigned char col)
{
  switch(row)
  {
   case 1:row=0x00;break;
   case 2:row=0x40;break;
   case 3:row=0x14;break;
   case 4:row=0x54;break;
  }	
  Lcd_Cmd(0b10000000 | row | col);
}

:arrow_right: administrator: příspěvek byl upraven
Předchozí příspěvky se necitují.

no prave . kondiky mas co nejbliz k mcu ? skus jeste na zacatek dat delay treba 500ms . udelej si jednoduchej program : delay, led ON, while(1); vyloucis chybu v programu…

Po zapnutí napájení je třeba počkat nějakou dobu (100ms) než začneš komunikovat s LCD.

Ano, to dělám.

:arrow_right: administrator: příspěvek byl upraven
Předchozí příspěvky se necitují.

Kodik přímo u PICu nepomohl. Program normálně běží, je to vidět na komunikaci i2c.

Co máte na výstupu, když ho nastavíte jako output. A nic s ním něděláte ? Já tu mám jednou jedničku - PK3 odpojený a jednou nulu - PK3 připojený, v tomhle případě je to OK. Jsem z toho tak trochu jelen.

tezko rict takle bez schematu a takovimdle programem, nebo to aspon vyfot z par stran (hlavne ne VGA kvalita),cely to rozhot a zacni od zacatku s ledkou…,

to nikdo nevi viz DS, nez nastavis tris tak je treba nastavyt log hodnotu vystupu

Zdravím,

tak jsem zrovna zkusil vyměnit PICko za jiné, služebně mladší. A hle, běhá to jak má. Čumím jak tele na nová vrata, teda PICko. :open_mouth:

Tomu se me nechce nejak verit … to by jsi musel nejakym zpusobem odpalit pin… Zkus nacist REVID z PIC. Pokazde kdyz chces posilat firmware do PIC ukaze ti to ID soucastky a kdyz mrknes do datasheetu zjistis REV. Mezi sebou porovnas a podivas se do priloy datasheetu ERRATA… Mozna tam najdes vysvetleni co se stalo …

:arrow_right: administrator: příspěvek byl upraven
Předchozí příspěvky se necitují.

Asi vím kam tím míříš, ale ID je v obou případech stejné, Device ID Revision = 00000006. Takže i stejná revize?

A když koukám na rozdíly v erratech tak nic z těch věcí kde jsou rozdíly nepoužívám.

jj presne tam mirim … Vetsinou nez neco zacnu delat s nejakym MCU koukam v prni rade na “zmenu” pak teprve zacnu uctivat datasheet…

Tak se ti zrejme podarilo odpalit nejaky pin nebo cely port ?

Jak jsem psal výše o té jedné LEDce co se mi rozsvítí, tak teď nesvítí a jede to, takže asi opravdu něco s tím portem C.

…teď jsem zkusil přehodit ty 2 signály pro LCD: E a RS z portu C na port A a běhá to OK i s tím starým chipem bez PK3. Takže port C mám na tom starším chipu nějakým způsobem poškozen…

Takhle “jemně” se mi ještě žáden chip nepodařilo poznamenat… Většinou nekomunikoval, chlásil chyby při programování nebo měl port kompletně mrtvý… dělám si další zářez :smiley:

díky za tip.