Nahodné zobrazování znaků na LCD

Zdravím všechny,
Mam velmi specificky problém a potřeboval bych poradit. Nejsem uplný začátečník, ale ani vybodej programátor. Potřebuji zobrazit proměnou (int) na LCD displej ( s řadičem HD44780), to znamená jako string, abych viděl jaká hodnota je ulozená v proměny. Při jejím výpisu dochází k velmi zajímavým úkazům, někdy se zobrazí v naprostém pořádku ale někdy úplně jiná hodnota či naproste nesmysli jako jsou kostičky a podobně. Už jsme zkoušel vše. zkoušel jsme přepsat funkce ale bez výsledně, vše je stejně. Měnil jsme nastaveni kompilátoru, nastaveni optimalizace,…a dokonce jsem z nouze měnil i procesor za jiný kus (mega16) ale bez výsledně. Po naběhnuti napájeni se dejou naprosto stejné věci.
Please help me (((((

tadz je ukazka kodu
vse mma rodeleny do modulu
jeden pro lcd
a druhy pro main





#include "System.h"
#include "LCD_displey.h"  



void dobezna_hrana_LCD(unsigned char instrukce_data,unsigned char W_R)		
{
             /*  Instrukce 0
                 Data 1
                                                
                 Write 0
                 Read 1          */                                       
                                                 
        mSet_PortC_pin_level(RS,instrukce_data);   
        mSet_PortC_pin_level(RW,W_R);  
		//RS= instrukce_data ;                      
		//RW= W_R ;                                 
		 
      
       vDelay_ms(1); 
         mSet_PortC_pin_level(E,log_1);
              //  E= 1;		                //   E jde z 0 do 1
	 	
		   vDelay_ms(1); 
		 
         mSet_PortC_pin_level(E,log_0);
		//E = 0;		                //   E z 1 do 0, zapisový 	
		  
	    vDelay_ms(1); 
		
		
		                                        
}  
     

void write_LCD(unsigned char znak)               // znk musi vit v apostrofech 'A' !!!!
{    
    
            pozice= pozice + 1;
       #asm("RCALL CEK1M");
   if (!((pozice==16) || (pozice==32)))  { // skoci do if jen kdyz poyice se nebude rovnat 17 nebo 34
        PORTC = (znak & 0xF0 );        // (znak & oxF0)= horni bity, pote privedeni na port              
        dobezna_hrana_LCD(1,0);             // zapis hornich 4 bitu, E=1 - data;RW=0 - zapis
        #asm("RCALL CEK1M");
        PORTC = (znak<<4);          // (znak & 0xF0)= dolni bity,posun o 4 bity do leva, pote privedeni na port
        dobezna_hrana_LCD(1,0);             // zapis spodnich 4 bitu, E=1 - data;RW=0 - zapis
        #asm("RCALL CEK1M");
        }


   if (pozice==16){
        radek=2; 
        
        PORTC = 0xC0;                  // 1100 0000
        dobezna_hrana_LCD(0,0);         // instrukce, skos na 2. radek na adesu 40   
        #asm("RCALL CEK1M");
        PORTC &=0x0F;
        dobezna_hrana_LCD(0,0);         // instrukce, skos na 2. radek na adesu 40 
        #asm("RCALL CEK1M");
        
        PORTC = (znak & 0xF0 );        // (znak & oxF0)= horni bity, pote privedeni na port              
        dobezna_hrana_LCD(1,0);             // zapis hornich 4 bitu, E=1 - data;RW=0 - zapis
        #asm("RCALL CEK1M");
        PORTC =(znak<<4);          // (znak & 0xF0)= dolni bity, posun o 4 bity do leva,pote privedeni na port
        dobezna_hrana_LCD(1,0);             // zapis spodnich 4 bitu, E=1 - data;RW=0 - zapis
        #asm("RCALL CEK1M");
          
        }  
        
   
    if (pozice == 32) {                 // testovani konce druheroho radku a vraceni na pocatek LCD
         
        
        
        erace_LCD();                    // vymaze LCD      
        #asm("RCALL CEK1M");
        
        
        radek=1;
        pozice=0; 
        PORTC = (znak & 0xF0 );        // (znak & oxF0)= horni bity, pote privedeni na port              
       
        dobezna_hrana_LCD(1,0);             // zapis hornich 4 bitu, E=1 - data;RW=0 - zapis
        #asm("RCALL CEK1M");
        PORTC =(znak<<4);          // (znak & 0xF0)= dolni bity, posun o 4 bity do leva,pote privedeni na port
        dobezna_hrana_LCD(1,0);             // zapis spodnich 4 bitu, E=1 - data;RW=0 - zapis
        #asm("RCALL CEK1M");
        }    
        
    
    
}     
           

void write_string_LCD(unsigned char flash *cp)        //retezec musi byt v uvozvkach    "ahoj"   !!!!!
{
   for (; *cp; cp++)
   
        {    
        write_LCD(*cp); }
} 

   
void write_stringRAM_LCD(unsigned char pom_stringRAM)             //vypise rovnou promenou int write_stringRAM_LCD(a), unsigned int a; 
{  
 unsigned char *cp;   

  

itoa(pom_stringRAM,cp);   


for (; *cp; cp++)
       { write_LCD(*cp); }
}                                
                   

            

no a modulu main mam


void main(void)
{
 
     
 vInit_LCD();     
 write_string_LCD("34 1692 947 1695 32 78 47 28"); 
  

  erace_LCD();
   void write_stringRAM_LCD(1635); 

a tak dale

takze po zapnuti napajeni se mi obcas zobrazi 1635 nekdz 1000 nekdz 1483 a abz toho nebylo dost tak inejaky paznaky. talsi zajimava vec je ze retezec pred tim mi to v pohode chyby vypise.

:arrow_right: administrator: příspěvek byl upraven

treba si uvedomit, ze radic LCD je schopny prijimat nejake data az cca 20-40ms po ustaleni napaj. napatia, neviem ci to mas osetrene, v zdrojaku to nevidim…

Jestli je ten jev náhodný a předpoklad je že program je dobře (jako že asi jo) tak bych skusil spíš zapřemejšlet nadtim jestli nemáš nějaký rušení. Doporučil bych nějakou slušnou kapacitu na vyhlazení napajení, potom neuškodí mít tam nějakou malou kapacitu (100nF) , popřípadě něco dalšího. Jestli problém přetrvá, tak délka kabelu k LCD. Spíš jen tak tipuju, možná to tim neni.

Rychlost zapisdu do LCD je osetrena, ta je dostacujici. Tak tim do neni. To uz me taky napadlo. A pridat C to taky neresi, mel jsme sondu oscaku na napajeni a to se ani nehne. Tyto nahodne znaky se vypisuji i kdyz dam do programu smycku pro opakovane zobrazovani. Vtip je v tom ze vsechny funkce mi bez problemu bezej. Ma mam podezreni na to ze se deje neco primo v promenou v pameti, ale nevim co by to mohlo byt. Jo jinak delka kabelu v tomhle pripade hrat roli nebute protoze je asi 20cm.

Nenapada vas jeste neco, uzj mse zoufalej

vidim v mainu testovaci vypis cisel jako ze je v uvozovkach

write_string_LCD(“34 1692 947 1695 32 78 47 28”);

vypis cisla

write_stringRAM_LCD(1635);

neni takze tam nedava cislo 1635 ale obsah pametove bunky, kam ukazuje pointer na 1635, podle me kdyz se da 1635 do uviozovek tak to pude

resp. ten problem je u toho write_LCD(*cp); asi by bylo lepsi write_LCD(cp[0]);

spatne sem se kouknul na to

ano mas pravdu kdyz napisu write_string_LCD(“1635”); tak skutecne mi to vypise 1635 ale to neni to co potrebuju. Potrebuji zobrazit hodnotu promene na LCD, to znamena ze mam promenou treba typu unsigned char s kterou pracuji a vysledek bach potrebuji zobrayzit na LCD takze mam jen jeji jmeno.
Zkusim tedy jeste zmenit write_LCD(*cp);na write_LCD(cp[0]); ale si myslim ze je to totozny zapis

to je totozny zapis, ak je pole jednorozmerne

Pokud jsemteda pochopil otazku tak potrebujes prevest cislo ulozene v promene na pole znaku (string) ktere se da zobrazit na standartnim LCD (pokud das zobrazit obsah promene zobrazi se znak ASCII lezici na danne pozici misto pozadovaneho cisla)? Pokud ano je reseni snadne staci si cislo delit a zobrazit si az jednotlive cislice v ascii, viz priklad:
konverze.txt (441 Bytes)

A co tak skusit normalne funkcie v C na to urcene :slight_smile:



char* itoa  (int  __val, char * __s, int __radix) 			

Convert an integer to a string.

The function itoa() converts the integer value from val into an ASCII representation that will be stored under s. The caller is responsible for providing sufficient storage in s.

Note:
The minimal size of the buffer s depends on the choice of radix. For example, if the radix is 2 (binary), you need to supply a buffer with a minimal length of 8 * sizeof (int) + 1 characters, i.e. one character for each bit plus one for the string terminator. Using a larger radix will require a smaller minimal buffer size.

Warning:
If the buffer is too small, you risk a buffer overflow.

Conversion is done using the radix as base, which may be a number between 2 (binary conversion) and up to 36. If radix is greater than 10, the next digit after ‘9’ will be the letter ‘a’.

If radix is 10 and val is negative, a minus sign will be prepended.

The itoa() function returns the pointer passed as s.


dokonca si este mozes vybrat aj ciselnu sustavu v ktorej chces cislo vidiet.