Fórum témák

» Több friss téma
Fórum » MikroPascal kérdések
 
Témaindító: bozsokiandras, idő: Máj 15, 2006
Témakörök:
Lapozás: OK   24 / 29
(#) progee hozzászólása Nov 21, 2013 /
 
Valaki meg tudná mondani, hogy a timer1 időzítőt hogyan kell helyesen használni?
Hiába próbálom a leírások alapján, nem akar sikerülni a t1 változó számlálása.

  1. procedure Interrupt;
  2. begin
  3.   if PIR1.TMR1IF = 1 then
  4.   begin
  5.     inc(t1);
  6.     PIR1.TMR1IF := 0;
  7.   end;
  8. end;
  9.  
  10.  
  11. begin
  12.   T1CON.T1CKPS1  := 0;  
  13.   T1CON.T1CKPS0  := 0;  
  14.   T1CON.T1OSCEN  := 1;  
  15.   T1CON.SYNC_bit := 1;  
  16.   T1CON.TMR1CS   := 0;  
  17.   T1CON.TMR1ON   := 1;  
  18.   INTCON.PEIE    := 1;  
  19.   INTCON.GIE     := 1;    
  20.   PIE1.TMR1IE    := 1;
  21.   PIR1.TMR1IF    := 0;
  22.  
  23. ...
  24.  
  25. end.
(#) progee válasza progee hozzászólására (») Nov 22, 2013 /
 
Sikerült megoldanom. Így működik:
  1. T1CON.TMR1CS   := 0;  
  2.   T1CON.T1CKPS1  := 0;  
  3.   T1CON.T1CKPS0  := 0;
  4.   T1CON.TMR1ON   := 1;  
  5.   TMR1H          := 0;  
  6.   TMR1L          := 0;
  7.   INTCON.GIE     := 1;
A hozzászólás módosítva: Nov 22, 2013
(#) progee válasza progee hozzászólására (») Nov 22, 2013 /
 
Timer0 osztásával van viszont további problémám. Hiába állítom 0-ról 1-re a ps2, ps1, ps0 értékeit, az intrerruptban lévő számláló értéke ugyanolyan sebességgel növekszik. Mi hiányzik még a kódból?

  1. procedure Interrupt;
  2. begin
  3.   if INTCON.T0IF = 1 then
  4.   begin
  5.     inc(t0);
  6.     INTCON.T0IF:= 0;
  7.     TMR0 := 0;      
  8.   end;
  9. end;
  10.  
  11.   OPTION_REG.T0CS := 0;    
  12.   OPTION_REG.T0SE := 0;  
  13.   OPTION_REG.PSA  := 0;  
  14.   OPTION_REG.PS2  := 1;
  15.   OPTION_REG.PS1  := 1;
  16.   OPTION_REG.PS0  := 1;
  17.   TMR0            := 0;    
  18.   INTCON.T0IE     := 1;    
  19.   INTCON.GIE      := 1;
(#) robing16 hozzászólása Dec 1, 2013 /
 
Sziasztok!

Egy kis segítséget szeretnék kérni, mert nem értem az I2C folyamatát egy PIC 16F887 -ben.

A célom az lenne, hogy egy Raspberry PI -t I2C master-ként, folyamatosan lekérdezek értékeket egy PIC16F887 -es IC-ről. Találtam egy MicroC -ben megírt példaprogramot, amit átírtam MikroPascal nyelvre.

Jelenleg most úgy működik, hogy ha az eszközre írok egy adatot, azt a PORTB -re kirakja. Ha beolvasok adatokat, akkor meg a programban megadott 234-es értéket kellene vissza kapnom! Ez így működik is, csak annyi a szépséghibája, hogy olvasásnál a regiszter címzést a PORTB-re íratja ki.

Raspberry kódok:
bus.read_byte_data(DEVICE,0x00) // Olvasom az adott eszközről a 0x00 -ás regiszterben lévő adatot
bus.write_byte_data(DEVICE,0x00,0x20) // Írok a 0x00 regiszterbe 0x20 -as értéket
A DEVICE változó a 0x34, amit a definiáláskor megadtam.

A Raspberryben a fent leírt két módon szoktam adatot olvasni és írni. Hasonló megoldást szeretnék eléni, mint pl. az MCP23017 -es IC-nek van.

Azt szeretném elérni, hogy ha mondjuk a PIC 0x20 -as címére ráírok egy bármilyen értéket, akkor a PORTB -n jelenjen meg. Ha 0x30 -as címére írok rá, az meg a PORTD-re kerüljön ki.

Ugyan így olvasásnál. 0x20 -nál a PORTB értékét tudjam beolvasni, 0x30-nál pedig a PORTD értékét.

Természetesen lenne még két regiszter, ahol a portok olvasását/írását tudnám beállítani, de ezzel elbűvészkedek én is

Az lenne a kérdés, hogy a megszakításnál hol, milyen módon és mit kell összehasonlítani, hogy a fent említett megoldás megszülessen?

A válaszokat előre is köszönöm

  1. program I2C_Slave;
  2.  
  3. { Declarations section }
  4.  
  5. // Valtozok definialasa
  6. var tx_data   : byte;
  7. var rxbuffer  : byte;
  8. var j         : byte;
  9.  
  10. // Allando valtozok definialasa
  11. const Addy = 0x69;                    // Megadjuk az eszkoz cimet
  12. const Delay_Time = 250;               // Portfigyeles kozotti ido
  13.  
  14. Procedure Setup;
  15.  begin
  16.   ADCON1 := 0;                          // All ports set to digital
  17.   TRISA := 0;  PORTA := 0;              // Set PORTA as output
  18.   TRISB := 0;  PORTB := 0;              // Set PORTB as output
  19.   TRISD := 0;  PORTD := 0;
  20.  
  21.   PORTD.0 := 1; PORTD.1 := 1;
  22.   delay_ms(1300);
  23.   PORTD.0 := 0;
  24.   delay_ms(600);
  25.   PORTD.1 := 0;
  26.   delay_ms(400);
  27.   TRISC := 0xFF;                        // PORTC-t inputra allitjuk
  28.   SSPADD :=  Addy;                      // Beallitjuk az eszkoz cimet
  29.   SSPCON := 0x36;                       // Beallitjuk az I2C Slave modot
  30.   PIE1.SSPIF := 1;                      // Engedelyezzuk az SSPIF megszakitasvezerlot
  31.   INTCON := 0xC0;                       // Engedelyezzuk a globalis megszakitasvezerlot
  32.  end;
  33.  
  34. Procedure Interrupt;
  35.  begin
  36.  if PIR1.SSPIF = 1 then
  37.   begin
  38.   PIR1.SSPIF := 0;                       // Vissza állítjuk az Interrupt FLAG-et.
  39.  
  40.  if SSPSTAT.R_W = 1 then               // 1 - READ olvasási BIT-et kaptunk
  41.    begin
  42.  
  43.    SSPBUF := 234;                      // tx_data;
  44.    SSPCON.CKP := 1;                    // Órajel levágás, Master felé nyuktázva
  45.    j := SSPBUF;
  46.    exit;
  47.    end;
  48.  
  49.   if SSPSTAT.BF = 0 then                 // Tároló televan, vagy üres. 0 = üres 1 = FULL
  50.    begin
  51.    j := SSPBUF;
  52.    exit;
  53.    end;
  54.  
  55.   if SSPSTAT.D_A = 1 then                // Data / Address -> 1 Data, 0 Address
  56.    begin
  57.    rxbuffer := SSPBUF;
  58.    j := SSPBUF;
  59.    exit;
  60.    end;
  61.  
  62.   j := SSPBUF;
  63.   end;
  64.  
  65.  end;
  66.  
  67.  
  68.  
  69. begin
  70.  Setup;
  71.   while true do
  72.    begin
  73.     PORTB   := rxbuffer;
  74.     tx_data := PORTC;
  75.     Delay_ms(Delay_Time);
  76.    end;
  77. end.
A hozzászólás módosítva: Dec 1, 2013
(#) progee válasza progee hozzászólására (») Dec 3, 2013 /
 
senkinek semmi ötlete a timerrel kapcsolatban?
(#) gthomas válasza robing16 hozzászólására (») Dec 3, 2013 /
 
Szia, pont most botlottam bele:

Gert van Loo wrote:
If you have a choice then don't use I2C for the connection as the Pi has a bug in its I2C interface.

Topic

A serial nem jó?
(#) robing16 válasza progee hozzászólására (») Dec 3, 2013 /
 
Szia!

Picit elvesztettem a fonalat, mivel először egy relé működtetéséről beszéltél, utána jött a Timer1, majd később a Timer0... Most akkor miről is van szó?

Ha Timer0 ban elakadok, először mindig a példaprogramot veszem elő!

A te kódodban nem látom a következő sor egyik részét
INTCON := 0x20; // Set T0IE, clear T0IF
Itt azt írják helyesen, hogy a T0IE -t 1-re húzzák, amivel vissza állítják a túlcsordulást engedélyező bitet, (Bár nem tudom, hogy egyáltalán ez a Bit túlcsordulásnál megváltozik-e) majd a T0IF -et viszont 0-ra húzzák, hogy a túlcsordulási zászló alaphelyzetbe álljon.

A példaprogramban még egy osztó is található a fő program részben, ahol még egy számláló segít a lassításban. Ennyi ötletem lett hirtelen

  1. program Timer0_Interrupt;
  2. var counter : word;
  3.  
  4. procedure Interrupt();
  5.   begin
  6.     Inc(counter);             // Increment value of counter on every interrupt
  7.     TMR0   := 96;
  8.     INTCON := 0x20;           // Set T0IE, clear T0IF
  9.   end;
  10.  
  11. begin
  12.   OPTION_REG := 0x84;       // Assign prescaler to TMR0
  13.   ANSEL  := 0;              // Configure AN pins as digital I/O
  14.   ANSELH := 0;
  15.   TRISB := 0;               // PORTB is output
  16.   PORTB := 0xFF;            // Initialize PORTB
  17.   TMR0  := 96;              // Timer0 initial value
  18.   INTCON := 0xA0;           // Enable TMRO interrupt
  19.   counter := 0;             // Initialize counter
  20.  
  21.   while TRUE do
  22.     begin
  23.       if (counter = 400) then
  24.         begin
  25.           PORTB := not PORTB;       // Toggle PORTB LEDs
  26.           counter := 0;             // Reset counter
  27.         end;
  28.     end;
  29. end.
(#) robing16 válasza gthomas hozzászólására (») Dec 3, 2013 /
 
Szia!

Furcsa, hogy ezt írják, hisz eddig nem nagyon találkoztam I2C hibával. Nagyon sokáig teszteltem egy másik projektemben az MCP23017 -es IC-t, remekül működik a mai napig.

Az én esetemben most reléket kellene rákötni egy 16F887-es IC-re, amit I2C -n keresztül vezérelve ki-be kapcsolgatok, és ez mellett 3db DS18B20 -as hőmérséklet IC-t is hozzá kellene csatolnom az IC-hez.

A példaprogramból amúgy addig jutottam, hogy a megszakítást a SSPBUF telítettségi értéke indítja el a megszakítást, és a megszakítás eléggé gyorsan lefut. Tehát elméletileg, ha megjön az első érték, ami írásnál, vagy olvasásnál a regiszter címet mondja meg, azt kellene először összehasonlítanom az előre definiált értékkel, majd a következő megszakításnál egy, a regiszter címhez írt rutint kellene végrehajtania?

Vagy esetleg, ha bejön mind a két adat (írásnál a regiszter és az adat), akkor utána kell valami feltételben definiálni?

És akkor itt a másik kérdés, hogy az eszköz ID-ját ki, vagy mi ellenőrzi? A sotfvware, vagy a hardware? Hisz a program legelején SSPADD := Addy; beadjuk az address-t és pont.
(#) progee válasza robing16 hozzászólására (») Dec 4, 2013 /
 
Valójában az összes időzítővel szenvedek valamilyen hibával.
Maradjunk a timer0-nál egyenlőre.

A INTCON := 0x20; szerintem azért felesleges az interrupt-ba, mert a INTCON.T0IF:= 0; nullára állítja a T0IF bitet, a T0IE bit értéke pedig az inicializáláskor már 1-re lett állítva.
A counter változó számlálásával valóban lehetséges a késleltetés, viszont szeretném megérteni a timer teljes működését, amiben az OPTION_REG.PSA PS2..PS0 bitekkel lehetne megoldani a problémát. És ezt nem sikerül működésre bírnom.
(#) gozi válasza progee hozzászólására (») Dec 4, 2013 /
 
Próbáld ki az alábbi programot, és hasonlítsd össze a kapott eredményt a saját programkódoddal:
http://www.libstock.com/projects/view/398/timer-calculator
(#) Ktulu válasza progee hozzászólására (») Dec 4, 2013 /
 
Szia.
Ezzel a minimális kiegészítéssel próbáltam, és jól működik. (Proteus szimulátor PIC16F877A)
Mindent úgy állítottál be, ahogy kell.

  1. program MyProject;
  2.  
  3.  var t0:byte;
  4.  
  5.       procedure Interrupt;
  6.       begin
  7.         if INTCON.T0IF = 1 then
  8.         begin
  9.           inc(t0);
  10.           INTCON.T0IF:= 0;
  11.           TMR0 := 0;
  12.           PortB.1:=not(PortB.1);
  13.         end;
  14.       end;
  15.  
  16. begin
  17.         OPTION_REG.T0CS := 0;
  18.         OPTION_REG.T0SE := 0;
  19.         OPTION_REG.PSA  := 0;
  20.         OPTION_REG.PS2  := 0;
  21.         OPTION_REG.PS1  := 0;
  22.         OPTION_REG.PS0  := 0;
  23.         TMR0            := 0;
  24.         INTCON.T0IE     := 1;
  25.         INTCON.GIE      := 1;
  26.         CMCON := 7;
  27.         TrisB:=0;
  28.         PortB:=0;
  29. end.
A hozzászólás módosítva: Dec 4, 2013
(#) progee válasza Ktulu hozzászólására (») Dec 4, 2013 /
 
Köszönöm mindenkinek a segítséget!
Úgy gondolom, hogy három hibát vétettem egyszerre.
- Az első, hogy az option_reg és intcon regisztereknek nem minden bitjét állítottam be, így alapértelmezetten azok 1-es értéket vettek fel.
- A második, hogy az interrupt-ban számlált változó értékét a PORTB lábakra kötött LCD-n írattam ki, így ez bezavarhatott a portok megszakítás engedélyezésébe.
- A harmadik hiba, hogy változóból próbáltam átadni inicializáláskor a PSA, PS2, PS1, PS0 értékeit, és a változóknak ugyanezeket a neveket adtam. Míg procedure-ban deklaráltam ezeket a változókat, addig nem is panaszkodott a fordító, csak amikor globális változók közzé helyeztem át őket.
Én nem szeretem hexa értékkel beállítani a regisztereket, mert akkor nem látom a forrásban világosan, hogy mely bitek hogyan is állnak.
Így készítettem el az inicializáló részt, ami végre működik sebességosztással is:
  1. procedure timer0_init(oszto: word);
  2. var t0_psa, t0_ps0, t0_ps1, t0_ps2: byte;
  3. begin
  4.   case oszto of
  5.     1:   begin t0_psa:= 1; t0_ps2:= 0; t0_ps1:= 0; t0_ps0:= 0; end;
  6.     2:   begin t0_psa:= 0; t0_ps2:= 0; t0_ps1:= 0; t0_ps0:= 0; end;
  7.     4:   begin t0_psa:= 0; t0_ps2:= 0; t0_ps1:= 0; t0_ps0:= 1; end;
  8.     8:   begin t0_psa:= 0; t0_ps2:= 0; t0_ps1:= 1; t0_ps0:= 0; end;
  9.     16:  begin t0_psa:= 0; t0_ps2:= 0; t0_ps1:= 1; t0_ps0:= 1; end;
  10.     32:  begin t0_psa:= 0; t0_ps2:= 1; t0_ps1:= 0; t0_ps0:= 0; end;
  11.     64:  begin t0_psa:= 0; t0_ps2:= 1; t0_ps1:= 0; t0_ps0:= 1; end;
  12.     128: begin t0_psa:= 0; t0_ps2:= 1; t0_ps1:= 1; t0_ps0:= 0; end;
  13.     256: begin t0_psa:= 0; t0_ps2:= 1; t0_ps1:= 1; t0_ps0:= 1; end;
  14.   end;
  15.  
  16.   TMR0               := 0;       //Timer0 számláló nullázása
  17.  
  18.   OPTION_REG.RBIE    := 0;       //PortB megszakítás engedélyezése / tiltása
  19.   OPTION_REG.INTEDG  := 0;       //RB0 INT megszakítás engedélyezése / tiltása
  20.   OPTION_REG.T0CS    := 0;       //Óra választás:   1 - Külső időzítő az RA4 lábon   0 - Belső ciklus óra
  21.   OPTION_REG.T0SE    := 0;       //RA4/TOCKI  Alacsony és magas átmenet közötti váltás, ha külső számlálót használunk: 0=low/high (pozitív impulzusok) / 1=high/low (negatív impulzusok)
  22.   OPTION_REG.PSA     := t0_psa;  //Időzítő kapcsoló:  1 - WDT-n keresztül    0 - PS0, PS1, PS2 figyelembevétele késleltetéshez
  23.   OPTION_REG.PS2     := t0_ps2;  //Sebesség osztó beállítások (PS2, PS1, PS0)
  24.   OPTION_REG.PS1     := t0_ps1;
  25.   OPTION_REG.PS0     := t0_ps0;
  26.  
  27.   INTCON.GIE         := 1;       //Globális megszakítás engedélyezése
  28.   INTCON.PEIE        := 0;       //Perifériás megszakítások engedélyezése / tiltása (PortB, RB0/Int)
  29.   INTCON.T0IE        := 1;       //Timer0 engedélyezése
  30.   INTCON.INTE        := 0;       //RB0 INT Sleep felébresztés engedélyezése / tiltása
  31.   INTCON.RBIE        := 0;       //PortB állapotváltozása miatti megszakítás engedélyezése / tiltása
  32.   INTCON.T0IF        := 0;       //TMR0 túlcsordulásának állapota (0- nem csordult túl, 1- Túlcsordult)
  33.   INTCON.INTF        := 0;       //RB0/Int port megszakítás állapota (0- nem történt megszakítás, 1- megszalítás történt)
  34.   INTCON.RBIF        := 0;       //PortB állapotváltozása miatti megszakítás állapota (0- nem történt megszakítás, 1- megszalítás történt)
  35. end;


A kommentekben remélem nem írtam nagy hülyeségeket. Próbáltam magyarul megfogalmazni, melyik bit mire is jó.
A hozzászólás módosítva: Dec 4, 2013
(#) robing16 válasza progee hozzászólására (») Dec 4, 2013 /
 
Szia! A Counter tényleg nem szükséges, ellenben, mikor a timer -eket nézegettem, nem volt oszcilloszkópom, és váltig állítottam, hogy a 20MHz-es kvarc remek lesz Igen, akkor, ha komolyabb munkába akarok fogni. Nálam akkor a LED counter nélkül világított, illetve vibrált. Akkor én is próbálgattam az osztókat

Mégvalami! Nekem nagyon tetszett az, mikor a goolge-ban rákerestem egy Timer kalkulátorra. Ott ha jól emlékszek, beadom, hogy milyen kvarc-om van, és hogy mit szeretnék vissza kapni, és a kis webes program kidobta a beállításokat

PIC Timer Calculator

Közben látom, hogy gozi is belinkelt egy kalkulátoros linket
A hozzászólás módosítva: Dec 4, 2013
(#) progee válasza robing16 hozzászólására (») Dec 5, 2013 /
 
Igen ismerem a programot.
Hiányolom belőle a regiszterek összes bitjének beállítását.
Próbáltam a segítségével órát készíteni egy 16F628A PIC-re. 4Mhz-es belső oszcillátorral.
A program által megadott beállításokkal 1ms-os megszakításokat kellett volna kapnom 1:4 osztó (PSA := 1 mellett) és TMR0 := 6 beállításával.
Sajnos nagyon pontatlan lett a végeredménye.
Ha a TMR0-át 60-ra állítom akkor már közelít a valósághoz, de abban az esetben is 10 percen belül 3mp-es késéssel működik. Az interrupt részben így számolom az időt:
  1. var o, p, mp: byte;
  2. var ms: word;    
  3.  
  4. procedure Interrupt;  
  5. begin
  6.   if INTCON.T0IF = 1 then
  7.   begin
  8.     TMR0 := 60;    
  9.     INTCON.T0IF:= 0;
  10.     inc(ms);
  11.     if ms = 1000 then
  12.     begin
  13.       inc(mp);
  14.       ms := 0;
  15.       if mp = 60 then
  16.       begin
  17.         inc(p);
  18.         mp := 0;
  19.         if p = 60 then
  20.         begin
  21.           inc(o);
  22.           p := 0;
  23.         end;
  24.       end;
  25.     end;
  26.   end;
  27. end;


Nem tudom, hogy az oszcillátor ennyire pontatlan, vagy a kódban van-e hiba.
A hozzászólás módosítva: Dec 5, 2013
(#) gthomas válasza robing16 hozzászólására (») Dec 6, 2013 /
 
Szia!
Linux oldalon miben programozol? Csak érdeklődés képen, mert nekem is itt van az asztalomon egy PI, ha lenne időm én is foglalkoznék vele egy kicsit. Nekem egy Lazarus van rajta egyenlőre.
(#) Hp41C válasza progee hozzászólására (») Dec 6, 2013 /
 
Ha mindenárom timer0 -val szeretnéd megoldani: Bővebben: Link
Timer2 -vel egyszerűen lehet 4MHz -es órajelből 1ms, 10ms -os periódikus megszakításkérst előállítani.
(#) progee válasza Hp41C hozzászólására (») Dec 6, 2013 /
 
Timer2-t hogyan kell paraméterezni egy pontos órához?
Timer0-val hiába próbálkozok, csak közelítőleg pontos időt kapok vissza.
Proteusban tesztelem a kapcsolást, így a PIC kristály pontatlanságát kizárom mint hibalehetőséget.
Azt tapasztalom, hogy az LCD-re kiíratott idő, mintha néha, kb 3-4 mp-ként később váltaná a mp-et.
Az interrupt-ot szinte teljesen kiürítettem, csak egy számláló, meg a működéséhez szükséges TOIF és TMR0 beállítások vannak benne.
(#) Hp41C válasza progee hozzászólására (») Dec 6, 2013 /
 
16F628 4MHz órajellel 1us -el lépteti a timereit. A Timer2 1:1, 1:4, 1:16 előosztóval, egy 8 bites programozható osztóval (RR2) és egy 1:1 .. 1:15 utóosztóval rendelkezik. 1ms előállításához a timer2 -nek 1000 -rel kell osztania: 1:4 előosztó, 250 -es programozható osztó és 1:1 utóosztó.
PR2 = 249; T2CON = 5;
A megszakítás kéréséhez PIE1 regiszter TMR2IE bitjét 1 -re, INTCON PEIE bitjét 1 -re, és az INTCON GIE bitjét is 1 -re kell állítani.
(#) progee válasza Hp41C hozzászólására (») Dec 6, 2013 /
 
Így írtam meg a program időzítő részét, de 15másodpercen belül 2 másodpercet késik. Proteus-ban tesztelem a kódot. A begin..End között van még pár sor kód (nyomógombok állapot lekérdezése), de annak az időzítést tudtommal nem kellene zavarnia.
  1. procedure Interrupt;  
  2. begin
  3.  if PIR1.TMR2IF = 1 then
  4.   begin
  5.     inc(t2);
  6.     TMR2  := 0;        //Kezdőértékek
  7.     PR2   := 249;
  8.     PIR1.TMR2IF := 0;
  9.   end;
  10. end;
  11.  
  12.  
  13. Begin
  14.   TMR2   := 0;
  15.   PR2    := 249;
  16.   T2CON  := %00000101 //prescale 1:4
  17.   PIE1   := %00000010 //TMR2IE
  18.   INTCON := %11000000 //GIE, PEIE
  19.  
  20.  
  21.   while true do
  22.   begin
  23.     if t2 >= 1000 then //1mp
  24.     begin
  25.       t2 := 0;
  26.       inc(mp);        
  27.  
  28.       KIIR_IDO;        //LCD_OUT    
  29.  
  30.       if mp = 60 then  //1perc
  31.       begin
  32.         inc(p);
  33.         mp := 0;
  34.         if p = 60 then //1óra
  35.         begin
  36.           inc(o);
  37.           p := 0;
  38.         end;
  39.       end;
  40.     end;
  41. end.
(#) progee válasza progee hozzászólására (») Dec 6, 2013 /
 
Ez egyre jobb!
Ugyanazt a hex fájlt ha futtatom a proteusban ill, kiírom a fizikai pic-re, akkor más-más sebességgel dolgozik. A proteus szimulációban késik, a gyakorlatban pedig egy keveset siet.
A hozzászólás módosítva: Dec 6, 2013
(#) Hp41C válasza progee hozzászólására (») Dec 6, 2013 /
 
A TMR2 -t nem kell írni, a hardware törli... A megszakításban a PR2 írása is felesleges, a beállított érték megmarad benne.
A hozzászólás módosítva: Dec 6, 2013
(#) progee válasza Hp41C hozzászólására (») Dec 6, 2013 /
 
Most kiírva hardwarre 2 mp-et siet 1 percen belül.
A hozzászólás módosítva: Dec 6, 2013
(#) robing16 válasza progee hozzászólására (») Dec 6, 2013 /
 
Szia!

Tapasztalatból mondom, hogy nagyon nehéz egy önálló PIC-el úgy órát készíteni (mondjuk nem csak az órát számolgatja, hanem egyéb más program részek is vannak), hogy az tényleg patentosan pontos legyen!

Én, ha órát fogok használni, a következő két módszert használnám! (BEVÁLT MÓDSZER).
RTC -- link

A DS1307 -es IC-nek konkrétan egyetlen egy feladata van, méghozzá a beállított idő tartása és rendkívül pontos számlálása. Ez az IC egy 32.768kHz - es kvarc -al működik, áramszünet esetén a ráköthető 3V -os (alaplapi elem PL: 2032) tartja, és működteti a számlálót. Ha jól emlékszek, akkor I2C buszon keresztül két vezetékkel könnyen kiolvasható a Regiszter táblákból a pontos idő értékei.

Ha mégis számlálósat szeretnél készíteni, akkor is javaslom, hogy legyen ott ez az IC, ugyanis képes 1s -os impulzusokat kiadni az SQW/OUT lábán. Ebben az esetben csak a megszakítás vezérlő bemenetre kell rákötnöd, és a programban megszakításkor a szmáláót kell növelned. Alaphelyzetben I2C buszon keresztül kell beállítani a pontos időt, majd a belső timer-ét elindítani, és amíg más parancsot nem kap, vagy nem merül le az elem, a pontos időt tartani fogja.

Csak egy ötlet
A hozzászólás módosítva: Dec 6, 2013
(#) robing16 válasza gthomas hozzászólására (») Dec 6, 2013 /
 
Szia!

Raspberry-n nekem a Python programozási nyelv fogott meg, főleg azért, mert sok olyan modulja is van, amit nem kell előre megírni.

OS-nek Raspbian -t raktam fel. Engem nagyon megfogott az I2C kommunikációs busz, és a fentebb leírt módon egy PIC16F887 -el szeretném összekötni.
(#) progee válasza robing16 hozzászólására (») Dec 7, 2013 /
 
Utánaolvastam rengeteg fórumon, és mindenhol a belső oszcillátor pontatlanságát írják.
A proteusz és a valóságban mért időeltérések oka pedig, valószínűleg a PIC hőmérsékletének betudható plusz ingadozás volt.
Próbálom a költségeket alacsonyan tartani, így 32.768KHz-es külső kvarcra próbáltam tesztet készíteni. Mivel itthon nincs ilyenem, így egyenlőre proteusban tesztelem.
Ebben is sikerült zátonyra futnom. Rengeteg kitartás kell a mikrokontrollerhez
Az alábbi módon inicializáltam a timer1-et:

  1. procedure Interrupt;
  2. begin
  3.   if PIR1.TMR1IF = 1 then
  4.   begin
  5.     inc(t1);
  6.     PIR1.TMR1IF := 0;
  7.   end;
  8. end;
  9.  
  10. begin
  11.  
  12.   COMPARATOR_OFF;
  13.  
  14.   T1CON.T1OSCEN  := 1; //Külső oszcillátor
  15.   T1CON.SYNC     := 1; //Nincs szinkronizáció
  16.   T1CON.TMR1CS   := 1; //Külső időzítő T1CKI lábon (RB6-RB7)
  17.   T1CON.TMR1ON   := 1; //Timer1 start
  18.   PIE1.TMR1IE    := 1; //Timer1 megszakítás engedélyezése
  19.   INTCON.GIE     := 1; //Globális megszakítás engedélyezése
  20.   INTCON.PEIE    := 1; //Perifériás megszakítások engedélyezése
  21.  
  22.   while true do
  23.   begin
  24.     if t1 >= 1000 then
  25.     begin
  26.       t1 := 0;
  27.       inc(mp);
  28.      
  29.       if mp >= 60 then
  30.       begin
  31.         inc(p);
  32.         mp := 0;
  33.         if p >= 60 then
  34.         begin
  35.           if o > 23 then o := 0 else inc(o);
  36.           p := 0;
  37.         end;
  38.       end;
  39.      
  40.       KIIR_IDO;  //LCD
  41.     end;
  42.   end;
  43.  
  44. end.


A regiszterek többi bitjét nullára állítottam.
Ennek a kódnak a belső 4MHz-es órára igazított beállításaival tudja számolni az időt, csak ugye pontatlan.
Ezzel a beállítással viszont meg sem moccannak a számok. Mintha az interrupt le sem futna.
Mielőtt kitépném az összes hajamat, valaki tudna adni tippet, mit hagytam figyelmen kívül?
Csatoltam a tesztáramkör rajzát.
A hozzászólás módosítva: Dec 7, 2013

32khz.jpg
    
(#) progee válasza progee hozzászólására (») Dec 8, 2013 /
 
Annyival jutottam közelebb a megoldáshoz, hogy a OPTION_REG.NOT_RBPU := 0; bit-el sikerült engedélyeztetnem a PortB megszakításokat, és így a T1CKI lábra kötött nyomógombbal sikerült külső impulzussal számoltatnom a timer1 interruptot.
Sajnos kvarccal továbbra sem csinál semmit.
A hozzászólás módosítva: Dec 8, 2013
(#) Ktulu válasza progee hozzászólására (») Dec 8, 2013 /
 
Nem vagyok teljesen meggyőződve róla, hogy a Proteus képes külső oszcillátort szimulálni.
Nagyon javaslom, hogy inkább a valóságban próbáld ki.
Óra kvarcot találsz bármilyen ócska vacak kínai órában, (pl. csipogós ébresztős) karórában stb.
Bővebben: Link
(#) progee válasza Ktulu hozzászólására (») Dec 8, 2013 /
 
Sajnos úgy sem jó.
Van valakinek erre biztosan működő példa programja pascalban?
(#) progee válasza progee hozzászólására (») Dec 9, 2013 /
 
Csináltam egy teljesen lebutított demot. Csatoltam a pascal kódot és a proteus szimulációs fájlt.
Tudná valaki tesztelni? Ha a T1CON.TMR1CS-t nullára állítom, akkor a belső óráról működik a timer1 számlálás, ha 1-re állítom, akkor nem megy külső kvarcról. Mi hiányozhat még belőle?
  1. program timer_teszt;
  2.    
  3. var LCD_RS : sbit  at RB4_bit;
  4. var LCD_EN : sbit  at RB5_bit;
  5. var LCD_D4 : sbit  at RB0_bit;
  6. var LCD_D5 : sbit  at RB1_bit;
  7. var LCD_D6 : sbit  at RB2_bit;
  8. var LCD_D7 : sbit  at RB3_bit;
  9.  
  10. var LCD_RS_Direction : sbit at TRISB4_bit;
  11. var LCD_EN_Direction : sbit at TRISB5_bit;
  12. var LCD_D4_Direction : sbit at TRISB0_bit;
  13. var LCD_D5_Direction : sbit at TRISB1_bit;
  14. var LCD_D6_Direction : sbit at TRISB2_bit;
  15. var LCD_D7_Direction : sbit at TRISB3_bit;
  16.  
  17. var t1: integer;
  18.     s: string[10];
  19.  
  20. procedure Interrupt;
  21. begin
  22.   if PIR1.TMR1IF = 1 then
  23.   begin
  24.     inc(t1);
  25.     TMR1H       := 0;      
  26.     TMR1L       := 0;
  27.     PIR1.TMR1IF := 0;
  28.   end;
  29. end;
  30.  
  31. procedure timer1_init;
  32. begin
  33.   TMR1H          := 0;      
  34.   TMR1L          := 0;
  35.   t1             := 0;
  36.  
  37. //  OPTION_REG.NOT_RBPU := 0;    
  38.  
  39.   T1CON.T1CKPS1     := 0;      
  40.   T1CON.T1CKPS0     := 0;
  41.   T1CON.T1OSCEN     := 1;      
  42.   T1CON.NOT_T1SYNC  := 1;      
  43.   T1CON.TMR1CS      := 1;      
  44.   T1CON.TMR1ON      := 1;      
  45.  
  46.   PIR1.EEIF         := 0;      
  47.   PIR1.CMIF         := 0;      
  48.   PIR1.RCIF         := 0;    
  49.   PIR1.TXIF         := 0;      
  50.   PIR1.CCP1IF       := 0;      
  51.   PIR1.TMR2IF       := 0;    
  52.   PIR1.TMR1IF       := 0;    
  53.  
  54.   PIE1.EEIE         := 0;      
  55.   PIE1.CMIE         := 0;      
  56.   PIE1.RCIE         := 0;    
  57.   PIE1.TXIE         := 0;    
  58.   PIE1.CCP1IE       := 0;      
  59.   PIE1.TMR2IE       := 0;      
  60.   PIE1.TMR1IE       := 1;      
  61.  
  62.   INTCON.GIE        := 1;      
  63.   INTCON.PEIE       := 1;      
  64.   INTCON.T0IE       := 0;      
  65.   INTCON.INTE       := 0;      
  66.   INTCON.RBIE       := 0;      
  67.   INTCON.T0IF       := 0;      
  68.   INTCON.INTF       := 0;      
  69.   INTCON.RBIF       := 0;      
  70. end;
  71.  
  72. begin
  73.   CMCON := %00000111;
  74.  
  75.   Lcd_Init();
  76.   delay_ms(100);
  77.   Lcd_Cmd(_LCD_CURSOR_OFF);
  78.   Lcd_Out(1, 1, 'T1:');
  79.  
  80.   Timer1_init;
  81.   delay_ms(100);
  82.  
  83.   while true do
  84.   begin
  85.     bytetostr(t1, s); ltrim(s);
  86.     Lcd_Out(1, 7, s);
  87.   end;
  88. end.
A hozzászólás módosítva: Dec 9, 2013
(#) progee válasza progee hozzászólására (») Dec 9, 2013 /
 
Csatoltam a kapcsolási rajz képét is...
Következő: »»   24 / 29
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem