[ janko11 @ 15.04.2018. 14:08 ] @
Napisao sam program u programskom jeziku C za mikroprocesor iz 8051 arhitekture koji putem serijskog porta prima podatke i prikazuje ih na displeju, ali iz nekog razloga cifre malo blinkuju. Da li bi neko mogao da mi pomogne oko resenja navedenog problema? U pitanju je procesor 80C32. Hvala unapred
[ shpiki @ 15.04.2018. 18:31 ] @
Sema i kod, bez toga nista...
[ janko11 @ 15.04.2018. 22:36 ] @
Program:
#include <reg51.h>
#include <stdio.h>
#include <stdlib.h>

void displayDigit(unsigned char cifra);
void delayTimer();
void showNumber();
void initSerial();
char receiveData();
void delay(unsigned int msdelay);
//void print();
char buff[20];
unsigned int pom;
//unsigned int br;
unsigned int flag;
unsigned int tmp1,tmp2,tmp3,tmp4,tmp5;
//unsigned int broj;
sbit A=P3^4;
sbit BB=P3^5;
sbit C=P3^6;
sbit INH=P3^7;
sbit LOAD=P1^7;
sbit DIN=P3^3;
sbit CLK=P3^2;
bit DMIRNA,DNULA,DTARA,DPRINT,DMINUS,DOVER,DMMER;

void main(void)
{
DMIRNA=1;
DTARA=0;
DNULA=0;
DMINUS=0;
DOVER=0;
DMMER=1;
P1=0x00;
P3=0x03;
PT0=1;
// flag=0;
// delayTimer();
// pom=0;
while(1)
{
initSerial();
showNumber();
// print();
// TH0=0xFF;
// TL0=0xFF;
delayTimer(); // kod petlji u interrup
}
}

// maskiranje (prikaz cifri na displeju koristeci kolo ULN2803)
void displayDigit(unsigned char cifra)
{
switch(cifra)
{
case 0: P1=0x3F; break;
case 1: P1=0x06; break;
case 2: P1=0x5B; break;
case 3: P1=0x4F; break;
case 4: P1=0x66; break;
case 5: P1=0x6D; break;
case 6: P1=0x7D; break;
case 7: P1=0x07; break;
case 8: P1=0x7F; break;
case 9: P1=0x6F; break;
}
}

// refresh display - a
void delayTimer()
{
// pom=0;
TMOD&=0xF0;
TMOD|=0x01;
TH0=0xFF;
TL0=0xFF;
ET0=1;
EA=1;
TR0=1;
while(TF0==0);
TF0=0;
TR0=0;
}

// inicijalizacija serijskog porta
void initSerial()
{
SCON=0xD0;
TMOD&=0x0F;
TMOD|=0x20;
TH1=0xFD;
TR1=1;
}

// prijem podataka
char receiveData()
{
char el;
while(RI==0);
el=SBUF;
RI=0;
return el;
}

// prijem podataka sa vage
void showNumber()
{
// unsigned int broj;
int i,j=0;
// int ind=0; // indeks elementa u redu niz
int tail=0; // indeks elementa u redu buff
// char buff[20],niz[5];
char el;
// br=0;
el=receiveData();
if(el==0x02) // pocetak komunikacije
{
buff[tail]=el;
tail++;
while(el!=0x03)
{
el=receiveData();
if(el!=0x03)
{
buff[tail]=el;
tail++;
}
else
{
buff[tail]=el;
tail++;
buff[tail]='\0';
// flag=1;
}
if(tail==20)
tail=0;
}
// flag=1; // uspesan prijem
}
else if(el==0x03) // kraj komunikacije
{
buff[tail]=el;
tail++;
buff[tail]='\0';
}
}

// obrada interrupta i ispis na display
void timer0(void) interrupt 1
{
int i;
tmp5=buff[3]-'0';
tmp4=buff[4]-'0';
tmp3=buff[5]-'0';
tmp2=buff[6]-'0';
tmp1=buff[7]-'0';
if(tmp5==0 && tmp4==0 && tmp3==0 && tmp2==0) // 1 cifra na displeju
{
for(i=0;i<40;i++)
{
INH=0;
C=0;
BB=0;
A=1;
displayDigit(tmp1);
delay(3);
}
}
else if(tmp5==0 && tmp4==0 && tmp3==0) // 2 cifre na displeju
{
for(i=0;i<40;i++)
{
INH=0;
C=0;
BB=0;
A=1;
displayDigit(tmp1);
delay(3);
INH=0;
C=0;
BB=1;
A=0;
displayDigit(tmp2);
delay(3);
}
}
else if(tmp5==0 && tmp4==0) // 3 cifre na displeju
{
for(i=0;i<40;i++)
{
INH=0;
C=0;
BB=0;
A=1;
displayDigit(tmp1);
delay(3);
INH=0;
C=0;
BB=1;
A=0;
displayDigit(tmp2);
delay(3);
INH=0;
C=0;
BB=1;
A=1;
displayDigit(tmp3);
delay(3);
}
}
else if(tmp5==0) // 4 cifre na displeju
{
for(i=0;i<40;i++)
{
INH=0;
C=0;
BB=0;
A=1;
displayDigit(tmp1);
delay(3);
INH=0;
C=0;
BB=1;
A=0;
displayDigit(tmp2);
delay(3);
INH=0;
C=0;
BB=1;
A=1;
displayDigit(tmp3);
delay(3);
INH=0;
C=1;
BB=0;
A=0;
displayDigit(tmp4);
delay(3);
}
}
else // 5 cifre na displeju
{
for(i=0;i<40;i++)
{
INH=0;
C=0;
BB=0;
A=1;
displayDigit(tmp1);
delay(3);
INH=0;
C=0;
BB=1;
A=0;
displayDigit(tmp2);
delay(3);
INH=0;
C=0;
BB=1;
A=1;
displayDigit(tmp3);
delay(3);
INH=0;
C=1;
BB=0;
A=0;
displayDigit(tmp4);
delay(3);
INH=0;
C=1;
BB=0;
A=1;
displayDigit(tmp5);
delay(3);
}
}
}

