Novo

Forum kao aplikacija na telefonu

Dodajte forum na početni ekran i koristite ga kao aplikaciju, sa menijem na dnu ekrana.

  • 63 odgovora
  • 14.321 pregleda

Najnovija ↓

ATMEL 89C51 zadatak u C 29.11.2015. u 13:50 · pre 132 meseca #1
Potrebno je napisati program u C za 8051 koji omogucuje ispis na displej(memorijski mapiran na adresi 0x8001) SAMO brojeve u datom nizu od sedam proizvoljnih elemenata koji su deljivi sa tri.
Brojeve ispisivati svake sekunde.

Pokusao sam da resim ali mi nije ne registruje deljenje nego samo ispisuje SVE brojeve redom u nizu i znatno brze od jedne sekunde.
Ideja je napraviti 50ms (C350 HEX) u tajmeru i preko brojaca napraviti 20 prekida jer 50ms *20=1 s

Ako neko zna gde je greska u kodu, neka napise ..
Hvala !

Code:

#include <reg51.h> 
#include <math.h>                  
typedef unsigned char byte;

byte a[7]= {7,5,16,1,4,11,9}; 

byte counter;
byte xdata display _at_ 0x8001;
byte started = 0;
int i=0;

sbit switcher=P0^0;
 
void Inic(void) 
{
    EA=1;         
    TMOD=1;       //  16 bit timer
    TH0=0xC3;     // set timer0  0xC350
    TL0=0x50;     // 50,000 decimalno
    TR0=1;
    counter=1;    // set brojac
}

 
void timer0(void) interrupt 1 using 2 
{    
    TH0=0xC3;  // set timer0  C350 = 50,000
    TL0=0x50;   // posle svakog prekida                   
    
    counter--;  // broj prekide
    if(counter == 0)      // broj 20 prekida za 1 sec kasnjenja     
       {
       counter = 20;        
       if(started == 1)  
         {
         if(i < 7)              //ako je i<7 deli sa tri brojeve u nizu
            if((a[i]/3) )       //    deli brojeve u nizu sa 3
               display=a[i];                            // ako su deljivi, ispisi na displej
         i++;             // inkrementiranje za  novu vrednost u nizu
         if(i == 7)        // kada se prodju svi elementi u nizu ,resetuj tajmer                         
            {
            ET0 = 0;      // disable timer 0 
            TR0 = 0;      // stop timer0 - svi u nizu su provereni
            started = 0;  // started = 0,zaustavi kada se prekidac opet stisne 
            }
         }
       }
}

void main(void) 
{
   Inic();        
   switcher = 1;  // prekidac se startuje na 1
                   
   while(1)       
     {                    
     if(switcher == 0)    
       if(started == 0)   
          {         
          started = 1;    // started ide na 1 kada je prekidac pritisnut
          i = 0;          // postavi i na prvi broj u nizu
          counter = 20;    // ceka se 1 sekunda
                          // 
          TH0=0xC3;       // set timer0 na 0xC350
          TL0=0x50;      // 50,000 decimalno
          ET0=1;          // enable timer0 
          TR0=1;          // start timer0        
          }
     }            
} 


Re: ATMEL 89C51 zadatak u C 29.11.2015. u 17:04 · pre 132 meseca #2
Code:
if(!(a[i]%3) )      
    display=a[i];                            // ako su deljivi, ispisi na displej


Kontrolišeš ostatak deljenja i ako je 0...
Potpis
__*__
*___*
Sviđa mi se1
Re: ATMEL 89C51 zadatak u C 29.11.2015. u 17:23 · pre 132 meseca #3
Hvala.
Tacnije sada pokazuje ali kada sam dodao jos par elemenata niza na kraju uocim samo promenu dioda na displeju koja odgovara prvom broju 3
{3,7,5,16,1,4,11,9,6}

Verovatno se prebrzo menja pa ne mogu da uocim. Trebao bi da prikazuje 3,9 i 6 iz niza. Treba broj po sekundi ali je dosta brze !!

Trebao bih nekako drugacije da brojac vracam na nulu ili ?

I koja je razlika izmedju
Code:

  1)  if(!(a[i]%3) )      
       display=a[i]; 

  ILI 

   2)  result =a[i]/3;
        display=result;

ili

     3)  if((a[i]/3) )      
         display=a[i]; 
Re: ATMEL 89C51 zadatak u C 29.11.2015. u 20:49 · pre 132 meseca #4
Brojač broji od 0 ka FFFF i na svaki interapt ga setuješ sa FFFF-C350...
Potpis
__*__
*___*
Sviđa mi se1
Re: ATMEL 89C51 zadatak u C 29.11.2015. u 21:21 · pre 132 meseca #5
Da,jeste. Sada je jedna sekunda ali za jednu sekundu promeni mi sva stanja.
Meni treba da posle svakog broja u nizu prodje 1 sekunda,a ne kada protrici kroz sve vrednosti koje su deljive sa tri.
Nije mi jasno kako da to omogucim , sekunda po jednom broju u nizu?
Re: ATMEL 89C51 zadatak u C 30.11.2015. u 14:30 · pre 132 meseca #6
Treba da prebacis pauzu iza ispisivanja broja.
Dakle nasao si broj djeljiv sa 3.
Posaljes taj broj na displej i okines brojanje vremena.
Kad isteken vrijeme nastavis sa ispitivanjem brojeva.
Re: ATMEL 89C51 zadatak u C 30.11.2015. u 17:05 · pre 132 meseca #7
Da, tako bi trebalo. Ali ne moze to tek tako ...
Ako resetujem pre tj posel ispisivanja,nece ici na sledeci broj..
Ne znam sta drugo da prebacim ?
Re: ATMEL 89C51 zadatak u C 30.11.2015. u 17:07 · pre 132 meseca #8
Citat:
veselinovic:
Treba da prebacis pauzu iza ispisivanja broja.
Dakle nasao si broj djeljiv sa 3.
Posaljes taj broj na displej i okines brojanje vremena.
Kad isteken vrijeme nastavis sa ispitivanjem brojeva.



Da, tako bi trebalo. Ali ne moze to tek tako ...
Ako resetujem pre tj posel ispisivanja,nece ici na sledeci broj..
Ne znam sta drugo da prebacim ?
Re: ATMEL 89C51 zadatak u C 30.11.2015. u 18:45 · pre 132 meseca #9
Kako si podesio preskaler brojača i koji je kristal?
Potpis
__*__
*___*
Re: ATMEL 89C51 zadatak u C 30.11.2015. u 19:33 · pre 132 meseca #10
Kristal je 12MHz

50 000*20=1s

FFFF-C350=3CAF

preskaler je podesen sada na
TH0=0x3C
TL0=0xAF
-----------------------------------------

Re: ATMEL 89C51 zadatak u C 30.11.2015. u 19:36 · pre 132 meseca #11
Sadasnji kod je sledeci

Code:


#include <reg51.h> 
#include <math.h>                  
typedef unsigned char byte;

byte a[7]= {7,5,16,1,4,11,9}; 

byte counter;
byte xdata display _at_ 0x8001;
byte started = 0;
int i=0;

sbit switcher=P0^0;
 
void Inic(void) 
{
    EA=1;         
    TMOD=1;       //  16 bit timer
    TH0=0x3C;     // set timer0  0xC350
    TL0=0xAF;     // 50,000 decimalno
    TR0=1;
    counter=1;    // set brojac
}

 
void timer0(void) interrupt 1 using 2 
{    
    TH0=0x3C;  // set timer0  C350 = 50,000
    TL0=0xAF;   // posle svakog prekida                   
    
    counter--;  // broj prekide
    if(counter == 0)      // broj 20 prekida za 1 sec kasnjenja     
       {
       counter = 20;        
       if(started == 1)  
         {
         if(i < 7)              //ako je i<7 deli sa tri brojeve u nizu
            if(!(a[i]%3) )       //    deli brojeve u nizu sa 3
               display=a[i];                            // ako su deljivi, ispisi na displej
         i++;             // inkrementiranje za  novu vrednost u nizu
         if(i == 7)        // kada se prodju svi elementi u nizu ,resetuj tajmer                         
            {
            ET0 = 0;      // disable timer 0 
            TR0 = 0;      // stop timer0 - svi u nizu su provereni
            started = 0;  // started = 0,zaustavi kada se prekidac opet stisne 
            }
         }
       }
}

void main(void) 
{
   Inic();        
   switcher = 1;  // prekidac se startuje na 1
                   
   while(1)       
     {                    
     if(switcher == 0)    
       if(started == 0)   
          {         
          started = 1;    // started ide na 1 kada je prekidac pritisnut
          i = 0;          // postavi i na prvi broj u nizu
          counter = 20;    // ceka se 1 sekunda
                          // 
          TH0=0x3C;       // set timer0 na 0xC350
          TL0=0xAF;      // 50,000 decimalno
          ET0=1;          // enable timer0 
          TR0=1;          // start timer0        
          }
     }            
} 

