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.
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);
}
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…
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
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 …
administrator: příspěvek byl upraven
Předchozí příspěvky se necitují.
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