void delay(unsigned int msdelay)
{
unsigned int i,j;
for(i=0;i<msdelay;i++)
{
for(j=0;j<100;j++);
}
}


[ veselinovic @ 19.04.2018. 22:02 ] @
Sta da ti kazem,
procesor direktno vozi displej a nemas neku interapt rutinu da bezuslovno osvjezavas displej.
I tako procesor radi nesto drugo a na displej zaboravi.
Imas dva rjesenja, ili da optimizujes kod ako je moguce ili bolja varijanta da displej vozis nekom drajverom tipa 74595.
Ja sam probao TLC 5916 ( hvala Goranu na info) i mogu ti reci super kolo.
Konstantna struja, mozes smanjiti svjetlost serijski upis lecovan izlaz ma milina.
[ tomam @ 20.04.2018. 07:39 ] @
Pogledaj malo temu na komsinskom forumu

http://forum.yu3ma.net/showthread.php?tid=1847
[ janko11 @ 24.04.2018. 12:44 ] @
Kako mislis da procesor direktno vozi displej. Mozes li malo detaljnije da objasnis? Na semi je displej preko kola ULN2803 povezan sa procesorom.
[ veselinovic @ 24.04.2018. 15:13 ] @
Pod direktno se misli da izmedju procesora i displeja nema neki IC sa lecovanim izlazima.
A ULN je samo glupavi drajver koji sluzi da napoji displej strujom koja je veca od one koju moze dati procesor.
[ mbm @ 24.04.2018. 16:15 ] @

Program je glavmi problem. I to jednostavno ovako ne vredi dalje raditi.
Daću samo perporuku:
Interapt ne zove kašnjenja a baš ne treba ni druge funkcije. Nek samo postavi flagove kao zadatke za glavnu programsku petlju i to je to.
Samo rx i tx stavi u svoj prekid i tako će displej funkcija dobijati asinhrono nove podatke za ispis.

Milan
[ janko11 @ 25.04.2018. 16:04 ] @
Ispravio sam deo koda za interrupt prekidnu rutinu timera, ali se samo prva cifra dobro vidi, ostale se slabije vide. Mozete li mi reci gde gresim u kodu?
Evo koda za prekidnu rutinu timera. Hvala na predlozima. Probacu i sa nekim drajverom.
void delayTimer()
{
TMOD&=0xF0;
TMOD|=0x01;
TH0=0xEE;
TL0=0x00;
TR0=1;
}

void timer0(void) interrupt 1
{
// int disp; // brojac za selekciju displeja
ET0=0;
EA=0;
TR0=0;
TF0=0;
TH0=0xEE;
TL0=0x00;
// disp=disp+1;
disp=1;
tmp5=buff[3]-'0';
tmp4=buff[4]-'0';
tmp3=buff[5]-'0';
tmp2=buff[6]-'0';
tmp1=buff[7]-'0';
// TH0=0xEE;
// TL0=0x00;
// P3=0x83; // iskljuci displeje
switch(disp)
{
case 1:
INH=0;
C=0;
BB=0;
A=1;
displayDigit(tmp1);
case 2:
INH=0;
C=0;
BB=1;
A=0;
displayDigit(tmp2);
case 3:
INH=0;
C=0;
BB=1;
A=1;
displayDigit(tmp3);
case 4:
INH=0;
C=1;
BB=0;
A=0;
displayDigit(tmp4);
case 5:
INH=0;
C=1;
BB=0;
A=1;
displayDigit(tmp5);
}
if(disp>6)
disp=1;
else
disp++;
TR0=1;
ET0=1;
EA=1;
}
[ bogdan.kecman @ 25.04.2018. 16:59 ] @
bez da gledam kod (u mailu izgleda uzasno pa ne mogu) mogu ti reci par
stvari

 - voznja lcd-a interaptom je bila ok '80tih godina, u 21. veku
koristimo externe cipove sa latch-om imas cip koji ti je spojen latch +
trandza drajver (kao npr 2003+595) kostaju ko kikiriki, trose manje
struje nego mcu koji trci non stop i daju mnogo bolju sliku na lcd-u (ne
titra) + mozes da biras nivo osvetljenja nekim pwm-om ako zelis

 - problem koji imas (da ti neke cifre svetle jace od drugih) znaci da
si lose napisao interapt rutinu (cesta greska) ... kada ispisujes cifre
na lcd-u (7segu u stvari kod tebe) moras da imas pauzu posle ispisa da
bi se cifra videla

595 kosta 0.09$ stvarno se ne isplati drndati se sa interaptima i
smarati mcu da gubi vreme (i struju) na te trivijale
[ mikikg @ 25.04.2018. 18:40 ] @
U 22. veku koriste Blue Pill bez drajvera, ULN-ova i tranzistora, more direkt na LED, jel mu fali nesto? :)
Ako se dobudzi FRAM tu, ihhh to je prelepo kako sve radi ....

https://www.youtube.com/watch?v=xA_-619ie-4
[ veselinovic @ 25.04.2018. 18:42 ] @
Inace ako si bas uporan postuj ovo,
kad displej vozis direktno sa uC procedura bi trebala biti ovakva:

Namjestis izlaze na pinovima za 1. cifru
Upalis katodu za 1. cifru.
Sacekas odredjeno vrijeme
Pogasis izlaze za anode displeja
ugasis katodu cifre 1
namjestis 2. cifru na pinovima
upalis katodu2
.
.
.
[ bogdan.kecman @ 25.04.2018. 19:05 ] @
@veselinovic