Re: ATMEL 89C51 zadatak u C 01.12.2015. u 01:03 · pre 132 meseca #12
Koji kompajler koristis? Mislim da na 8051 moras da ocistis interapt flegove pri ulasku u interapt rutinu. Ako to ne uradis, moze da se desi da se naknadni isteci tajmera ne obradjuju ili u gorem slucaju da kontrolor ostane zaglavljen u interapt rutini. Pogledaj datasheet.
Re: ATMEL 89C51 zadatak u C 01.12.2015. u 10:58 · pre 132 meseca #13
Koristim KEIL microvison program.
Ne koristim pravu maketu nego KEL maketu sa diodama u softveru..
Re: ATMEL 89C51 zadatak u C 01.12.2015. u 16:47 · pre 132 meseca #14
Zna li neko nacin da se svaki broj kao rezultat prikaze svake sekunde ? :)
Re: ATMEL 89C51 zadatak u C 01.12.2015. u 21:10 · pre 132 meseca #15
Ja bih, za početak, pojednostavio interapt rutinu:


Umesto

Code:

void timer0(void) interrupt 1 using 2 
{    
    TH0=0x3C;  // set timer0  C350 = 50,000
    TL0=0xAF;   // posle svakog prekida                   
    
    counter--;  // broj prekide
    if(counter == 0)      // broj 20 prekida za 1 sec kasnjenja     
       {
       counter = 20;        
       if(started == 1)  
...
...
}


uveo bih flag update_display, pa bi ovaj deo koda izgledao ovako:

Code:

byte counter = 20;
byte update_display = 0;


void timer0(void) interrupt 1 using 2 
{    
TR0 = 0; //zaustavi tajmer
    TH0=0x3C;  // set timer0  C350 = 50,000
    TL0=0xAF;   // posle svakog prekida                   
TR1 = 1; //pokreni tajmer
    
    counter--;  // broj prekide
    if(counter == 0)      // broj 20 prekida za 1 sec kasnjenja     
       {
       update_display = 1; //ovde smo svakih 1 sec
       counter = 20;
}



Staro je pravilo da interapt rutine treba da budu što kraće tj. da imaju što manje instrukcija.

Proveru deljivosti bih prebacio u glavnu petlju. Nema potrebe isključivati tajmer, update_display će imati vrednost "1" svaku put kada istekne sekunda.

Dodao sam i instrukcije za zaustavljanje tajmera 0 pre upisa TH0 i TL0. U nekim (retkim) slučajevima može doći do probelma u radu tajmera ako se on ne zaustavi pre upisa TH0 i TL0.

Za dalje mi nije baš jasno kako ovo treba da radi.

Ne radi ništa dok se ne pritisne taster? Kada se pritisne taster odmah se ispisuje prvi broj u nizu koji je deljiv sa 3, pa se zatim čeka jedna sekunda?
Posle jedne sekunde se ispisuje sledeći? Šta se dešava ako je samo jedan broj u nizu deljiv sa 3? Ili nijedan?
...
...



Re: ATMEL 89C51 zadatak u C 02.12.2015. u 09:19 · pre 132 meseca #16
Pa ne zanam bas da update flag resava stvar

Treba da svake sekunde ispise broj. Tj broj po sekundi.

Nece nista ispisati ako nema broj deljiv sa tri. Sam uslov sa if (!(a%3)) omogucuje.
Nisam nikada radio sa update display

Cuo sam da moze da se napise i bez toga samo nesto treba drugacije napisati..
Ja sam uspeo da sve brojeve koji su deljivi sa 3 ispise za jednu sekundu. Jer ne znam kako da omogucim da jedan broj bude po sekundi.

Profa kaze da treba ispisivanje da bude u prekidnoj rutini. Sto mi je i nekako logicno zbog ispisivanja svake sekunde, da prekid napravi svake sekunde ide na sledeci..
E sad.. Nece nista vise da kaze ;)

Rekao je da nigde ne vracam brojac na nula . E sada gde treba da ga vratim nemam pojma??
Vracam ga sa uslovom if(counter ==0) counter =20 i to je to ... Drugi nacin ne znam
Re: ATMEL 89C51 zadatak u C 02.12.2015. u 10:17 · pre 132 meseca #17
uh bre al ste ga zakomplikovali, ne radi se to tako :( ti ne znas koliko dugo ce ispitivanje trajati, zavisno od velicine ulaza i nacina generacije ulaza moze da potraje..

1. napravis ring bafer (implementiras sa nizom i 2 pointera)
2. dokle god p nije stigao q u glavnoj petlji ispitujes ulazne vrednosti i kada naidjes na ulaz koji odgovara uslovu zadatka (u tvom slucaju deljiv sa tri) dodas ga u ring bafer
3. u interapt rutini, brzinom koja je zadata (1 u sekundi ili 1 u 3 sekunde ili sta ti je vec zadatak postavio), uzimas vrednost iz ring bafera i ispisujes na ekran

obrati paznju da dodavanje u bafer pomera p, vadjenje iz bafera pomera q, dakle p i q se medjusobno jure, kada p sustigne q znaci da nemas mesta vise u ring baferu i tada u glavnoj petlji cekas da ti se oslobodi mesto

jasno? ili da crtam :)
Potpis
arhimed
http://www.mysql.rs/ | http://elco.crsndoo.com/
Re: ATMEL 89C51 zadatak u C 02.12.2015. u 10:30 · pre 132 meseca #18
Jasno mi je skroz sta zelis da kazes ali mi nismo radili sa ring baferom bas nista..
Radili smo samo tajmer 0 i 1 i brojac koji broji ako prevazilazi kapacitet tajmera i to je to. Naravno primeri neki sa ispisivanjem niza ali ne ovakvog kako sada imam, da trazi sekundu za svaki broj. Malo je drugacije
Ostalo je umece iz C :D

Ako si voljan, slobodno crtaj :)))
Treba mi resenje za ispit...
Re: ATMEL 89C51 zadatak u C 02.12.2015. u 10:37 · pre 132 meseca #19
pa sta ako niste radili sa ring baferom, radio si sa nizom, znas da
napravis pointer na element u nizu, to ti je to, samo fancy ime za
drugacije koristenje niza .. to sto ga niste koristili tako ne znaci da
nije upravo ono sto profa ocekuje od vas da skapirate ..