sto "Pogasis izlaze za anode displeja" ?

kad zabodes katodu ugasi se display, promenis izlaze anode, upalis
katodu, cemu tak korak setovanja anode na intermediate vrednost?


@miki, fali mnogo toga :D
[ mikikg @ 25.04.2018. 19:10 ] @
Citat:
bogdan.kecman: @miki, fali mnogo toga :D


Klientu koji to koristi ne fali nista, cak sam ih pitao:

- Hocete LCD 2x16? - jok, ne vidim nista tu ...
- Hocete LCD 4x20? - jok, ne vidim nista tu ...
- Hocete Touch 7'' - jok, ne mogu to da pipkam ..
- Hocete 7-Seg LED? - Eeeee to hocu!

Sto je trazio to je dobio, ja sam extremno zadovoljan kako ta kombinacija radi, i stvarno radi bolje nego sve ovo gore sto sam spomenuo za veliki broj slucajeva ...
[ bogdan.kecman @ 25.04.2018. 20:14 ] @
7seg je keva, ali isto tako voznja 7seg-a sa latch drajverom je keva
[ scoolptor @ 25.04.2018. 20:23 ] @
A voznja 7-segment sa MAX7219 je kevina keva.
Za $1.5 dobijes ceo displej.

[ mbm @ 25.04.2018. 21:22 ] @
Da ne ulazim u hardver. Molim vas prijatelji ne sugerišite CEO ispis na multipleks sedmosegmentni LED unutar jednog prekida ako već na njemu insistirate !!

Ako mora u prekidnu rutinu onda se tajmerom mora generisati interapt pa u njemu ugasiti prethodna i upaliti sledeća cifra upravo po redosledu kako je Jovan napisao. pa tako u krug.

Taj prekid se mora izvršiti za najkraće moguće vreme. u svakom slučaju na ovom hardveru za nekoliko mikrosekundi a na atmel AT89LP seriji za nekoliko stotina nanosekundi. Svo ostalo vreme sveta je onda na raspolaganju glavnoj programskoj petlji i funkcijama da rade šta im je volja.
RX i TX komunikacija moraj da se obavljaju u svom interaptu sa prioritetom koji je za red viši od tajmerskog prekida za ispis.

Ako već čovek želi da koristi ovaj hardver samo da primetim da u svakom "case" nedostaje "break" pa se uvek sve izvršava i onda switch nema smisla.

Hajde da se prvo na postojećem programu to ispravi. Sve ostalo neka bude u funkciji učenja.
[ mikikg @ 25.04.2018. 23:35 ] @
Da objasnim zasto stalno instistiram na ovom resenju sa Blue Pill i direktnim guranjem LED, igrom slucaja to je retka kombinacija svih pojedinacnih delova koji se savrseno lepo uklapaju i sa SW i sa HW.

Kao prvo STM32 ima stalno spominjanje BSRR registre koji nam omugucavaju da napokon mozemo da setujemo bilo koju nozicu na bilo kom portu bez read-modify-write, ja ne znam da li imaju drugi ne-ARM kontroleri koji to mogu da urade, ispravite me ako gresim.
Ta jedna jedina opcija nam daje preduslov na mozemo da se malo "opustenije" igramo u ISR rutini jer ne moramo da pazimo na raise-condition sve dok vodimo racuna koje nozice kontrolisemo iz ISR. Takodje bas ta opcija nam se savrseno lepo nadovezuje na to da 7-Seg LED modul (5x7seg) mozemo fizicki da umetnemo izmedju DIP-40 rastera koji zauzima Blue Pill sa druge strane plocice tako da nozice od displeja idu odmah na I/O nozicu i tacno ima malo izmedju prostora (jedna raster-rupica 2.54mm) gde se umetne seriski otpornik za LED. Izpovezane nozice se lepo konfigurisu u programu i to je resen problem displeja.
U programu kao sto rekoh pocinje prica ali na malo drugaciji nacin (bar sam ja to tako resavao), ima tajmer koji poziva ISR recimo na svakih 1ms (1kHz) koji radi potrebnu logiku za osvezavanje JEDNE CIFRE + isti ISR iskoristio za interne vremence posto mi je zgodna vremenska baza, tako sam dobio i vremensku bazu i brzo osvezavanje LED-a i to je sve skockano sa inline optimizovanim switch/case logikom, bez funkciskih poziva i zauzima minimalno procesorskog vremena. Veza izmedju ISR rutine i vrednosti na displeju je preko jedne globalne array sa 5 clanova i to je sve.
Ja zgodnije i jednostavnije HW / SW resenje nisam video od tog do sad ... Naravno nagledao sam se kojekakvih 8-bit MCU kod kojih MORA da se sloze portovi sa LED nozicama, ne mogu bilo koje nozice, sa STM32 mogu bilo koje nozice i to je to ...

Ja sam tako gurao do 6 cifri direktno iz STM32 i to sa oversamplovanim (internim) 18bit-A/D, kao nesto zbog shuma ovo-ono ... ma radi to sve ko zmaj ...


[ uart @ 26.04.2018. 05:24 ] @
Kao što reče kolega mbm za prijem podataka treba koristiti serijski interapt, evo primera koda:

Code:


#define RECBUFLEN 20
...........................


volatile unsigned char recv_bufptr=0;
volatile bit ser_received=0; 
volatile unsigned char dummy;

volatile unsigned char recv_buf[RECBUFLEN]; 

........................

void serial_isr (void) interrupt 4
{
   if (RI) {
           RI = 0;
           dummy = SBUF;

           switch (dummy)
               {

           case 0x02: start_OK = 1; recv_bufptr = 0; break; /* pocetak prijema */
            
           case 0x03: ser_received = 1; start_OK = 0; break; /* podaci primljeni */
            
           default: if (start_OK) {if (recv_bufptr < RECBUFLEN) {recv_buf[recv_bufptr] = dummy; recv_bufptr++;}} break;  /* upis u bafer */
            

                 }  /* switch */
               
           } /* if */
   
   else    {
           TI = 0;
           }

}

.......................

/* u glavnoj petlji */

if (ser_received)
   {
   EA = 0;

   /* obrada primljenih podataka */

   EA = 1;
   ser_received = 0;
   }

..............





Naravno, mora de se izmeni i rutina za tajmer interapt.


[ veselinovic @ 26.04.2018. 06:01 ] @
Citat:
bogdan.kecman:
@veselinovic

sto "Pogasis izlaze za anode displeja" ?

kad zabodes katodu ugasi se display, promenis izlaze anode, upalis
katodu, cemu tak korak setovanja anode na intermediate vrednost?



Bogdan je u pravu ( pleonazam),
dosao onaj nijemac ( kako se ono zvase) i sapnuo mi :)
[ janko11 @ 26.04.2018. 08:57 ] @
Ok. Hvala na predlozima. Sta konkrentno treba da se izmeni u kodu za timer interrupt? Moze li izmena?
[ mikikg @ 26.04.2018. 12:56 ] @
Samo shemu da vidite, da li ima nesto "lepse i jednostavnije" od ovoga trenutno na planeti sa tom kolicinom delova koja ipak radi nesto korisnu u pozadini osim sto svicka po LED? :)

Kad budu napravili MAX7219 da moze isto ovako da se programira onda cu da predjem na njega, mozda : )

[ mbm @ 26.04.2018. 15:06 ] @
Citat:
mikikg:
Da objasnim zasto stalno instistiram na ovom resenju sa Blue Pill i direktnim guranjem LED, igrom slucaja to je retka kombinacija svih pojedinacnih delova koji se savrseno lepo uklapaju i sa SW i sa HW.

Kao prvo STM32 ima stalno spominjanje BSRR registre koji nam omugucavaju da napokon mozemo da setujemo bilo koju nozicu na bilo kom portu bez read-modify-write, ja ne znam da li imaju drugi ne-ARM kontroleri koji to mogu da urade, ispravite me ako gresim.
Ta jedna jedina opcija nam daje preduslov na mozemo da se malo "opustenije" igramo u ISR rutini jer ne moramo da pazimo na raise-condition sve dok vodimo racuna koje nozice kontrolisemo iz ISR. Takodje bas ta opcija nam se savrseno lepo nadovezuje na to da 7-Seg LED modul (5x7seg) mozemo fizicki da umetnemo izmedju DIP-40 rastera koji zauzima Blue Pill sa druge strane plocice tako da nozice od displeja idu odmah na I/O nozicu i tacno ima malo izmedju prostora (jedna raster-rupica 2.54mm) gde se umetne seriski otpornik za LED. Izpovezane nozice se lepo konfigurisu u programu i to je resen problem displeja.
U programu kao sto rekoh pocinje prica ali na malo drugaciji nacin (bar sam ja to tako resavao), ima tajmer koji poziva ISR recimo na svakih 1ms (1kHz) koji radi potrebnu logiku za osvezavanje JEDNE CIFRE + isti ISR iskoristio za interne vremence posto mi je zgodna vremenska baza, tako sam dobio i vremensku bazu i brzo osvezavanje LED-a i to je sve skockano sa inline optimizovanim switch/case logikom, bez funkciskih poziva i zauzima minimalno procesorskog vremena. Veza izmedju ISR rutine i vrednosti na displeju je preko jedne globalne array sa 5 clanova i to je sve.
Ja zgodnije i jednostavnije HW / SW resenje nisam video od tog do sad ... Naravno nagledao sam se kojekakvih 8-bit MCU kod kojih MORA da se sloze portovi sa LED nozicama, ne mogu bilo koje nozice, sa STM32 mogu bilo koje nozice i to je to ...

Ja sam tako gurao do 6 cifri direktno iz STM32 i to sa oversamplovanim (internim) 18bit-A/D, kao nesto zbog shuma ovo-ono ... ma radi to sve ko zmaj ...





Ali naš prijatelj nije pitao za 32 bitni STM ARM miktrokontroler već za konkretan problem sa arhitekturom koju je odlučio da koristi a to je 8051 u osnovi.
STM32 je odličan ali nije mcs51 arhitektura. Ako neko misli da je starudija spora verujte greši a read-modify-write koncept kod 8051 ni ne postoji jer ne može da čita koje stanje izlaza je zadato nekom ranijom komandom već čita samo fizičko stanje.
AT89LP serija je za mene odlična. Koliko će potrajati i treba li ga proučavati u dubinu u vreme drugih naprava ne mogu da kažem, ali bar vredi videti šta može.



[ mbm @ 27.04.2018. 12:52 ] @
Upravo sam ponovo pročitao naše postove na temi i shvatio da deluju baš nadmeno sve sa korišćenjem primerenih izraza ali nepotrebnih i slabo razumljivih u ovom slučaju, a čovek je samo pitao kako da nešto da uradi. Evo ja se u moje ime izvinjavam. Ako postavljač teme želi pomoći ću efikasnije koliko mogu.

Milan
[ janko11 @ 29.04.2018. 16:17 ] @
Koji deo u kodu za prekidnu rutinu timera, treba ispraviti da bi sve to funkcionisalo bez problema?
[ mbm @ 30.04.2018. 01:17 ] @
Vidi Janko da otklonimo prvo neke druge greške.
Ne mogu na šemi da pročitam ništa ali ako su displeji neki standardni nije mi jasno kako to još nije pocrkalo kad nema ostpornike na linijama sa uln2803 prema displejima. Prvo to da se reši pa onda:



Ovo je glavna programska petlja u main
while (1) {
initSerial();
showNumber();
// print();
// TH0=0xFF;
// TL0=0xFF;
delayTimer(); // kod petlji u interrup
}


tu se stalno u krug poziva :

void initSerial()

To ne treba da radiš. initSerial() treba da pozoveš samo jednom posle reseta (dakle na početku rada a pre ulaska u glavnu programsku petlju)
jer je ovo samo jednokratno podešavanje načina rada i startovanje serijskog porta. Inicijačlizacija je početno podešavvanje načina rada pa ga ne treba stalno beskonačno pozivati.
ovo lepo radi ali večno čeka na karakter i ništa drugo ne radi osim ako ima neki interapt.
// prijem podataka
char receiveData() {
char el;
while (RI == 0);
el = SBUF;
RI = 0;
return el;
}

Napiši prvo prijem karaktera u jednu globalnu promenljivu preko serijskog interapta. Postavi jedan bit global flag kao znak da imaš primljen karakter pa u main while petlji tek ako ima promene ti obrađuj a ko nem asamo obnavljaj displej. Toćeš ispraviti kasnije Pokušaj prvo ovo. Nemoj pokušavati odmah da pišeš serijski cirkularni bafer. to posle...

[ janko11 @ 09.05.2018. 12:36 ] @
Napisao sam funkciju za serijski interrupt i koristio flegove. Sada cifre ne trepere. Evo koda i za interrupt timera:

switch(disp)
{
case 1:
INH=0;
C=0;
BB=0;
A=1;
displayDigit(tmp5);
delay(5);
break;
case 2:
INH=0;
C=0;
BB=1;
A=0;
displayDigit(tmp4);
delay(5);
break;
case 3:
INH=0;
C=0;
BB=1;
A=1;
displayDigit(tmp3);
delay(5);
break;
case 4:
INH=0;
C=1;
BB=0;
A=0;
displayDigit(tmp2);
delay(5);
break;
case 5:
INH=0;
C=1;
BB=0;
A=1;
displayDigit(tmp1);
delay(5);
break;
}
disp++;
if(disp>6)
disp=1;

Sta je potrebno izmeniti u navedenom kodu da bi na displeju recimo umesto 01234 pisalo 1234 ili umesto 00675 pisalo 675?
[ mbm @ 09.05.2018. 17:29 ] @
Na konkretno pitanje konkretan odgovor u duhu koda koji je već napisan (sve ovo se u principu radi sasvim drugačije ali ako kažeš da sad radi kao što želiš onda je u redu.)

u duhu datog koda:

ako je tmp5 najviša težinska cifra a tmp1 najniža onda predlažem da uz jednu pomoćnu unsigned char promenljivu za ovu namenu, nazvaću je nula dopišeš...

copy / past tvog koda pa dodato to što ti treba s tim što ne obraćam pažnju na selekciju dipleja u multipleksu pa neću dirati INH, C, BB, A to se pobrini sam ali ni ne moraš neka ostane ovako samo se pobrini za displayDigit da ugasi displeje na sadrzaj 255



nula=0;
switch(disp)
{
case 1:
INH=0;
C=0;
BB=0;
A=1;
nula+=tmp5;
if (nula){displayDigit(tmp5);}else{displayDigit(0xFF);}// u funkciju displayDigit stavi da ako je 255 budu ugaseni segmenti
delay(5);
break;
case 2:
INH=0;
C=0;
BB=1;
A=0;
nula+=tmp4;
if (nula){displayDigit(tmp4);}else{displayDigit(0xFF);}
delay(5);
break;
case 3:
INH=0;
C=0;
BB=1;
A=1;
nula+=tmp3;
if (nula){displayDigit(tmp3);}else{displayDigit(0xFF);}
delay(5);
break;
case 4:
INH=0;
C=1;
BB=0;
A=0;
nula+=tmp2;
if (nula){displayDigit(tmp2);}else{displayDigit(0xFF);}
delay(5);
break;
case 5:
INH=0;
C=1;
BB=0;
A=1;
displayDigit(tmp1);
delay(5);
break;
}
disp++;
if(disp>6)
disp=1;

[ mbm @ 11.05.2018. 16:29 ] @
Šta bi Janko, da li je sad u redu?
[ janko11 @ 14.05.2018. 12:22 ] @
Probacu danas ili sutra. Nisam mogao ovih dana. Javljam cim probam. Samo jedno pitanje, za prikaz decimalne tacke na displeju, moralo bi se u funkciji displayDigit napraviti maska na isti nacin, kao sto sam radio za ostale cifre, ili postoji neki drugi nacin da se u programu podesi ukljucivanje decimalne tacke?
[ mbm @ 14.05.2018. 17:28 ] @
Najlakše je da se i tačka tretira kao segment ako ima dosta vodova, pa ubaciš i taj bit u masku.
[ mikikg @ 15.05.2018. 10:46 ] @
Decimalna tacka treba da ima svoju logiku koja je malo odvojena od 7-seg logike.

Konkretno ne moze iz jedne komande da se upise i broj i tacka, tehnicki moze ali logicki nije prakticno.
Dakle 7-seg se obraduje kako se obraduje a decimalna tacka treba da ima jednu variablu gde se upisuje pozicija tacke, 0=nema tacke, 1=prva cifra levo, 2=druga cifro levo i tako dalje.