uvek kada imas taj tip problema - gledaj kakav ti bafer treba, da li
hoces neki FIFO kao sto ti sada treba, tu je ring keva (zovu ga i
rolling, circular..) ili ti treba FILO (ili LIFO, ista stvar) gde onda
implementiras nesto kao stek .. na mcu nemas vremena da se igras sa
listama i slicno, uvek je obican niz i samo pitanje da li imas 1, 2 ili
3 pointera na taj niz



da ne bih crtao pogledaj: https://en.wikipedia.org/wiki/Circular_buffer


evo ti primer implementacije (malo duzi zato sto je "generalni primer"
to mozes da iskasapis ihahaj za sebe):
http://c.learncodethehardway.org/book/ex44.html
Potpis
arhimed
http://www.mysql.rs/ | http://elco.crsndoo.com/
Re: ATMEL 89C51 zadatak u C 02.12.2015. u 11:45 · pre 132 meseca #20
Citat:
uvek kada imas taj tip problema - gledaj kakav ti bafer treba, da li
hoces neki FIFO kao sto ti sada treba, tu je ring keva (zovu ga i
rolling, circular..) ili ti treba FILO (ili LIFO, ista stvar) gde onda
implementiras nesto kao stek .. na mcu nemas vremena da se igras sa
listama i slicno, uvek je obican niz i samo pitanje da li imas 1, 2 ili
3 pointera na taj niz


Bogdane, vrlo cenim tvoje misljenje ali mi nije bas najjasnije koja je upotrebna vrednost ring buffera u ovom zadatku. On vec ima staticki niz koji predstavlja fiksan "ulaz".
HeplF2 ima problem sa interapt rutinom. Trebao bi za pocetak da u rutinu stavi samo toggle nekog pin-a i vidi da li ledica blinka na sekundu. Moguce je da postoiji neka igrarija sa interupt flegovima ili sa variablama koje koristi u ISR.
Moguce je da je kompajler u optimizaciji eliminisao neku od varijabli iz rutine. Probaj ih deklarisati kao volatile.
Odgovori
Prijavite se da biste odgovorili u ovoj temi.PrijavaRegistracija

Premeštanje teme