U interapt rutini ili funkciji koja obraduje 7-seg treba dodati tu logiku koja za izabrano decimalno mesto u trenutku kada se osvezava pojedinacna cifra i ako je izabrana decimalna tacka bas na tom mestu onda se aktivira i bit koji pali DP dok u svim ostalim situacijama gasi DP.
[ veselinovic @ 15.05.2018. 11:36 ] @
ili ako imas slobodnih pinova vozis DP direktno sa pina bez multipleksa.
[ mbm @ 15.05.2018. 15:06 ] @
Ako ima slobodnih pinova (a nekako nazirem na šemi da ima) onda taj jedan pin staviti kao osmi bit koji prolazi kroz ULN2803 i vrlo jednostavno se može koristiti pokretna tačka jer se upravlja isto kao bilo koji drugi segment (recimo to ovako umesto 7 ima 8 segmenata.)

"Konkretno ne moze iz jedne komande da se upise i broj i tacka, tehnicki moze ali logicki nije prakticno."

Konkretno može pozivom jedne funkcije (dakle jednom komandom) da se upiše i broj i tačka u smislu ima tačke ili nema tačke na datom displeju. I veoma je praktično samo stanje treba generisati u istoj funkciji gde se vrši konverzija u cifarska mesta.

Naravno ako je fiksna decimalna tačka onda nema potrebe za svim tim.

Ako se float pretvara u cifre za prikazivanje lako je unutar te funkcije staviti i jedan bajt čiji bitovi pokazuju postojanje ili nepostojanje decimalne tačke na ovakvom displeju slično kao što reče mikikg. To je samo poređenje težinskih mesta celobrojnog dela float. Vrlo je jednostavno i praktično.

U svakom slučaju tretiraj tačku kao osmi segment u ovakvoj upotrebi.

Milan

[ janko11 @ 04.06.2018. 09:58 ] @
Nisam stigao da odgovorim. Decimalna tacka radi. Da li postoji neka mogucnost da se u programu kod inicijalizacije serijskog porta podesi da se bira baudrate izmedju vise vrednosti, umesto da se stavi fiksna vrednost? Moze li neka smernica u kom pravcu treba razmisljati? Hvala svima na odgovorima i savetima.
[ mbm @ 05.06.2018. 01:32 ] @
Može, samo reci kako bi hteo da aktiviraš različite brzine. Zapravo može se napisati "autobaud", da se prijemni deo prilagodi brzini kojom se spoljašnji uređaj obraća serijskom portu, pa kad automatski odredi prijemnu brzinu podesi i predajnu. Nije komplikovano, smišljeno pre oko 30 godina ali ipak treba malo više programske memorije nego obična inicijalizacija.
https://www.pjrc.com/tech/8051/autobaud.html
Evo jednog načina ali orginalni način je mislim baš Intelov a Paul ga samo primenio.

Opet kažem zavisi šta hoćeš da postigneš.
Evo ti zgodan program da ne moraš da računaš na kalkulatoru:
https://www.8051projects.net/d...ytimer-routine-calculator.html

(Division je 12 kao standardni delilac oscilatora a ako koristiš AT89LP.... ili drugi tako zmijski brz onda je delilac 1.)
[ janko11 @ 05.06.2018. 15:08 ] @
Evo koda kako sam zamislio:

Code:

   void bRate()
   {
    switch(pom)
    {
        case 1:
                TH1=0xA0; // baudrate=300
            baud=jurbaud();
            if(baud==1)
               TR1=1;
        break;
        case 2:
            TH1=0xD0; // baudrate=600
            baud=jurbaud();
            if(baud==1)
            TR1=1;
        break;
        case 3:
                TH1=0xE8; // baudrate=1200
             baud=jurbaud();
             if(baud==1)
                 TR1=1;
            break;
        case 4:
            TH1=0xF4; // baudrate=2400
             baud=jurbaud();
             if(baud==1)
                TR1=1;
        break;
        case 5:
            TH1=0xFA; // baudrate=4800
            baud=jurbaud();
            if(baud==1)
            TR1=1;
        break;
        case 6:
                TH1=0xFD; // baudrate=9600
            baud=jurbaud();
            if(baud==1)
               TR1=1;
      break;
    }
    pom++;
    if(pom>7)
        pom=1;
}

unsigned int jurbaud()
{
    int i;
    for(i=0;i<10;i++)
    {
        if(RI)
        {
            el=SBUF;
            RI=0;
            if(el==0x02)  // pocetak komunikacije
                baudrate=1;
            else 
                baudrate=0;
        }
    }
    return baudrate;
}

void initSerial()
{
    TMOD&=0x0F;
    TMOD|=0x20;
    SCON=0xD0;
//    TH1=0xFD;
    TR1=1;
}

// main funkcija

void main()
{
  ...
 initSerial();
 while(1)
 {
     bRate();
 }
}



Baudrate, baud i pom su globalne promenljive.
Funkcionise za baudrate=9600, za ostale brzine ne radi. Da li sam na pravom putu ili je pogresan pristup? Ako je pogresan pristup, kako bi moglo da se uradi, da se detektuje baudrate izmedju vise razlicitih brzina. Frekvencija oscilatora je 11.0592MHz. Pogledao sam nacin koji je Paul primenio.

[Ovu poruku je menjao janko11 dana 05.06.2018. u 16:18 GMT+1]
[ mbm @ 05.06.2018. 18:14 ] @
Citat:
janko11:
Nisam stigao da odgovorim. Decimalna tacka radi. Da li postoji neka mogucnost da se u programu kod inicijalizacije serijskog porta podesi da se bira baudrate izmedju vise vrednosti, umesto da se stavi fiksna vrednost? Moze li neka smernica u kom pravcu treba razmisljati? Hvala svima na odgovorima i savetima.


Ovaj program koji si poslao po svom konceptu ne može da radi to što je napisano da bi trebalo da radi u gornjem citatu.
Opet je pomešana inicijalizacija sa redovnim radom. Moram da te podsetim da je SBUF validan tek ako je postavljen flag RI! dakle nema čitanja SBUF dok RI nije jednak 1 a takođe kad jednom pročitaš SBUF on više nije validan. a RI moraš sam da resetuješ.

Izbriši ovo sve. Koncept nije dobar i ovako ne može da se odredi kojom brzinom je poslat bajt ka 8051.

1. Predlažem da ne gubiš vreme sa autobaud algoritmom jer mislim da to nema neku pravu primenu.
2. Ako hoćeš da menjaš "u letu" brzinu onda prvo onemogućiš prijem pa podesiš reload vrednosti tajmera na novu vrednost pa omogućiš prijem i imaš novu brzinu.

Uostalom imaš gore link na fin kalkulator ne moraš da računaš.

Evo inicijalizacije na 19200 iz tog kalkulatora


//Replace x with timer no.
//Configure and Enable timer.
//Timer Clk=11.0592/12*1 = 0.9216 MHz
PCON |= 0x80 //Set SMOD
SCON = 0x50; //8-bit,rx enable
TLx = 0x00; //Lower Byte
THx = 0xFD; //Upper Byte
TRx = 1; //Run timer

Evo isto iz njega inicijalizacije za 4800

//Replace x with timer no.
//Configure and Enable timer.
//Timer Clk=11.0592/12*1 = 0.9216 MHz
PCON |= 0x80 //Set SMOD
SCON = 0x50; //8-bit,rx enable
TLx = 0x00; //Lower Byte
THx = 0xF4; //Upper Byte
TRx = 1; //Run timer


i to je urađeno JEDNOM NA POČETKU. Kasnije kad po nekom kriterijumu hoćeš da menjaš brzinu onda samo onemogući prijem na kratko promeni TH bajt na novu vrednost i ponovo pokreni prijem. To je zgodno ako GSM modul radi sa procesorom na 19200 a GPS/GLONASS na 4800 a prebacuješ procesorov port sa jedne na drugu periferiju.


Inače jesi li stavio gašenje vodeće nule kao što si hteo.

A ovo mi bode oči:

int i;
for(i=0;i<10;i++) ......

zašto za ime sveta int i ? to čak nije ni signed a ne unsigned char za to što broji ? nije to tridestdvobitni ARM :)
[ janko11 @ 06.06.2018. 12:26 ] @
Resen je problem sa nulom. Gde treba dodati menjanje brzine, u funkciji za inicijalizaciju serijskog porta? Posto ovo radim prvi put, mozes li da mi napises primer, da prijem podataka recimo zapocne brzinom 9600, pa se posle "u letu" promeni recimo na 2400, jer meni nikako ne uspeva to menjanje brzine?
[ mbm @ 06.06.2018. 18:15 ] @


Hajde prvo dobro prouči (komotno prepiši šta ti treba) a vrednost za TH1 za određenu brzinu izračunaj onim programom od gore.
Nema potrebe da ponavljam što je u ovom linku napisano, sasvim je korektno.

https://www.8051projects.net/w.../Serial_Communication_Tutorial
Ako bude i dalje trebalo pošalji mi privatnu poruku pošto ovo druge ne zanima pa ću ti poslati uzvratno.



[ janko11 @ 03.07.2018. 10:46 ] @
Potreban mi je jos jedan mali savet. Naime, na port P1 procesora povezani su preko ULN2803 kola displeji. Takodje, Q1-Q7 izlazi kola 74HC573 povezani su na P1 port procesora, dok su na D4, D5,D6 i D7 ulaze kola 74HC573 povezani E0,A2,A1,A0 izlazi kola 74LS148. OE pin kola 74HC573 povezan je na x7 izlaz kola 4051. Ideja je da se u zavisnosti od vrednosti A2,A1,A0 kola 74LS148 na displeju prikazu odgovarajuce poruke, a kada nije aktivan nijedan od ulaza 74LS148, na displeju prikaze ono sto se prima sa serijskog porta. Sve mi je to jasno sta treba raditi. Ali ono sto mi predstavlja problem, je kako nakon sto procesor na P1 portu detektuje koju poruku treba prikazati, promeniti ulogu porta P1 da on sada ukljuci segmente na displeju, da bi se prikazala poruka? Da li moze neko da mi da savet kako ili u kom pravcu treba razmisljati da bi se resio navedeni problem? U prilogu dostavljam navedenu semu. Hvala unapred svima na odgovorima i savetima.

[ janko11 @ 10.07.2018. 11:15 ] @
Kod u prilogu ispisuje poruku na displeju. Kod odlicno radi kada je OE pin 74HC573 kola povezan direktno na procesor. Medjutim, kada se OE pin 74HC573 kola poveze na x7 izlaz kola 4051 (multipleksera) poruka se ne ispisuje na displeju onako kako bi trebalo. Poruka je START. Moze li mi neko reci, gde je problem u navedenom kodu, zbog cega ne radi kada je OE pin 74HC573 povezan na kolo 4051? Hvala unapred na savetima i odgovoru.

Code:

 void timer0(void) interrupt 1
 {
    TH0=0xFC;
    TL0=0x66;
    switch(disp)
        {
            case 1:
               C=0;
           BB=0;
           A=1;
     //           oe=0;
           P3=P3|0xE3; // OE=0 kod 74HC573
                if(q5==0 && q6==0 && q7==0)
        {
     //             oe=1;
             P3=P3&0x03; // disable 74HC573
             displayDigit('T');
             delay(5);
             displayDigit(0xFF);
        }
            break;
            case 2:
               C=0;
           BB=1;
           A=0;
      //       oe=0;
           P3=P3|0xE3; // OE=0 kod 74HC573
           if(q5==0 && q6==0 && q7==0)
           {
      //         oe=1;
             P3=P3&0x03; // disable 74HC573
             displayDigit('R');
             delay(5);
             displayDigit(0xFF);
           }
            break;
            case 3:
               C=0;
           BB=1;
           A=1;
      //       oe=0;
           P3=P3|0xE3; // OE=0 kod 74HC573
           if(q5==0 && q6==0 && q7==0)
           {
     //            oe=1;
            P3=P3&0x03; // disable 74HC573
            displayDigit('A');
            delay(5);
            displayDigit(0xFF);
        }
            break;
            case 4:
               C=1;
           BB=0;
           A=0;
       //      oe=0;
           P3=P3|0xE3; // OE=0 kod 74HC573
           if(q5==0 && q6==0 && q7==0)
           {
       //           oe=1;
             P3=P3&0x03; // disable 74HC573
             displayDigit('T');
             delay(5);
             displayDigit(0xFF);
        }
            break;
            case 5:
                C=1;
            BB=0;
            A=1;
        //    oe=0;
            P3=P3|0xE3; // OE=0 kod 74HC573
            if(q5==0 && q6==0 && q7==0)
            {
       //         oe=1;
             P3=P3&0x03; // disable 74HC573
             displayDigit('S');
             delay(5);
             displayDigit(0xFF);
        }
           break;
        }
        disp++;
    //  oe=0;
         P3=P3|0xE3;
         if(e0==1 && q5==0 && q6==0 && q7==0)
     {
    //            oe=1;
            P3=P3&0x03;
            if(disp>5)
             disp=1;
     }
 }
[ janko11 @ 16.08.2018. 09:28 ] @
Da li moze neko da mi da konkretan savet u vezi jednog problema? Naime, program treba da na displeju prikaze odredjenu poruku. Kada testiram program u simulatoru, sve savrseno radi, ali kada se program izvrsava na fizickom hardveru, dolazi do problema, ne ukljucuju se svi segmenti, samim tim poruka se ne prikazuje kako treba. Procesor je 80C32. DIP Switch su povezani na ulaz 74HC573, 74HC573 je povezan na P1 port procesora, takodje na P1 port procesora preko ULN2803 povezani su i displeji. Kombinacijom DipSWitch - eva prikazuje se odredjena poruka. Da li moze neko da mi pomogne oko datog problema, posto mi je potrebna pomoc? Hvala unapred svima na savetima i odgovorima.
[ bogdan.kecman @ 16.08.2018. 09:36 ] @
Citat:
janko11: Da li moze neko da mi da konkretan savet u vezi jednog problema? Naime, program treba da na displeju prikaze odredjenu poruku. Kada testiram program u simulatoru, sve savrseno radi, ali kada se program izvrsava na fizickom hardveru, dolazi do problema, ne ukljucuju se svi segmenti, samim tim poruka se ne prikazuje kako treba. Procesor je 80C32. DIP Switch su povezani na ulaz 74HC573, 74HC573 je povezan na P1 port procesora, takodje na P1 port procesora preko ULN2803 povezani su i displeji. Kombinacijom DipSWitch - eva prikazuje se odredjena poruka. Da li moze neko da mi pomogne oko datog problema, posto mi je potrebna pomoc? Hvala unapred svima na savetima i odgovorima.


prvo, mislim da je bilo bolje da si otvorio zasebnu temu za ovaj rpoblem
drugo, ja te nista nisam skontao sta si uradio?!
573 je transparent latch kakve veze imaju dip switchevi sa latch-em? namestis switch pa mcu upali OE procita dip pa ugasi OE da bi koristio P1 za display? kakav display koristis 7seg? koliko komada? 1 ili vise? moraces da pokazes semu posto iz teksta nije jasno sta si uradio...

a 99% je pitanje tajminga to sto radi u simulatoru a ne radi live
[ janko11 @ 16.08.2018. 10:22 ] @
Otvoricu posebnu temu za dati problem, ali da posaljem odgovor i ovde. Displeji su sa zajednickom anodom. Ima ih 6, ali se samo 5 ukljucuju i na njima se ispisuje poruka.
Navedeni program gde se ispisuje poruka izgleda ovako:
Code:

 void timer0(void) interrupt 1

  TH0=0xFC;
  TL0=0x66;
  switch(disp)
  {
    case 1:
       C=1;
       BB=1;  // OE=0 kod 573
       A=1;
       if(e0==1 && q4==0 && q5==0 && q6==0)  // proveri koji je switch pristisnut
        pom=1;
    break;
    case 2:
       C=1;
       BB=0;
       A=1;
       if(pom==1)
          displayDigit('S');
       delay(5);
    break;
    case 3:
       C=1;
           BB=0;
       A=0;
       if(pom==1)
          displayDigit('T');
       delay(5);
    break;
    case 4:
       C=0;
       BB=1;
       A=1;    
           if(pom==1)
          displayDigit('A');
       delay(5);
    break;
    case 5:
       C=0;
       BB=1;
           A=0;
       if(pom==1)
          displayDigit('R');
       delay(5);
    break;
        case 6:
       C=0;
       BB=0;
       A=1;
       if(pom==1)
          displayDigit('T');
      delay(5);
    break;
    }
    disp++;
    if(disp>6)
      disp=1;
}

// funkcija koja ukljucuje masku
void displayDigit(unsigned char cifra)
{
   switch(cifra)
   {
      case 'S': P1=0x6D; break;
      case 'T': P1=0x78; break;
      case 'A': P1=0x77; break;
      case 'R': P1=0x50; break;
   }
}

void delayTimer()
{
  TMOD&=0xF0;
  TMOD|=0x01;
  TH0=0xFC;
  TL0=0x66;
  TR0=1;
}


U prilogu dostavljam i semu
[ bogdan.kecman @ 16.08.2018. 10:43 ] @
cisto da dodamo link na novu temu:
http://www.elitesecurity.org/t500083-0#3849223