Fórum témák

» Több friss téma
Fórum
Keresés
Lapozás: OK   1 / 41
(#) KoblogPerGyok válasza kisgy hozzászólására (») Jún 13, 2024
Szia!

Még dolgozok rajta, nincs kész, de már vannak fejlemények. Sajnos nem tudtam foglalkozni vele az elmúlt napokban, de ma már haladtam is vele. Még a fő logika hiányzik, minden egyéb kész. Megpróbálom darabokra szedni a logikát is, hogy minél könnyebben átlátható legyen az is. Pár függvényt már kiszerveztem .c és .h fájlokba is, mint például a timer1, PWM, és a PIN_setup-ot is. Ezek jól működnek, így a fő programban csak meg kell hívni őket 1x, ezáltal a fő program sokkal átláthatóbb lesz szerintem.

Jelentkezem mihamarabb, és bocs a késlekedésért!
(#) kisgy válasza KoblogPerGyok hozzászólására (») Jún 9, 2024
Üdv!

Gépkocsimba szeretnék belső világítás vezérlést kreálni.
Az eredei kódot nem én írtam, itt az oldalon találtam egy hasonlót amit mintaként szerettem volna némi átalakítással felhasználni.
Az eredetit potyo készítette 2008-ban. Itt a linkben megtalálod. A 3. oldalon leírja miért ilyen a kód, az 5. oldalon fent van a hex. és c. is.
Ő úgy oldotta meg, hogy nem használ interruptot.
Én csak egy táki-máki ember vagyok, aki "talán" sejti hogy hogyan is kell ilyet csinálni.
Azért csak a kód első részletét raktam fel, mert a delay és a pwm is benne van.
A pwm megy, a számláló viszont sem timer2 vel, sem timer1-el nem működik.

Idézet:

Ez miért ilyen?
#define HA_IDO ((HALV_IDO/255)*255-1)

Nem tudom miért ilyen, de ez működik.


Nem tudom, hogy ennek pl működnie kellene, de ez sem működik és nem értem miért:
  1. if (bv_ajto == 0)              // ha kinyílt az ajtó
  2.            {
  3.               PORTC.RC5 = 1;                   // bekapcsol a led
  4.               szamlalo= 3000;                  // késleltet
  5.               PORTC.RC5 = 0;                   // kikapcsol
  6.             }


Idézet:

De a témafelvető nem reagál, már kezdtem azt hinni lesz egy kis programozási feladat.


Ha gondolod leírom miről is szólna ez az egész, de gondoltam kilogikázom én, bár jelenleg úgy látszik túlnő rajtam
(#) KoblogPerGyok válasza Hp41C hozzászólására (») Jún 9, 2024
Én azt hittem, hogy timer2-nek nincs átfordulásra interrupt.

TMR2IF: Timer2 to PR2 Match Interrupt Flag bit
1 = Timer2 to PR2 match occurred (must be cleared in software)
0 = Timer2 to PR2 match has not occurred

A Timer2-nek van overflow interruptja? Nem csak egyezésre? Az adatlapot nem néztem olyan mélyen át, nekem úgy tűnt, hogy ennél a típusnál nincs a timer2-nek, a timer1-nek és a timer0-nak van. Ezért írtam hogy más, mint amivel találkoztam eddig. A PR2-vel való egyezésre ad interuptot, ha jól értem. (most lehet keverem, mert épp Arduino timer1 ComparA, ComparB, és overflow interrupt van a fejemben)

A kódot felületesen olvasva egyik interrupt sincs engedélyezve, nincs erre függvény felhúzva, ebben az esetben lesz egyezés? Mikor?

Idézet:

2. #define HA_IDO ((HALV_IDO/255)*255-1) kérdése.
A műveleteket a fordítók a saját alapbeállításuk szerinti típussal végzik, mivel nincs megadva a változók típusa. A Hi-Tech C 32 bites egész típussal számol. Az osztás is egyész osztás. Így a sor egy kerekítési művelet.


Ezt nem tudtam, köszi!

De épp az ilyenek adják az okát, hogy ki legyen szervezve minden és tesztelve legyen rendesen minden, akár csak egy blink-kóddal is, amivel a timer-t ellenőrizni lehet könnyedén.

Megnézem milyen van nekem itthon, azt tudom, hogy 16F, de nem tuti, hogy 648-as.
A hozzászólás módosítva: Jún 9, 2024
(#) KoblogPerGyok válasza kisgy hozzászólására (») Jún 9, 2024
Ez a kód nekem nem tetszik.
Most fejből írom mindezt, lehet másképp van. Nem használ interrupot, kikapcsolja mind a Timer2 mind a globális interruptot. Akkor hogy lesz az interrupt flag 1, amire hivatkozik a for(; után rögtön?
A for helyett is lehetne While();

PIE1=0; Egy egész regiszter értéke nulla. Ebben a regiszterben kellene bekapcsolni a timer2 interruptot is:

16. oldal

DE nem teszi, így a flag soha nem lesz 1. (szerintem)

Ok, lehet én is sokat hibázok, mert felületesen nézem a kódod, de így nem lesz jó. Látom, hogy ennél a PIC-nél a timer2 másképp van, mint ahogy nálam volt. Lépésről lépésre kell haladni, főleg a PIC-nél, az nem olyan mint az Arduino.
Érdemes például Timer0, timer1 stb. függvényeket írni, ahol van init, stop, start függvény. Ezeket ki kell szervezni .c és .h fájlokba, és include-olni. Ezeket tesztelni kell keményen. Utána lehet PWM-et is előállítani ugyanígy, például PWM_init, PWM_Satart, PWM_stop függvényekkel, mert akkor a kitöltési tényezőt lehet változtatni például egy Timer0-ban is....
Ez jó lehet például az oszcillátor init-re is, amit szintén nem látok, hogy hol miképp van beállítva.

Szerintem túl sok így a hibalehetőség, persze lehet nem ez a hiba, de mintha tényleg ki lenne kapcsolva a global interrupt, ami miatt nincs flag, de tévedhetek. Illetve a PIC amit használtam külön interrupt függvényeket ad az ilyen esetekre, azaz a for(,,)-ban nem kell várni, mire oda jut a processzor. (mi ez a for(,,) pontosan?)

Hát még valami:

  1. PORTA=0b00001001;  
  2.      TRISA=0b00110111;


Fordítva kellene. Így azt gondolom jobb lenne az elejéről írni a kódot, mert lehet sok a hiba. Ha kell segítség szólj, lépésről lépésre össze lehet ezt hozni.
(#) Bakman válasza kisgy hozzászólására (») Jún 6, 2024
Ha jól látom, Timer2-t használod időzítésre is, miközben az a PWM generálásához van rendelve. Megy egyáltalán a kettő egyszerre? Dereng valami, hogy annó próbáltam valamilyen PIC-en de nagyon nem volt jó. Lehet, hogy keverem valamivel, már nem emlékszem. Próbaképpen időzítésre használd a timer1-et vagy a Timer0-át.
(#) asch válasza nickname hozzászólására (») Ápr 15, 2024
Kellene tudni azt is, hogy mekkora a cél-frekvencia és a kitöltési tényező (az ábra 50%-ot sugall, de tényleg annyi-e, és kell-e változatani)?

AMEGA328p esetén van olyan megoldás, hogy a számlálót úgy konfigurálod, hogy OCR1A, OCR1B egyezésnél átállítsa a kimenetet, és triggereljen interruptot (ISR(timer1_COMPA_vect), ISR(timer1_COMPB_vect)). Az interruptból pedig be lehet állítani a következő jelváltás irányát és időpontját.
Ha az IRQ futása belefér két jelváltás között, akkor ezzel a módszerrel tetszőleges jelformát ki lehet adni, az általad leírtat is.

Azt is meg lehet csinálni, hogy két különböző számlálóra állítasz be 1-1 PWM-et, és a számlálóikat úgy indítod el, hogy eltérő fázisban legyenek. Ha három dologra figyelsz, akkor reprodukálhatóan helyesen tudod állítani a fázist:

* Akkor állítsd a számláló értékét, amikor szabályos abban az értelemben, hogy nem ugrasz át eseményt.
* Az egyikből kiolvasod a számláló értéket, számolod az új értéket, és azt beállítod a másik számlálónak.
* Mindezt IRQ kizárt blokkban csinálod: ekkor mindig ugyanannyi lesz a végrehajtás ideje. Ezt vagy méred, vagy az ASM alapján számolhatod is, és ezzel az értékkel korrigálhatod, hogy mennyit adsz hozzá. De ha sima összeadással csinálod, akkor néhány órajel lesz összesen, ami 1 mikroszekundum körülre jön ki, az is lehet, hogy elhanyagolható.

Szerk.: Amit írsz úgy hangzik mintha "dead time" generátorról lenne szó, aminek az a célja, hogy H-híd esetén ne nyissuk szembe a két FET-et, ami rövidzárat jelentene. Vannak csipek, amik beípítetten tudnak dead time-ot generálni a PWM kimenethez, érdemes megfontolni, hogy olyat használj, ami eleve tudja ezt. Pl. az ATtiny1614 az adatlap szerint tudja. Ez egy újabb családba tartozik amit kicsit másképpen kell programozni.
A hozzászólás módosítva: Ápr 15, 2024
(#) KoblogPerGyok válasza KoblogPerGyok hozzászólására (») Márc 21, 2024
Ez lenne az alapkoncepció, majd gondolkodnék azon, mi van, ha zavar van a hálózatban, vagy elszámoltam valamit, azaz időközben beüt egy másik nullátmenet. Első körben a nullátmenet beérkezésekor elindítanék mindent, majd az utolsó sorában leválasztanám a függvényt róla, azaz kikapcsolnám a detektálást. A timer2 lefutása után pedig engedném újra.

Vagy: logikai változókkal oldanám meg, azaz mindig lenne detektálás, de csak akkor indítanék timer1-et, ha a timer2 lefutását és így mindennek a kinullázását jelző változó 1. persze akkor ezt a változót a megfelelő helyeken kell beállítani és kinullázni. Így elkerülném szoftveresen, hogy ráindítson 2x. Az más kérdés, hogy utána olyan beállításokkal kellene mennie, hogy ne csak minden második félperiódusban működjön, és tényleg azt tegye amit szeretnék.
(#) KoblogPerGyok válasza andyka hozzászólására (») Márc 21, 2024
Egyelőre nem értem pontosan mert PIC-hez jobban értek, de nem minden világos miért van.

Én ilyesmin gondolkodnék:

-Nullátmenetbe: (interrupt)
Timer 1 indítása a megfelelő idő betöltésével, így az annyi idő után kapcsol be amit a kívánt teljesítmény igényel. (addig nulla ugye) Azaz 10ms-nél kisebb idővel ugye.

-Timer 1-ben: (interrupt) //Ez adná meg, melyik időben kell kapcsolni a pillanatnyi teljesítményhez

a triak lába bekapcsol, a láb magas.
timer1 kikapcsolása
timer1 kinullázása //úgyis a nullátmenet indítja el

itt indítanék egy timer2-t, ami mindig fixen ugyanannyi idő alatt fut le, ami a triak kapcsolás ideje

-Timer2-ben: (interrupt)
a triak lába kikapcsol. Ez a timer2 adja meg a triaknak szükséges impulzus hosszt.
timer2 kikapcsolása
timer2 kinullázása //Majd elindítja újra a timer1, mikor kella kakaó

Az egészre meg úgy figyelnék, hogy a timer1-be betöltendő idő nagyobb legyen, mint amit a teljesítmény igényel + a triak gyújtási ideje. + valami 1-2 mikroszek a lábak miatt, amit korábban kérdeztél.

Azaz a timer 1 időt NEM lehetne egy bizonyos szint alá vinni. Ezt kellene meghatározni, valamint azt, ha ez van, akkor mit tegyen a progi.

De lesznek nálam sokkal jobban értők is, szerintem tuti kapsz jó megoldásokat, ráadásul a tiéd is lehet jó, lehet csak én nem vágom.
A hozzászólás módosítva: Márc 21, 2024
(#) KoblogPerGyok válasza Massawa hozzászólására (») Márc 19, 2024
Ennyit pakoltam össze 10 perc alatt a wokwi-n, nem tudom most tesztelni.

  1. unsigned long d4_magas_ideje;
  2. unsigned long d5_magas_ideje;
  3. unsigned long dt_tranzisztorok_szembenyitas;
  4. volatile unsigned long most;
  5. volatile unsigned long eltelt;
  6. void setup() {
  7.   // put your setup code here, to run once:
  8.  
  9.  
  10.   d4_magas_ideje=5000; //microsec
  11.   d5_magas_ideje=5000; //microsec
  12.   digitalWrite(4, LOW);
  13.   digitalWrite(5, LOW);
  14.  
  15.   Serial.begin(9600); // Serial connection to print samples
  16.    
  17.   cli(); // disable interrupts during setup
  18.  
  19.   // Configure Timer 1 interrupt
  20.   // F_clock = 16e6 Hz, prescaler = 64, Fs = 50 Hz
  21.   TCCR1A = 0;
  22.   TCCR1B = 1<<WGM12 | 0<<CS12 | 1<<CS11 | 1<<CS10;
  23.   TCNT1 = 0;          // reset Timer 1 counter
  24.   // OCR1A = ((F_clock / prescaler) / Fs) - 1 = 5000-1
  25.   //Remélem ennyi, csak írtam, nem teszteltem.
  26.   OCR1A = 4999;       // Set sampling frequency Fs = 50 Hz
  27.   TIMSK1 = 1<<OCIE1A; // Enable Timer 1 interrupt
  28.  
  29.   sei(); // re-enable interrupts
  30. }
  31. // Timer 1 interrupt service routine (ISR)
  32. ISR(timer1_COMPA_vect)
  33. {
  34.   most=micros();
  35.   digitalWrite(4, HIGH);
  36.   while (micros-most >=d4_magas_ideje)
  37.   {  
  38.   }
  39.   digitalWrite(4, LOW);
  40.   // kis idő, mielőtt szembe nyitnánk a h-hidat
  41.   most=micros();
  42.   while (micros()-most >=dt_tranzisztorok_szembenyitas)
  43.   {
  44.   }
  45. //D5 bekapcsol
  46.   digitalWrite(5, HIGH);
  47.   most=micros();
  48.   while (micros()-most >=d5_magas_ideje)
  49.   {
  50.   }
  51.   digitalWrite(5, LOW);
  52.   //Serial.println(analogRead(0)); // Sample voltage on pin A0
  53. }
  54. void loop() {
  55.   // put your main code here, to run repeatedly:
  56.  
  57. }
(#) deminger válasza KoblogPerGyok hozzászólására (») Jan 25, 2024
  1. #include <Arduino.h>
  2. #include <TM1637Display.h>
  3. #include  <TimerOne.h>
  4.  
  5. #define CLK 8
  6. #define DIO 7
  7. TM1637Display display(CLK, DIO);
  8. volatile int i=0;               // Variable to use as a counter volatile as it is in an interrupt
  9. volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
  10. int dimm;
  11. int dim = 0;
  12. int beolvasdelay;
  13. const byte interruptL1= 2;
  14. int L1_out=12;
  15. int L2_out=3;
  16. int L3_out=4;
  17. int gas=5;
  18. int preflow;
  19. volatile boolean triggered=0;
  20. volatile boolean uzem=0;
  21. volatile int gas_pre=0;
  22. int dimm_old;
  23. int wirespeed=0;
  24. int motorout=6;
  25. int freqStep = 75;    // This is the delay-per-brightness step in microseconds.
  26.  
  27. int current_beolvas ()
  28. {
  29.   int ertek;
  30.   if(beolvasdelay<50){beolvasdelay++;}
  31.   else{
  32.     ertek=((analogRead(A0)+1)/3.41333);
  33.     beolvasdelay = 0;
  34.   }
  35.   return ertek;
  36. }
  37.  
  38. bool torch_switch()
  39. {
  40.   int torch;
  41.   torch = analogRead(A2);
  42.   if(torch>300){return 1;}
  43.   else{return 0;}
  44. }
  45.  
  46. void kiir(int ertek, int viszony)
  47. {
  48.   if(ertek!=viszony){
  49.   display.clear();  // Clear the display
  50.   display.showNumberDec(ertek, false); // Display the number
  51.   }
  52. }
  53.  
  54. void zero_cross_detect() {    
  55.   zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  56.   i=0;
  57.   digitalWrite(L1_out, LOW);       // turn off TRIAC (and AC)
  58. }                                
  59.  
  60. // Turn on the TRIAC at the appropriate time
  61. void dim_check() {                  
  62.   if(zero_cross == true) {              
  63.     if(i>=dim) {                    
  64.       if(uzem)
  65.       {digitalWrite(L1_out, HIGH);} // turn on light      
  66.       i=0;  // reset time step counter                        
  67.       zero_cross = false; //reset zero cross detection
  68.     }
  69.     else {
  70.       i++; // increment time step counter                    
  71.     }                                
  72.   }                                  
  73. }                      
  74.  
  75.  
  76. void wire_speed_pwm()
  77. {
  78. wirespeed=(analogRead(A3)/4);
  79. analogWrite(motorout, wirespeed);
  80. }
  81.  
  82.  
  83. void setup() {
  84.   // initialize digital pin LED_BUILTIN as an output.
  85.   pinMode(L1_out, OUTPUT);
  86.   pinMode(gas, OUTPUT);
  87.   pinMode(motorout, OUTPUT);
  88.   display.setBrightness(7);
  89.   attachInterrupt(digitalPinToInterrupt(interruptL1), zero_cross_detect, RISING);
  90.   timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  91.   timer1.attachInterrupt(dim_check, freqStep);  
  92.  
  93. }
  94.  
  95. void loop() {
  96.   dimm_old=dimm;
  97.   dimm=current_beolvas();
  98.   dim=(113-(dimm/2.6548))+14;
  99.  
  100.   preflow = analogRead(A1);
  101.  
  102.   if(torch_switch())
  103.   {
  104.    gas_pre++;
  105.    digitalWrite(gas, HIGH);
  106.   }
  107.   else if (gas_pre>1)
  108.   {
  109.    gas_pre--;
  110.   }
  111.  
  112.   if((preflow*2)<gas_pre)
  113.   {
  114.     if(uzem==0){gas_pre+=5;}
  115.     uzem=1;
  116.     gas_pre--;
  117.     wire_speed_pwm();
  118.   }
  119.   else
  120.   {
  121.    uzem=0;
  122.    analogWrite(motorout, 0);
  123.   }
  124.  
  125.   if(gas_pre<10 && !torch_switch())
  126.   {digitalWrite(gas, LOW);}
  127.  
  128.  
  129.   kiir(dimm, dimm_old);
  130. }


Ez a kódom egyenlőre, van benne sok favágó megoldás, ez az első nagyobb arduinos próbálkozásom. A cél egy CO2 hegesztő vezérlésének megvalósítása. a fő a 3 fázisos fázishasításos dimmelés megvalósítása, ez nincs még ugye meg. Van benne ezen kívül egy gáz szelep nyitás és annak az időzítése (egyik favágó megoldás) illetve egy PWM motor szabályozás ami a huzaltoló motort vezérli. Ha a fázishasítás miatt ezt a pwm vezérlést el kell engednem az nem akkora gond, meg tudom oldani máshogy is.
(#) KoblogPerGyok válasza deminger hozzászólására (») Jan 25, 2024
  1. volatile byte allapot;
  2.  
  3.  
  4.  
  5. //Ebben a fggvényben lévő dolgok fognak lefutni, ha a beállított idő letelik
  6.  
  7. ISR(timer1_COMPA_vect)
  8. {
  9.   allapot=!allapot;
  10.   if (allapot==true) {
  11.     PORTB=255;
  12.   }
  13.   else {
  14.     PORTB=0;
  15.   }
  16. }
  17.  
  18. void setup() {
  19.  
  20. allapot=false;
  21. cli(); // disable interrupts during setup+
  22.  
  23.   // Configure Timer 1 interrupt
  24.   // F_clock = 16e6 Hz, prescaler = 64, Fs = 100 Hz
  25.  
  26.   //  CS12      CS11    CS10    Description
  27.   //     0      0       0       Timer stop
  28.   //     0      0       1       Prescalar=1
  29.   //     0      1       0       Prescalar=8
  30.   //     0      1       1       Prescalar=64
  31.   //     1      0       0       Prescalar=256
  32.   //     1      0       1       Prescalar=1024
  33.   //     1      1       0       Falling edge
  34.   //     1      1       1       Rising edge
  35.  
  36.   TCCR1A = 0; //Mert nem kell PWM ezen
  37.   //Ez kell neked, ezt kell megérteni, az adatlapot böngészni:
  38.   TCCR1B = 1<<WGM12 | 0<<CS12 | 1<<CS11 | 1<<CS10; //CS12 ,CS12,11,10 a Prescale Binárisan számolva 1, 8, 32, 64, 128, 256, 1024 értékeket lehet beállítani
  39.   TCNT1 = 0;          // reset Timer 1 counter
  40.   // OCR1A = ((F_clock / prescaler) / Fs) - 1 = 2499
  41.   OCR1A = 2499;//100Hz mert 16000000/64=250000 ez osztva a kívánt 100-Hz-el:=2500 és-1
  42.  
  43.  
  44.   sei(); // re-enable interrupts  
  45.  
  46.  
  47.  
  48. Serial.begin(9600);
  49. Serial.println("Soros Port elinditva 9600 Baoud-al.");
  50. DDRB = DDRB | B11111111;
  51. Serial.println("Port B kimenetre allitva. 8-13 pin");
  52. PORTB = B00000000;
  53. Serial.println("Port B Nullara allitva.");
  54.  
  55. TIMSK1 = 1<<OCIE1A; // Timer 1 interrupt indítása
  56.  
  57. }
  58.  
  59. void loop()
  60.   {
  61.  
  62.   }


Bővebben: Link

Ide feltöltöttem, megy. A LED világít folyamatosan de nem tudja lemodellezni, no meg 100Hz-en amúgy is emberi szemmel nem látható lenne a villogás. Nekem PORT manipuláció kellett, azzal villogtatom a ledet, de 8-13 ig villogna most minden lábon.

A timer 2 szerintem hasonló. De 150Hz-re ez állítható, de ekkor az interrupt- függvényben kell a megelelő változóknak értéket adni.
A hozzászólás módosítva: Jan 25, 2024
(#) deminger válasza benjami hozzászólására (») Jan 25, 2024
Igen, 50hz-es jelre kell a dolog, a logikát értem és köszönöm az ötletet. A kérdésem akkor már csak a kivitelezés részét érinti: egy arduino nano alkalmas e erre a feladatra? Azt tudom hogy van benne egy timer amit a delay függvény használ, illetve van benne egy timer1 nevű amit használok az első fázishoz, ezt indítja a nullátmenet és ennek a végén gyújt az első triak. A kérdésem hogy van e benne még egy timer (a netes kereséseim alapján kellene lennie) és ha igen akkor azt hogyan tudom erre felhasználni? (valami konkrét kódrészlet ha lenne az lenne a legjobb)
(#) deminger hozzászólása Jan 25, 2024
Üdv mindenkinek!
Egy kis segítséget szeretnék kérni egy arduinos projektben. Azzal vagyok elakadva hogy próbálok egy 3 fázisú fázishasításos dimmelést megvalósítani egy nanoval, de nem igazán tudok rájönni hogy hogyan kellene. Van az első fázison egy zero-cross figyelésem ami a D2es bemeneten egy interrupt és a timer1 segítségével azon a fázison szépen csinálja a dimmelést. Viszont nem tudom, hogy a másik két fázist hogy tudnám megfelelően megoldani, vagy hogy egyáltalán egy nano képes-e erre. Nagy segítség lenne ha valaki adna pár tippet hogy hogyan menjek tovább.
(#) asch válasza sonajkniz hozzászólására (») Okt 4, 2023
Szerintem maga a CPU altatható külső RTC nélkül is, csak az oszcillátor kell hogy működjön, meg a timer. A timer overflow (pontosan két másodpercenként), és a gombokra rakott pin change interrupt ébresztheti a CPU-t.
fotomen32-nek: Egy ATMEGA328p-t egyszer méregettem, hogy mennyit fogyaszt alvó módokban. A legfontosabb, hogy egyik láb se maradjon lebegve! Ha lebeg a láb, akkor esetleg belül változást tud indítani, és akkor fogyaszt a csip. Nem kell feltétlen külső le/felhúzó ellenállás, de a belsőt be kell álllítani a nem használt lábakra. Alapból ezek a csipek úgy működnek, hogy állapotváltozás nélkül a tranzisztorokon nem folyik áram, és nincs fogyasztásuk. A kivétel az oszcillátor és a számláló lesz, ennek menni kell. Ha a külső RTC oszcillátora hatékonyabb, mint maga a PIC, akkor lehet csak javítani azzal a hatékonyságot.

Az ADC nagy zabáló, az mindenképpen legyen lekapcsolva! Illetve minden láb legyen megfelelően bekötve és beállítva úgy, hogy statikus legyen a működés! Az ATMEGÁs mérésemnél először például elkövettem azt a hibát, hogy a VREF lábra nem kötöttem semmit és lebegni hagytam: többszörös lett a mért áram, mint az adatlapi! Ezzel azt akarom mondani, hogy akármilyen csipet is használsz, az adatlap szerint kell huzalozni ahhoz, hogy elérd a specifikáció szerinti fogyasztást.

A sonajkniz által javasolt csip adatlapjából: "Extreme Low-Power Management PIC18LF1XK22 with XLP Technology
• Sleep mode: 34 nA
• Watchdog Timer: 460 nA
timer1 Oscillator: 650 nA @ 32 kHz"
Tehát eszerint a 684nA fogyasztást el lehet érni alvás közben, a példa is pont a kvarcórák tipikus 32kHz oszcillátorával számol. Ezt az értéket összehasonlíthatod azzal, hogy a külső RTC mit ígér, illetve ebből tudod becsülni, hogy mennyi időt fog bírni elemről.
A hozzászólás módosítva: Okt 4, 2023
(#) sonajkniz válasza fotomen32 hozzászólására (») Okt 4, 2023
Ez a PIC 1,8-5,5V-ig dolgozik.
A PIC fogyasztása nagyban csökkenthető, ha alapvetően alszik, és csak 2 másodpercenként ébred timer1 által vezérelve. Ilyenkor pár villámgyors számítás, és megy vissza szunyálni, hacsak nem érzékel gombnyomást. Ha igen, kapcsolja a ledeket. A gomb elengedése után törölni kell az összes kimenetet, (még kisebb belső fogyasztás érhető el, ha altatás előtt a kimeneteket átkapcsoljuk bemenetté) majd mehet újra aludni. Persze így se számíts többéves működésre, de 6-8 hónapig azért elmegy egy 2032-essel.
(#) asch válasza Tambi hozzászólására (») Aug 18, 2023
Nem mondtad, hogy mi a hardvered, feltételezem, hogy valami AVR alapú Arduino lehet, például UNO. Ennek van PWM kimenete, amivel simán meg lehet valósítani ez a jelgenerátort. Viszont az Arduino könyvtárai alig-alig alkalmasak ilyesmire.
Ez az Arduinonak a nagy csapdája, hogy hiába fut mikrovezérlőn, pontos vezérlést, amire a mikrovezérlőket teremtették, azt Arduinoval nagyon nehéz megvalósítani. A szoftver nehézkesen alkalmas csak rá. A hardver viszont simán, az bőven elegendő erre a célra.
Lényegében PWM kimenetet kell használni, csak nem a kitöltési tényezőt kell állítgatni, hanem a periódusidőt, és erre elfelejtettek API-t adni az Arduino-n belül. (Ismereteim szerint, ha valaki tud rá APIt mégis az csak jó.)

Az Arduino környezeten belül is meg lehet csinálni, hogy a PWM-et nem a liben keresztül, hanem közvetlenül a regisztereket írva programozod fel. Én ezt csinálnám, akár úgy, hogy bekapcsolnám a PWM-et az Arduino libben - analogWrite funckcióval, ekkor már látsz valami működést szkópon. És utána felülírnám azokat a változókat az adatlap szerint, amivel másképpen akarom hajtani a PWM modult (Timer/Counter1). Próbálgatva kis lépésekkel lehet haladni.

Alternatív megközelítés, hogy teljesen kihagyod az analogWrite meghívását, és az adatlap szerint a regisztereket beállítva programozod fel a PWM-et.

Itt van az ATMEGA328p csip adatlapja: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

Ezen belül ez a fejezet lesz érdekes: 15.9.2 Clear Timer on Compare Match (CTC) Mode. Ebben a módban hajtva az OCR1A regiszterbe kell beírni a periódusidőt és ezzel lehet állítani a periódust/frekvenciát. Tehát ezt a módot kell bekonfigurálni az adatlap szerint és után az OCR1A értékét állítgatni.

Ha már valamennyire működik, akkor még azt is meg kell csinálni, hogy mindig az átfordulás után kell beírni az értéket, amikor a számláló kicsi. Különben ha kisebbre állítjuk a határt (OCR1A) mint az előző értéke, és a számláló éppen a kettő között van amikor átírjuk, akkor lesz egy hibás teljes periódus. Ezt elkerülni a legegyszerűbben úgy lehet, hogy az OCIE1A interruptot engedélyezed, és ennek az interruptnak a kezelőjében másolod be a következő értéket. Ez az IRQ mindig 0-ra állítás után fut, tehát amikor a lehető legtöbb időnk van beállítani a határt (OCR1A). 50kHz esetén is van 320 órajelünk erre, ami bőven bőven elegendő ezen a processzoron.

Pszeudó kód a periódusidő bemásolására az OCIE1A regiszterbe:

  1. static volatile uint16_t period=255;
  2. loop()
  3. {
  4.   int poti = analogRead(A0);  //A poti két "vége" az ARDUINO NANO 17. lába (3,3V) és 29. lába (GND) közé, csúszkája a 19. lábára (A0) van kötve.
  5.   int freq = 100 + 76 * poti; // min "freq" = 100 Hz, max "freq" = 100 + ((76*1023*(3,3/5)) = 51 314 Hz.
  6.   uint16_t newPeriod=big_number / freq; // periódusidő kiszámolása a frekvencia alapján osztással. A big_number értékét a PWM beállításai alapján kell kiszámolni
  7.   ATOMIC_BLOCK  ( ATOMIC_RESTORESTATE)
  8.   {
  9.     period = newPeriod;
  10.   }
  11. }
  12.  
  13. ISR(timer1_COMPA_vect)
  14. {
  15.   OCIE1A=period;
  16. }


Az ATOMIC_BLOCK azért kell, mert 16 bites érték RAM-ba beírása nem atomi művelet.

Arra, hogy ez a proci ne lenne alkalmas ne hallgass, nagyonis alkalmas, a feladat egyáltalán nem nehéz ennek a procinak, csak korrektül kell felprogramozni. Persze az STM32 is alkalmas nyilván, ha mégis arra váltasz.

Valóban érdemes több ADC mérést csinálni és átlagolni. Az, hogy mennyire lesz zajos a mérés, az az áramkör kialakításán múlik nagymértékben, ha nem vagy profi, akkor várhatóan bizony zajos lesz...

Szerk.: ahhoz, hogy a 16 bites tartomány elegendő legyen a periódusidő kifejezéséhez, az osztót /8-ra kell állítani ( TCCR1B CS bitjei). Így 40-20000 között lesz a periódusidő az igényelt frekvenciákhoz.
A hozzászólás módosítva: Aug 18, 2023
(#) GPeti1977 válasza sdrlab hozzászólására (») Júl 31, 2023
ATMEGA timer1 moduljával meg tudom csinálni.
(#) GPeti1977 hozzászólása Júl 26, 2023
Az USDX rádiót szerintem érdemes lenne megépíteni ATMEGA2560 kontrollerrel.
Több láb, memória, ami szerintem zavaró az USDX -nél hogy a hang 8 bites, így én nem érteni a beszédit, pedig az A/D konverter 10 bites, illetve a számolásokat 16 biten végzi, de csak a timer1 alsó 8 bitje van használva fast PWM módban, a jel osztva 32-vel nem, tudom miért nem a 10 bites módban használják, valószínűleg lassúbb.
Nem lenne jobb egy külső DAC például MCP4921 ?
Valahogy így:
OCR1AL = min(max((ozi2>>5) + 128, 0), 255);
helyett:
int DACOUT = min(max((ozi2) + 2048, 0), 4095);
SPDR = (DACOUT >> 8)|0x30;
SPDR = DACOUT & 0x00FF;
(#) KoblogPerGyok válasza Kera_Will hozzászólására (») Júl 5, 2023
Egész pontosan:

  1. // Timer 1 interrupt service routine (ISR)
  2. ISR(timer1_COMPA_vect)
  3. {
  4.        PORTB=(szin_tabla[index]);
  5.        index+=increment;
  6. }
(#) KoblogPerGyok válasza vill hozzászólására (») Jún 4, 2023
Üdv!

Akkor jók lehetnek a kijelzések, de ezt a kódot nem értem pontosan. Az idő nem lesz pontos. Miért nem használsz timert? Az pontosabb lehet, mert a fenti kódodban a műveletek elvégzéséhez időre van szüksége az mcu-nak. Volatile változót növelhetsz, ha a timer beüt. Elvileg az Atmega is tud olyat, hogy a Timer valmilyen kezdőértékről indulva fusson. Azt beállítva lehet pontosítani még. Bár az IDE erre nem nagyon alkalmas.

if (timer == 1){
sec = sec + 1;
delay(1000); //Ez nem vágja agyon a hardveres timert????

Bár itt van timer, de nem tudom az pontosan micsoda, de a delay tuti nem a legjobb ide. Vagy még jobb megoldás az RTC modul használata lenne.

Itt valamiről beszélgetnek:

Bővebben: Link

A PIC-nél (annak sem pontos a pll-je) úgy kell beállítani a timert, hogy a fő oszcillátort le lehet osztani kettő hatvényaival. Azaz pl 64-el. Feltéve, ha az Arduino 16MHz-en fut, akkor 0.25MHz-en fut a timer 64 -es leosztás mellett. Ha a timer 66535-ig tud számiolni, akkor a túlcsordulás kb 0.27s -enként történik. Ez nem elég, de le lehet osztani többel is:

3. Available division factors:
CS12 - CS10 = 000 : no clock source TC1 is OFF
CS12 - CS10 = 001 : divide by 1
CS12 - CS10 = 010 : divide by 8
CS12 - CS10 = 011 : divide by 64
CS12 - CS10 = 100 : divide by 256
CS12 - CS10 = 101 : divide by 1024

Ha 256-al osztod, akkor már több mint 1s. Az jó. Ha tudod, hogy 16/256MHz (62500Hz)-en számol a timer és tudod, hogy ha 16 bites a timer (saccolom, remélem ennyi) akkor 65535-62500=3035-ről kell indtani. A PIC-nél lehet tudni, hogy maga a beállítás mennyi órajelbe telik, azt le lehet vonni. De 256 prescale-nél mát más lehet a dolog...

Szóval, ha pontos külső 16MHz-es kvarcról hajtod, még pontos is lehet.

De lehet ezt is csinálod, de akkor a delay-t nem értem...
(#) wbt hozzászólása Dec 6, 2022
Sziasztok!
Frekvenciagenerátorhoz timer1-el állítgatnom kellene az előosztót.
--------------------------------------
(P-frekvencia Hz-ben van és TOGGLE a kimenet, de ez most nem érdekes)
Select Case P_frekvencia
Case Is >= 123:
A = Tccr1b
A = A And &B1111_1000
A = A Or &B0000_0001 'Előosztó=1
P_oszto = 8000000 / P_frekvencia
Case 16 To 122:
A = Tccr1b
A = A And &B1111_1000
A = A Or &B0000_0010 'Előosztó=8
P_oszto = 1000000 / P_frekvencia
Case Is < 16:
A = Tccr1b
A = A And &B1111_1000
A = A Or &B0000_0011 'Előosztó=64
P_oszto = 125000 / P_frekvencia
End Select
Tccr1b = A
Temp_w = Loww(p_oszto) '16bit
Compare1a = Temp_w
Compare1b = Temp_w

Start timer1
-------------------------------------------------------------------------------------
Hiába írom a TCCR1B regisztert, nem történik semmi
Mit néztem be?
(alsó 3 bit az előosztó)
(#) Bakman válasza spenyo hozzászólására (») Nov 3, 2022
Attól függ, milyen PIC-ről beszélünk. PWM-et le leht állítani úgy is, hogy adott lábat bemenetre kapcsolod. Az új kontrollerekben ott a bővített tudású Timer2, kapuzható timer1, CLC, NCO modulok stb. Csak fantázia kérdése.
(#) Bakman válasza Lamprologus hozzászólására (») Szept 28, 2022
Miért nem direkt a PWM jelet méred? timer1/3/5 module with gate control, vagy újabb kontrollerekben SMT - Signal Measurement Timer.
(#) Naresh Jain válasza Hp41C hozzászólására (») Jún 24, 2022
Dear friend, hardware testing is time taking and little hard job and remote in proteus is not functioning perfectly, please let me know if we attached two toggle swiches on free port as shown in attached screen shot,port RC0 SW1 is for ON and port RC2 SW2 is for OFF for triac2, then what ia modification in codes in main.c, if it is possible then i can test in proteus simulation software,
PLEASE MODIFY THE CODES:
  1. /********************************************************************************
  2. *                   Fan Controller                                              *
  3. *                                                                               *
  4. *   This program is free software: you can redistribute it and/or modify        *
  5. *   it under the terms of the GNU General Public License as published by        *
  6. *   the Free Software Foundation, either version 3 of the License, or           *
  7. *   (at your option) any later version.                                         *
  8. *                                                                               *
  9. *   This program is distributed in the hope that it will be useful,             *
  10. *   but WITHOUT ANY WARRANTY; without even the implied warranty of              *
  11. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
  12. *   GNU General Public License for more details.                                *
  13. *                                                                               *
  14. *   You should have received a copy of the GNU General Public License           *
  15. *   along with this program.  If not, see <https://www.gnu.org/licenses/>.      *
  16. *                                                                               *
  17. *       Date            : Friday, 21 January 2011                               *
  18. *       Author          : C.V.Niras/VU3CNS                                      *
  19. *       Copyright       : (C) 2010 C. V. Niras                                  *
  20. *       Email           : cvniras@gmail.com                                     *
  21. *       Processor       : 12F675                                                *
  22. *       First Release   : 23/01/2011                                            *
  23. *       Ver             : 0.7                                                   *
  24. *   Change History:                                                             *
  25. *       Rev     Date        Description                                         *
  26. *       0.5     06/03/2011  First stable release                                *
  27. *       0.6     08/03/2011  Bug fixed - Can't swich on by CH+, when turned      *
  28. *                           off by set speed to 0                               *
  29. *       0.7     14/06/2011  Trigger off delayed for full speed (low firing      *
  30. *                           angle) to reach the TRIAC latch current             *
  31. *                                                                               *
  32. *********************************************************************************/
  33. #include <pic.h>
  34. #include "type_def.h"
  35. #include "remote_commands.h"
  36.  
  37. #if defined _12F675
  38. __CONFIG(WDTDIS & MCLRDIS & INTIO & BORDIS & UNPROTECT & PWRTEN);
  39.  
  40. #define IsIRDataBitHigh()   GPIO3 == 0  // Inverted logic
  41. #define SW_UP           _GPIO,0         // Up switch
  42. #define SW_DN           _GPIO,2         // Down switch
  43. #define LEDOn()         GPIO1 = 1       // LED
  44. #define LEDOff()        GPIO1 = 0
  45. #define TriacOn()       GPIO5 = 0       // Triac
  46. #define TriacOff()      GPIObits.GPIO5 = 1
  47. #define TRIAC           GPIO5           // Triac pin
  48. #endif  
  49.  
  50. #if defined _16F676
  51. __CONFIG(WDTDIS & MCLRDIS & INTOSCIO & BORDIS & UNPROTECT & PWRTEN);
  52.  
  53. #define GPIO PORTA
  54. #define TRISIO TRISA
  55. #define GPIF RAIF
  56. #define GPIE RAIE
  57.  
  58. #define IsIRDataBitHigh()   PORTAbits.RA3 == 0  // Inverted logic
  59. #define SW_UP           _PORTA,0         // Up switch
  60. #define SW_DN           _PORTA,2         // Down switch
  61. #define LEDOn()         PORTAbits.RA1 = 1       // LED
  62. #define LEDOff()        PORTAbits.RA1 = 0
  63. #define TriacOn()       PORTAbits.RA5 = 0       // Triac
  64. #define TriacOff()      PORTAbits.RA5 = 1
  65. #define TRIAC           PORTAbits.RA5           // Triac pin
  66.  
  67. // v Added to handle triac2
  68. #define Triac2On()      PORTCbits.RC5 = 0       // Triac2
  69. #define Triac2Off()     PORTCbits.RC5 = 1
  70. #define TRIAC2          PORTCbits.RC5          
  71. // ^ Added to handle triac2
  72.  
  73. #endif  
  74.  
  75.  
  76. __EEPROM_DATA(5, 1, 1, 255, 255, 255, 255, 255);
  77.  
  78. __IDLOC7('0','.','7','B');
  79.  
  80. #define TIMER_ENABLE                    // Enable timer
  81. // -- Chip Configurations --
  82. #define _XTAL_FREQ      4000000
  83. #define ZC_PIN_MASK     0x10            // Pin used for zero cross detection
  84. #define IR_PIN_MASK     0x08            // IR sensor output
  85. #define TIME_COUNT      6866            // Number of timer1 overflows in an hour
  86. #define ANY_KEY         Key & 0x80
  87. #define UP_KEY          Key & 0x01
  88. #define DN_KEY          Key & 0x02
  89.  
  90. // Timer 1 is the time base, 1 bit time = 8us; the NEC physical bit time is 560us = 70 Timer 1
  91. // The following time are set with a +/- 20% tolerance
  92.  
  93. #define IR_MARK_MIN_TIME    787
  94. #define IR_SPACE_MIN_TIME   219
  95. #define MIN_IR_BIT_TIME     56
  96. #define MAX_IR_BIT_TIME     84
  97.  
  98. // -- End of Chip Configurations --
  99.  
  100. #define IRRx            Flag.b0         // New IR bit received
  101. #define IRNewHit        Flag.b1         // A new IR command received
  102. #define Error           Flag.b2         // General error flag
  103. #define IRCmdRepeat     Flag.b3         // A IR repeat command received
  104. #define StartFan        Flag.b4         // Indicate to start the fan
  105. #define EEPromWrite     Flag.b5         // Indicate to write to EEPROM
  106. #define UnknownCmd      Flag.b6         // Unused IR command
  107.  
  108. #define EETimeUpdate    Flag1.b0        // Indicate to update time in eeprom
  109. #define IR05Seconds     Flag1.b1        // A 0.5 seconds of IR inactivity, used to clear IR command repeate flag
  110. #define ClearLED        Flag1.b2        // Need to turn off LED
  111.  
  112. #define FanOn           Status.b0       // Fan Running
  113. #define TimerRunning    Status.b1       // Timer Running
  114.  
  115. #define AddZeroToIRData()   IRData._dword >>= 1                                 // Add a 0 bit to IR data
  116. #define AddOneToIRData()    IRData._dword >>= 1; IRData._dword |= 0x80000000    // Add a 1 bit to IR data
  117.  
  118. // NEC IR protocol states
  119. typedef enum _NEC_STATES
  120. {
  121.     IR_IDLE,
  122.     IR_MARK,
  123.     IR_SPACE,
  124.     IR_HIGH,
  125.     IR_LOW,
  126.     IR_REPEAT
  127. } NEC_STATES;
  128.  
  129. // V A R I A B L E S
  130. //const unsigned char STable[10] = {0, 157, 165, 173, 181, 188, 195, 205, 216, 252};
  131. // Modified to latch low power (load) fans  low firing angle (on full speed)
  132. const unsigned char STable[10] = {0, 157, 165, 173, 181, 188, 195, 205, 216, 234};
  133. near volatile BYTE Flag, Flag1, Status;
  134. near NEC_STATES IRState;
  135. unsigned char IRDataCount, PhaseAngle, Speed, Time, Count;
  136. volatile near unsigned char EECounter, Ticks, Key, KeyCount;
  137. volatile unsigned int IRTime, TimeCounter;
  138. DWORD IRData;
  139.  
  140. // F U N C T I O N   P R O T O T Y P E S
  141. void IRHandler(void);
  142. void NECDecoder(void);
  143. void InitIR(void);
  144. void SetSpeed(void);
  145. void OffTimer(void);
  146. void OnTimer(void);
  147. void SetTimer(void);
  148. void GetEEVariables(void);
  149. void SetEEVariables(void);
  150. void KeyDelay(void);
  151. void interrupt isr(void);
  152. void Delay2s(void);
  153.  
  154. // M A I N
  155. void main(void)
  156. {
  157.     #asm
  158.         call    0x3ff
  159.                 bsf             STATUS, 5
  160.                 movwf   OSCCAL & 0x7f
  161.                 bcf             STATUS, 5
  162.     #endasm
  163.     GPIO    = 0;                                        // Clear PORT
  164.  
  165. // v Added to handle triac2
  166.     PORTC   = 0;
  167. // ^ Added to handle triac2
  168.  
  169.     TriacOff();                                         // Triac off
  170.     TRISIO  = ZC_PIN_MASK | IR_PIN_MASK | 0x05;         // IR, Zero cross and swiches
  171.  
  172. // v Added to handle triac2
  173.     TRISC   = 0;
  174. // ^ Added to handle triac2
  175.  
  176.     WPU     = 0x05;                                     // Weak pull up enabled for wwitches
  177.     IOC     = ZC_PIN_MASK | IR_PIN_MASK;                // Interrupt on change is enabled for GPIO2, GPIO4
  178.     ANSEL   = 0x00;                                     // All are digital i/o
  179.     CMCON   = 0x07;                                     // Comparators off
  180.     INTCON  = 0x68;                                     // Enable PEIE, Timer0, Port change interrupts
  181.     OPTION_REG  = 0x05;                                     // INT falling edge, Prescaler 1:64
  182.     T1CON   = 0x31;                                     // Prescaler 1:8, internal clk, TMR1ON
  183.     LEDOn();
  184.     Flag._byte = 0;                                     // Initialise flags and variables
  185.     Flag1._byte = 0;
  186.     InitIR();
  187.     GetEEVariables();                                   // Read variables  eeprom
  188.     IRState = IR_IDLE;                                  // Init IR state
  189.     if(FanOn)
  190.         StartFan = 1;
  191.     FanOn = 0;                                          // This created a fresh start
  192. #ifdef  TIMER_ENABLE
  193.     if(TimerRunning)                                    // If already started, set the time again
  194.         SetTimer();
  195. #endif
  196.     GIE = 1;                                            // Enable interrupts
  197.     SetSpeed();                                         // Set the speed
  198.     LEDOff();                                           // Turn off LED
  199.     Count = Time << 1;                                  // Count = Time * 2, i.e turn on/off
  200.     Ticks = 0;
  201.     do
  202.     {
  203.         NECDecoder();                                   // Decode NEC formatted IR data
  204.         if(IRNewHit)                                    // Is any new data?
  205.         {
  206.             IRNewHit = 0;                               // Y. Clear flag
  207.             IRHandler();                                // Do the command
  208.         }
  209.         if(IRCmdRepeat)                                 // As long as the repeat command present
  210.         {                                               // do not turn of LED
  211.             IRCmdRepeat = 0;
  212.             Ticks = 0;                                  // for the same clear Ticks
  213.         }
  214.         if(EEPromWrite)
  215.         {
  216.             EEPromWrite = 0;                            // Clear eeprom update flag
  217.             SetEEVariables();                           // Write variables if necessory
  218.         }
  219.         if(ClearLED)
  220.         {
  221.             if(Ticks & 0x20)                            // If remote command received, turn off LED after only
  222.             {                                           // few ms (~320ms)
  223.                 ClearLED = 0;
  224.                 LEDOff();
  225.             }
  226.         }
  227. #ifdef  TIMER_ENABLE
  228.         else if(TimerRunning && (Ticks & 0x40))         // If timer is running and a short time expired (640ms)
  229.         {                                               // used to blink LED to show the time remaining
  230.             if(Count == 0xF7)                           // Reload counter to show the time, after a certain time gap
  231.             {
  232.                 Count = Time << 1;                      // Count = Time * 2, i.e turn on/off
  233.                 LEDOff();                               // Ensure LED is off
  234.             }
  235.             if(!(--Count & 0x80))                       // Blinks the LED till counter become -ve
  236.             {
  237.                 if(Count & 0x01) {                      // On odd numbers in counter LED on
  238.                     LEDOn();
  239.                 }
  240.                 if(!(Count & 0x01)) {                   // For even numbers LED off
  241.                     LEDOff();
  242.                 }
  243.             }
  244.             Ticks = 0;                                  // Reset ticks
  245.         }//if(TimerRunning && (Ticks & 0x40))
  246. #endif
  247.  
  248.         if(KeyCount >= 4)                               // Has key pressed for a short time?
  249.         {
  250.             if(UP_KEY)                                  // Y. Check for Up key press
  251.             {
  252.                 StartFan = 1;                           // Y. Up key pressed, inc the speed
  253.                 Speed++;
  254.             }
  255.             if(DN_KEY)                                  // Check for a down key press
  256.             {
  257.                 StartFan = 1;                           // Y. Down key pressed, decrement the speed
  258.                 Speed--;
  259.             }
  260.             if(StartFan)                                // If any key pressed, do the action
  261.             {
  262.                 SetSpeed();
  263.                 KeyDelay();                             // Give a delay beore the next check
  264.             }
  265.         }
  266.     }while(1);
  267. }// main
  268.  
  269. // F U N C T I O N S
  270. /**
  271. The function is used to decode IR commands and make changes required
  272. */
  273. void IRHandler(void)
  274. {
  275.     if(!(IRData.byte0 ^ IRData.byte1) == 0)             // Address and its compliment match
  276.      {
  277.          if(IRData.byte0 == 0)                          // Address  is zero
  278.          {
  279.              if(!(IRData.byte2 ^ IRData.byte3) == 0)    // Command and its compliment match
  280.              {
  281.                 UnknownCmd = 0;
  282.                 switch(IRData.byte2)
  283.                 {
  284.                     case VOL_PLUS:
  285.                     StartFan = 1;
  286.                     Speed++;
  287.                     break;
  288.                     case VOL_MINUS:
  289.                     StartFan = 1;
  290.                     Speed--;
  291.                     break;
  292.                     case DIGIT0:
  293.                     Speed = 0;
  294.                     OffTimer();
  295.                     break;
  296.                     case DIGIT1:
  297.                     StartFan = 1;
  298.                     Speed = 1;
  299.                     break;
  300.                     case DIGIT2:
  301.                     StartFan = 1;
  302.                     Speed = 2;
  303.                     break;
  304.                     case DIGIT3:
  305.                     StartFan = 1;
  306.                     Speed = 3;
  307.                     break;
  308.                     case DIGIT4:
  309.                     StartFan = 1;
  310.                     Speed = 4;
  311.                     break;
  312.                     case DIGIT5:
  313.                     StartFan = 1;
  314.                     Speed = 5;
  315.                     break;
  316.                     case DIGIT6:
  317.                     StartFan = 1;
  318.                     Speed = 6;
  319.                     break;
  320.                     case DIGIT7:
  321.                     StartFan = 1;
  322.                     Speed = 7;
  323.                     break;
  324.                     case DIGIT8:
  325.                     StartFan = 1;
  326.                     Speed = 8;
  327.                     break;
  328.                     case DIGIT9:
  329.                     StartFan = 1;
  330.                     Speed = 9;
  331.                     break;
  332.  
  333.                     case CH_MINUS:
  334.                     FanOn = 0;
  335.                     OffTimer();
  336.                     break;
  337.  
  338.                     case CH_PLUS:
  339.                     if(Speed == 0) Speed++;
  340.                     StartFan = 1;
  341.                     break;
  342.  
  343.                     case PREV:
  344.                     if(FanOn)   Time--;
  345.                     SetTimer();
  346.                     break;
  347.  
  348.                     case NEXT:
  349.                     if(FanOn)   Time++;
  350.                     SetTimer();
  351.                     break;
  352.  
  353.                     case EQ:
  354.                     OffTimer();
  355.                     break;
  356.  
  357.                     case PLAY:
  358.                     OnTimer();
  359.                     break;
  360.  
  361. // v Added to handle triac2
  362.                                     case CH100:
  363.                     Triac2On();
  364.                     break;
  365.      
  366.                     case CH200:
  367.                     Triac2Off();
  368.                     break;
  369. // ^ Added to handle triac2
  370.  
  371.                     default:
  372.                     UnknownCmd = 1;
  373.                     break;
  374.                 }
  375.                 if(!UnknownCmd){
  376.                     LEDOn();                // A new command received
  377.                     ClearLED = 1;           // Clear LED after a little time
  378.                     Ticks = 0;              // Reset timer ticks
  379.                     SetSpeed();
  380.                 }
  381.              }// if((IRData.byte0 ^ IRData.byte1) == 0)
  382.          }// if(IRData.byte3 == 0)
  383.      }//if((IRData.byte3 ^ IRData.byte2) == 0)
  384. }
  385. /**
  386. Off the timer, without changing previous set time
  387. */
  388. void OffTimer(void)
  389. {
  390.     TimerRunning = 0;                                   // Turn off timer
  391.     Time = eeprom_read(1);                              // Read the eeprom, value
  392.     EETimeUpdate = 1;                                   // Update time in the eeprom
  393.     EECounter = 0;                                      // Clear the eeprom counter to update eeprom
  394. }
  395. /**
  396. On timer, start with the previous set time, if the timer is not running
  397. */
  398. void OnTimer(void)
  399. {
  400.     if(FanOn == 1)                                      // Only start Timer when fan on
  401.     {
  402.         if(!TimerRunning)                               // Nothing to do if already started
  403.         {
  404.             TimerRunning = 1;                           // Start the timer
  405.             Time = eeprom_read(1);                      // Get time  eeprom
  406.             if(Time == 0)                               // If zero, switch on timer with a non zero value, i.e one hour
  407.                 Time++;
  408.             TimeCounter = TIME_COUNT;                   // Reload the counter
  409.             EETimeUpdate = 1;                           // Update time in the eeprom
  410.             EECounter = 0;                              // Clear the eeprom counter to update eeprom
  411.         }
  412.     }
  413. }
  414. /**
  415. Set the counters for the timer. When the counter reached zero, the fan will be turned off
  416. If the timer not running, it reload time value with the last saved value  the eeprom,
  417. otherwise adjust counters as required, and clear eeprom counter to update time value in the
  418. eeprom, for the same it set a EETimeUpdate flag
  419. */
  420. void SetTimer(void)
  421. {
  422.     if(Time & 0x80)                                     // A neg, so clear it
  423.         Time = 0;
  424.     if(Time > 8)
  425.         Time = 8;                                       // Max 8 hours
  426.     if(FanOn == 0)                                      // Nothing to do if fan is not running
  427.         return;
  428.     if(!TimerRunning && (Time != 0)) {                  // If decrementing, and time reached zero, on further
  429.         Time = eeprom_read(1);                          // decrements never start the timer, only start on
  430.         TimerRunning = 1;                               // increments, i.e when time not zero.
  431.         if(Time == 0)                                   // If zero, start with a non zero value
  432.             Time++;                                     // i.e. set to one
  433.     }
  434.     if(Time == 0)                                       // Stop timer, if time is zero
  435.         TimerRunning = 0;
  436.     TimeCounter = TIME_COUNT;                           //
  437.     EETimeUpdate = 1;                                   // Update time in the eeprom
  438.     EECounter = 0;                                      // Clear the eeprom counter to update eeprom
  439. }
  440. /**
  441. Set the speed and update phase angle for a given speed. If start fan flag is set, and fan not running
  442. it starts fan will full speed for a second, then changes to ed speed.
  443. */
  444. void SetSpeed(void)
  445. {
  446.     if(Speed & 0x80)                                    // A neg, keep it as zero
  447.         Speed = 0;
  448.     if(Speed >= 10)                                     // Reach the max.
  449.         Speed = 9;
  450.     if(Speed == 0){
  451.         StartFan = 0;                                   // For a zero speed, switch off
  452.         FanOn = 0;
  453.     }
  454.     if(StartFan){                                       // If required, try to start the fan
  455.         if(!FanOn){                                     // Already running?
  456.             FanOn = 1;                                  // No. Switch on fan
  457.             PhaseAngle = STable[9];                     // If just swiched on run it on full speed
  458.             Delay2s();                                  // for a short time
  459.         }
  460.         StartFan = 0;                                   // Clear the flag
  461.     }
  462.     if(FanOn == 0) OffTimer();
  463.     PhaseAngle = STable[Speed];                         // Set the phase angle for the speed
  464.     EECounter = 0;                                      // Update EEPROM
  465. }
  466. /**
  467. Decode the IR data received in NEC format
  468. */
  469. void NECDecoder(void)
  470. {
  471.     static unsigned int IRBitTime, PrevIRTimer;
  472.     #if 0
  473.     static unsigned char Port;
  474.     if((Port ^ GPIO) & IR_PIN_MASK)                     // IR line changed
  475.     {
  476.         *((unsigned char*)&IRTime) = TMR1L;             // Copy the current Timer 1 value (LSB)
  477.         *((unsigned char*)&IRTime + 1) = TMR1H;         // -- do -- (MSB)
  478.         Port = GPIO;
  479.         IRBitTime = IRTime - PrevIRTimer;
  480.         PrevIRTimer = IRTime;
  481.         if(IRBitTime & 0x0800)
  482.             IRState = IR_IDLE;               // Idle for more than 16 ms
  483.         IRRx = 0;
  484.     #else
  485.     if(IRRx)
  486.     {
  487.         IRBitTime = IRTime - PrevIRTimer;
  488.         PrevIRTimer = IRTime;
  489.         if(IRBitTime & 0x0800)
  490.             IRState = IR_IDLE;              // Idle for more than 16 ms
  491.         IRRx = 0;
  492.     #endif
  493.         Error = 0;
  494.         switch(IRState)
  495.         {
  496.             case IR_IDLE:
  497.             if(IsIRDataBitHigh())           // If it is a one, IR starting
  498.                 IRState++;                  // Now is IR_MARK
  499.             IRDataCount = 0;
  500.             IRData._dword = 0;
  501.             break;
  502.  
  503.             case IR_MARK:                   // Now IR Mark just over
  504.             if(IRBitTime < IR_MARK_MIN_TIME)
  505.             {
  506.                 Error = 1;                  // Less than specified mark time
  507.             }
  508.             IRState++;
  509.             break;
  510.  
  511.             case IR_SPACE:                  // Now IR space just over
  512.             if(IRBitTime < IR_SPACE_MIN_TIME)
  513.             {
  514.                 Error = 1;                  // Less than specified space time
  515.             }
  516.             if(IRBitTime < IR_SPACE_MIN_TIME * 2)
  517.             {
  518.                 IRState = IR_REPEAT;        // If it is less than 4.5 ms, it may be a repeat command
  519.                 break;
  520.             }
  521.             IRState++;                      // Space is 4.5 ms, now IR high
  522.             break;
  523.  
  524.             case IR_HIGH:                   // IR high just over, check it
  525.             if(((unsigned char) IRBitTime < MIN_IR_BIT_TIME) || ((unsigned char) IRBitTime > MAX_IR_BIT_TIME))
  526.             {
  527.                 Error = 1;                  // Too short or too long pulse
  528.             }
  529.             IRState++;
  530.             break;
  531.  
  532.             case IR_LOW:                    // IR low just over, check it
  533.             if(((unsigned char) IRBitTime < MIN_IR_BIT_TIME) || ((unsigned char) IRBitTime > MAX_IR_BIT_TIME * 3))
  534.             {
  535.                 Error = 1;                  // Too short or too long pulse
  536.             }
  537.             if((unsigned char) IRBitTime >= MIN_IR_BIT_TIME * 3)
  538.             {
  539.                 AddOneToIRData();           // Longer low time, add a one
  540.             }
  541.             else
  542.             {
  543.                 AddZeroToIRData();          // Short low time add a zero
  544.             }
  545.             IRDataCount++;                  // Increment the counter
  546.             IRState--;                      // Now is IR High
  547.             break;
  548.  
  549.             case IR_REPEAT:                 // In repeat, the 560us IR burst just over, check it now
  550.             if(((unsigned char) IRBitTime < MIN_IR_BIT_TIME) || ((unsigned char) IRBitTime > MAX_IR_BIT_TIME))
  551.             {
  552.                 IRCmdRepeat = 0;
  553.                 Error = 1;
  554.             }
  555.             IRCmdRepeat = 1;
  556.             IRState = IR_IDLE;
  557.             break;
  558.  
  559.         }// switch(IRState)
  560.         if(Error)
  561.         {
  562.             InitIR();
  563.         }
  564.         if(IRDataCount == 32)
  565.         {
  566.             IRNewHit = 1;
  567.             IRState = IR_IDLE;
  568.             IRDataCount = 0;
  569.             //IROff = 0;
  570.         }
  571.         IR05Seconds = 0;
  572.     }// if(IRRx)
  573. }
  574. /**
  575. Initialise IR states
  576. */
  577. void InitIR( void ) // initial IR engine
  578. {
  579.     IRState = IR_IDLE;
  580.     IRNewHit = 0;
  581.     IRCmdRepeat = 0;
  582.     IRDataCount = 0;
  583. }
  584. /**
  585. Read variables  eeprom
  586. */
  587. void GetEEVariables(void)
  588. {
  589.     Speed = eeprom_read(0);
  590.     Time = eeprom_read(1);
  591.     Status._byte = eeprom_read(2);
  592. }
  593. /**
  594. Write to eeprom, the variables
  595. */
  596. void SetEEVariables(void)
  597. {
  598.     // Compare with the eeprom variables and update if necessory
  599.     if(Speed != eeprom_read(0))
  600.         eeprom_write(0, Speed);
  601.     if(EETimeUpdate)                                    // Time may change while running, so only update
  602.     {                                                   // if user make changes
  603.         if(Time != eeprom_read(1))
  604.             eeprom_write(1, Time);
  605.         EETimeUpdate = 0;
  606.     }
  607.     if(Status._byte != eeprom_read(2))
  608.         eeprom_write(2, Status._byte);
  609. }
  610. /**
  611. Create a 2 seconds delay, used to start the fan
  612. */
  613. void Delay2s(void)
  614. {
  615.     unsigned char Count;
  616.     Count = 200;                                        // Make a 200 x 10 ms delay
  617.     while(--Count != 0)
  618.         __delay_ms(10);
  619. }
  620. /**
  621. Delay after a key press. This function retuns after a specified time or when no key pressed down
  622. */
  623. void KeyDelay(void)
  624. {
  625.     unsigned char ms;
  626.     ms = 250;                                           // 500 ms delay
  627.     do
  628.     {
  629.         if(!ANY_KEY)                                    // If key released, return
  630.             break;
  631.         __delay_ms(2);
  632.     }while(--ms != 0);
  633. }
  634.  
  635. void interrupt isr(void)
  636. {
  637.     static unsigned char PortStatus, PortChanges;
  638.     if(GPIF)
  639.     {
  640.         PortChanges = PortStatus;                       // Copy the previous value
  641.         PortStatus = GPIO;                              // Update PortStatus
  642.         GPIF = 0;                                       // Clear interrrupt
  643.         PortChanges ^= PortStatus;                      // Find the differences
  644.         if(PortChanges & ZC_PIN_MASK)                   // Zero cross
  645.         {
  646.             TMR0 = PhaseAngle;                          // Phase angle is controlled via TMR0, on interrupt it trigger
  647.             if(FanOn && (PhaseAngle >= STable[9])){     // For full speed hold trigger  now, and TMR0 interrupt (delayed
  648.                 TriacOn();                              // to reach TRIAC holding current) clear the trigger
  649.             }
  650.             Ticks++;                                    // Ticks @ 10 ms
  651.             {
  652.             #asm
  653.             INCFSZ      _KeyCount,W                     // Inc Key Count, but not beyond 255
  654.             MOVWF       _KeyCount
  655.             CLRW                                        // Clear W
  656.             BTFSS       SW_UP                           // Up Key pressed?
  657.             MOVLW       0x81                            // Y. Load W with 0x81
  658.             BTFSS       SW_DN                           // Down Key pressed?
  659.             MOVLW       0x82                            // Y. Load W with 0x82
  660.             MOVWF       _Key                            // Save W to Key
  661.             BTFSS       _Key,7                          // Has any key pressed?
  662.             CLRF        _KeyCount                       // N. Clear the counter
  663.             #endasm
  664.             }
  665.         }//if(PortChanges & ZC_PIN_MASK)
  666.         if(PortChanges & IR_PIN_MASK)                   // IR line changed
  667.         {
  668.             *((unsigned char*)&IRTime) = TMR1L;         // Copy the current Timer 1 value (LSB)
  669.             *((unsigned char*)&IRTime + 1) = TMR1H;     // -- do -- (MSB)
  670.             IRRx = 1;
  671.         }
  672.     }
  673.     if(T0IF)                                            // Interrupt depends on phase angle (TMR0 is set by phase angle)
  674.     {
  675.         if(FanOn){
  676.             TriacOn();                                  // Triac triggered
  677.         }
  678.         T0IF = 0;                                       // Clear flag
  679.         NOP();
  680.         NOP();
  681.         NOP();
  682.         NOP();
  683.         TriacOff();                                     // Triac off, beacuse already triggered
  684.     }//if(T0IF)
  685.  
  686.     if(TMR1IF)                                          // @ 524ms; This interrupt is not set, but polled
  687.     {                                                   // with other interrupts
  688.         TMR1IF = 0;
  689. #ifdef  TIMER_ENABLE
  690.         if(TimerRunning && (--TimeCounter == 0))        // If timer running, decrement counter
  691.         {
  692.             TimeCounter = TIME_COUNT;                   // Reload counter
  693.             if(--Time == 0)                             // The time expired, switch off fan and counter
  694.             {
  695.                 OffTimer();                             // Switch off timer
  696.                 FanOn = 0;
  697.             }
  698.         }
  699. #endif
  700.         {
  701.         #asm
  702.         INCFSZ  _EECounter,W                            // Inc eeprom timer, but not beyond 255
  703.         MOVWF   _EECounter
  704.         #endasm
  705.         }
  706.         if(EECounter == 8)                              // After 4 seconds since clearing the counter
  707.             EEPromWrite = 1;                            // set eeprom write flag
  708.         if(IR05Seconds)                                 // After 0.5 seconds of inactivity
  709.             IRCmdRepeat = 0;                            // clear the repeat command
  710.         IR05Seconds = 1;
  711.     }//if(TMR1IF)
  712. }

Again Thank you
A hozzászólás módosítva: Jún 24, 2022
(#) Bakman válasza Broy hozzászólására (») Jún 22, 2022
timer1, ha nem használod, elvileg nem szólhat bele. A T1CON regiszter értéke Reset után 0x00. Ha használod, akkor bit 7-6 ne legyen 0b10, valamint bit 3 ne legyen 0b1.

Az RA5 elvileg nem lehet analóg bemenet, így azt a bitet át sem lehet állítani. Már csak az RA5-re vonatkozó regiszter marad, ami Reset után egyébként is 0b1:

TRISAbits.TRISA5=1;

Ha nem valamilyen hipertitkor projekt, töltsd fel a kódot, több szem többet lát.
(#) Elektro.on válasza Elektro.on hozzászólására (») Jún 22, 2022
Ezen kívűl a timer1 bemenete is lehet az RA5. Adatlap 172. oldaltól olvasd el.
(#) Naresh Jain válasza Hp41C hozzászólására (») Jún 21, 2022
Dear Sir, I need your help again, I have the codes to control the traic to control the speed of fan using 16F676 schematic 1 working successfully and codes attached below, now I want some amendment in codes to toggle control one more triac on another port as schematic 2 attached below, Please help me
  1. /********************************************************************************
  2. *                   Fan Controller                                              *
  3. *                                                                               *
  4. *   This program is free software: you can redistribute it and/or modify        *
  5. *   it under the terms of the GNU General Public License as published by        *
  6. *   the Free Software Foundation, either version 3 of the License, or           *
  7. *   (at your option) any later version.                                         *
  8. *                                                                               *
  9. *   This program is distributed in the hope that it will be useful,             *
  10. *   but WITHOUT ANY WARRANTY; without even the implied warranty of              *
  11. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
  12. *   GNU General Public License for more details.                                *
  13. *                                                                               *
  14. *   You should have received a copy of the GNU General Public License           *
  15. *   along with this program.  If not, see <https://www.gnu.org/licenses/>.      *
  16. *                                                                               *
  17. *       Date            : Friday, 21 January 2011                               *
  18. *       Author          : C.V.Niras/VU3CNS                                      *
  19. *       Copyright       : (C) 2010 C. V. Niras                                  *
  20. *       Email           : cvniras@gmail.com                                     *
  21. *       Processor       : 12F675                                                *
  22. *       First Release   : 23/01/2011                                            *
  23. *       Ver             : 0.7                                                   *
  24. *   Change History:                                                             *
  25. *       Rev     Date        Description                                         *
  26. *       0.5     06/03/2011  First stable release                                *
  27. *       0.6     08/03/2011  Bug fixed - Can't swich on by CH+, when turned      *
  28. *                           off by set speed to 0                               *
  29. *       0.7     14/06/2011  Trigger off delayed for full speed (low firing      *
  30. *                           angle) to reach the TRIAC latch current             *
  31. *                                                                               *
  32. *********************************************************************************/
  33. #include <pic.h>
  34. #include "type_def.h"
  35. #include "remote_commands.h"
  36.  
  37. #if defined _12F675
  38. __CONFIG(WDTDIS & MCLRDIS & INTIO & BORDIS & UNPROTECT & PWRTEN);
  39.  
  40. #define IsIRDataBitHigh()   GPIO3 == 0  // Inverted logic
  41. #define SW_UP           _GPIO,0         // Up switch
  42. #define SW_DN           _GPIO,2         // Down switch
  43. #define LEDOn()         GPIO1 = 1       // LED
  44. #define LEDOff()        GPIO1 = 0
  45. #define TriacOn()       GPIO5 = 0       // Triac
  46. #define TriacOff()      GPIObits.GPIO5 = 1
  47. #define TRIAC           GPIO5           // Triac pin
  48. #endif  
  49.  
  50. #if defined _16F676
  51. __CONFIG(WDTDIS & MCLRDIS & INTOSCIO & BORDIS & UNPROTECT & PWRTEN);
  52.  
  53. #define GPIO PORTA
  54. #define TRISIO TRISA
  55. #define GPIF RAIF
  56. #define GPIE RAIE
  57.  
  58. #define IsIRDataBitHigh()   PORTAbits.RA3 == 0  // Inverted logic
  59. #define SW_UP           _PORTA,0         // Up switch
  60. #define SW_DN           _PORTA,2         // Down switch
  61. #define LEDOn()         PORTAbits.RA1 = 1       // LED
  62. #define LEDOff()        PORTAbits.RA1 = 0
  63. #define TriacOn()       PORTAbits.RA5 = 0       // Triac
  64. #define TriacOff()      PORTAbits.RA5 = 1
  65. #define TRIAC           PORTAbits.RA5           // Triac pin
  66. #endif
  67.  
  68. __EEPROM_DATA(5, 1, 1, 255, 255, 255, 255, 255);
  69.  
  70. __IDLOC7('0','.','7','B');
  71.  
  72. #define TIMER_ENABLE                    // Enable timer
  73. // -- Chip Configurations --
  74. #define _XTAL_FREQ      4000000
  75. #define ZC_PIN_MASK     0x10            // Pin used for zero cross detection
  76. #define IR_PIN_MASK     0x08            // IR sensor output
  77. #define TIME_COUNT      6866            // Number of timer1 overflows in an hour
  78. #define ANY_KEY         Key & 0x80
  79. #define UP_KEY          Key & 0x01
  80. #define DN_KEY          Key & 0x02
  81.  
  82. // Timer 1 is the time base, 1 bit time = 8us; the NEC physical bit time is 560us = 70 Timer 1
  83. // The following time are set with a +/- 20% tolerance
  84.  
  85. #define IR_MARK_MIN_TIME    787
  86. #define IR_SPACE_MIN_TIME   219
  87. #define MIN_IR_BIT_TIME     56
  88. #define MAX_IR_BIT_TIME     84
  89.  
  90. // -- End of Chip Configurations --
  91.  
  92. #define IRRx            Flag.b0         // New IR bit received
  93. #define IRNewHit        Flag.b1         // A new IR command received
  94. #define Error           Flag.b2         // General error flag
  95. #define IRCmdRepeat     Flag.b3         // A IR repeat command received
  96. #define StartFan        Flag.b4         // Indicate to start the fan
  97. #define EEPromWrite     Flag.b5         // Indicate to write to EEPROM
  98. #define UnknownCmd      Flag.b6         // Unused IR command
  99.  
  100. #define EETimeUpdate    Flag1.b0        // Indicate to update time in eeprom
  101. #define IR05Seconds     Flag1.b1        // A 0.5 seconds of IR inactivity, used to clear IR command repeate flag
  102. #define ClearLED        Flag1.b2        // Need to turn off LED
  103.  
  104. #define FanOn           Status.b0       // Fan Running
  105. #define TimerRunning    Status.b1       // Timer Running
  106.  
  107. #define AddZeroToIRData()   IRData._dword >>= 1                                 // Add a 0 bit to IR data
  108. #define AddOneToIRData()    IRData._dword >>= 1; IRData._dword |= 0x80000000    // Add a 1 bit to IR data
  109.  
  110. // NEC IR protocol states
  111. typedef enum _NEC_STATES
  112. {
  113.     IR_IDLE,
  114.     IR_MARK,
  115.     IR_SPACE,
  116.     IR_HIGH,
  117.     IR_LOW,
  118.     IR_REPEAT
  119. } NEC_STATES;
  120.  
  121. // V A R I A B L E S
  122. //const unsigned char STable[10] = {0, 157, 165, 173, 181, 188, 195, 205, 216, 252};
  123. // Modified to latch low power (load) fans  low firing angle (on full speed)
  124. const unsigned char STable[10] = {0, 157, 165, 173, 181, 188, 195, 205, 216, 234};
  125. near volatile BYTE Flag, Flag1, Status;
  126. near NEC_STATES IRState;
  127. unsigned char IRDataCount, PhaseAngle, Speed, Time, Count;
  128. volatile near unsigned char EECounter, Ticks, Key, KeyCount;
  129. volatile unsigned int IRTime, TimeCounter;
  130. DWORD IRData;
  131.  
  132. // F U N C T I O N   P R O T O T Y P E S
  133. void IRHandler(void);
  134. void NECDecoder(void);
  135. void InitIR(void);
  136. void SetSpeed(void);
  137. void OffTimer(void);
  138. void OnTimer(void);
  139. void SetTimer(void);
  140. void GetEEVariables(void);
  141. void SetEEVariables(void);
  142. void KeyDelay(void);
  143. void interrupt isr(void);
  144. void Delay2s(void);
  145.  
  146. // M A I N
  147. void main(void)
  148. {
  149.     #asm
  150.         call    0x3ff
  151.                 bsf             STATUS, 5
  152.                 movwf   OSCCAL & 0x7f
  153.                 bcf             STATUS, 5
  154.     #endasm
  155.     GPIO    = 0;                                        // Clear PORT
  156.     TriacOff();                                         // Triac off
  157.     TRISIO  = ZC_PIN_MASK | IR_PIN_MASK | 0x05;         // IR, Zero cross and swiches
  158.     WPU     = 0x05;                                     // Weak pull up enabled for wwitches
  159.     IOC     = ZC_PIN_MASK | IR_PIN_MASK;                // Interrupt on change is enabled for GPIO2, GPIO4
  160.     ANSEL   = 0x00;                                     // All are digital i/o
  161.     CMCON   = 0x07;                                     // Comparators off
  162.     INTCON  = 0x68;                                     // Enable PEIE, Timer0, Port change interrupts
  163.     OPTION_REG  = 0x05;                                     // INT falling edge, Prescaler 1:64
  164.     T1CON   = 0x31;                                     // Prescaler 1:8, internal clk, TMR1ON
  165.     LEDOn();
  166.     Flag._byte = 0;                                     // Initialise flags and variables
  167.     Flag1._byte = 0;
  168.     InitIR();
  169.     GetEEVariables();                                   // Read variables  eeprom
  170.     IRState = IR_IDLE;                                  // Init IR state
  171.     if(FanOn)
  172.         StartFan = 1;
  173.     FanOn = 0;                                          // This created a fresh start
  174. #ifdef  TIMER_ENABLE
  175.     if(TimerRunning)                                    // If already started, set the time again
  176.         SetTimer();
  177. #endif
  178.     GIE = 1;                                            // Enable interrupts
  179.     SetSpeed();                                         // Set the speed
  180.     LEDOff();                                           // Turn off LED
  181.     Count = Time << 1;                                  // Count = Time * 2, i.e turn on/off
  182.     Ticks = 0;
  183.     do
  184.     {
  185.         NECDecoder();                                   // Decode NEC formatted IR data
  186.         if(IRNewHit)                                    // Is any new data?
  187.         {
  188.             IRNewHit = 0;                               // Y. Clear flag
  189.             IRHandler();                                // Do the command
  190.         }
  191.         if(IRCmdRepeat)                                 // As long as the repeat command present
  192.         {                                               // do not turn of LED
  193.             IRCmdRepeat = 0;
  194.             Ticks = 0;                                  // for the same clear Ticks
  195.         }
  196.         if(EEPromWrite)
  197.         {
  198.             EEPromWrite = 0;                            // Clear eeprom update flag
  199.             SetEEVariables();                           // Write variables if necessory
  200.         }
  201.         if(ClearLED)
  202.         {
  203.             if(Ticks & 0x20)                            // If remote command received, turn off LED after only
  204.             {                                           // few ms (~320ms)
  205.                 ClearLED = 0;
  206.                 LEDOff();
  207.             }
  208.         }
  209. #ifdef  TIMER_ENABLE
  210.         else if(TimerRunning && (Ticks & 0x40))         // If timer is running and a short time expired (640ms)
  211.         {                                               // used to blink LED to show the time remaining
  212.             if(Count == 0xF7)                           // Reload counter to show the time, after a certain time gap
  213.             {
  214.                 Count = Time << 1;                      // Count = Time * 2, i.e turn on/off
  215.                 LEDOff();                               // Ensure LED is off
  216.             }
  217.             if(!(--Count & 0x80))                       // Blinks the LED till counter become -ve
  218.             {
  219.                 if(Count & 0x01) {                      // On odd numbers in counter LED on
  220.                     LEDOn();
  221.                 }
  222.                 if(!(Count & 0x01)) {                   // For even numbers LED off
  223.                     LEDOff();
  224.                 }
  225.             }
  226.             Ticks = 0;                                  // Reset ticks
  227.         }//if(TimerRunning && (Ticks & 0x40))
  228. #endif
  229.  
  230.         if(KeyCount >= 4)                               // Has key pressed for a short time?
  231.         {
  232.             if(UP_KEY)                                  // Y. Check for Up key press
  233.             {
  234.                 StartFan = 1;                           // Y. Up key pressed, inc the speed
  235.                 Speed++;
  236.             }
  237.             if(DN_KEY)                                  // Check for a down key press
  238.             {
  239.                 StartFan = 1;                           // Y. Down key pressed, decrement the speed
  240.                 Speed--;
  241.             }
  242.             if(StartFan)                                // If any key pressed, do the action
  243.             {
  244.                 SetSpeed();
  245.                 KeyDelay();                             // Give a delay beore the next check
  246.             }
  247.         }
  248.     }while(1);
  249. }// main
  250.  
  251. // F U N C T I O N S
  252. /**
  253. The function is used to decode IR commands and make changes required
  254. */
  255. void IRHandler(void)
  256. {
  257.     if(!(IRData.byte0 ^ IRData.byte1) == 0)             // Address and its compliment match
  258.      {
  259.          if(IRData.byte0 == 0)                          // Address  is zero
  260.          {
  261.              if(!(IRData.byte2 ^ IRData.byte3) == 0)    // Command and its compliment match
  262.              {
  263.                 UnknownCmd = 0;
  264.                 switch(IRData.byte2)
  265.                 {
  266.                     case VOL_PLUS:
  267.                     StartFan = 1;
  268.                     Speed++;
  269.                     break;
  270.                     case VOL_MINUS:
  271.                     StartFan = 1;
  272.                     Speed--;
  273.                     break;
  274.                     case DIGIT0:
  275.                     Speed = 0;
  276.                     OffTimer();
  277.                     break;
  278.                     case DIGIT1:
  279.                     StartFan = 1;
  280.                     Speed = 1;
  281.                     break;
  282.                     case DIGIT2:
  283.                     StartFan = 1;
  284.                     Speed = 2;
  285.                     break;
  286.                     case DIGIT3:
  287.                     StartFan = 1;
  288.                     Speed = 3;
  289.                     break;
  290.                     case DIGIT4:
  291.                     StartFan = 1;
  292.                     Speed = 4;
  293.                     break;
  294.                     case DIGIT5:
  295.                     StartFan = 1;
  296.                     Speed = 5;
  297.                     break;
  298.                     case DIGIT6:
  299.                     StartFan = 1;
  300.                     Speed = 6;
  301.                     break;
  302.                     case DIGIT7:
  303.                     StartFan = 1;
  304.                     Speed = 7;
  305.                     break;
  306.                     case DIGIT8:
  307.                     StartFan = 1;
  308.                     Speed = 8;
  309.                     break;
  310.                     case DIGIT9:
  311.                     StartFan = 1;
  312.                     Speed = 9;
  313.                     break;
  314.  
  315.                     case CH_MINUS:
  316.                     FanOn = 0;
  317.                     OffTimer();
  318.                     break;
  319.  
  320.                     case CH_PLUS:
  321.                     if(Speed == 0) Speed++;
  322.                     StartFan = 1;
  323.                     break;
  324.  
  325.                     case PREV:
  326.                     if(FanOn)   Time--;
  327.                     SetTimer();
  328.                     break;
  329.  
  330.                     case NEXT:
  331.                     if(FanOn)   Time++;
  332.                     SetTimer();
  333.                     break;
  334.  
  335.                     case EQ:
  336.                     OffTimer();
  337.                     break;
  338.  
  339.                     case PLAY:
  340.                     OnTimer();
  341.                     break;
  342.  
  343.                     default:
  344.                     UnknownCmd = 1;
  345.                     break;
  346.                 }
  347.                 if(!UnknownCmd){
  348.                     LEDOn();                // A new command received
  349.                     ClearLED = 1;           // Clear LED after a little time
  350.                     Ticks = 0;              // Reset timer ticks
  351.                     SetSpeed();
  352.                 }
  353.              }// if((IRData.byte0 ^ IRData.byte1) == 0)
  354.          }// if(IRData.byte3 == 0)
  355.      }//if((IRData.byte3 ^ IRData.byte2) == 0)
  356. }
  357. /**
  358. Off the timer, without changing previous set time
  359. */
  360. void OffTimer(void)
  361. {
  362.     TimerRunning = 0;                                   // Turn off timer
  363.     Time = eeprom_read(1);                              // Read the eeprom, value
  364.     EETimeUpdate = 1;                                   // Update time in the eeprom
  365.     EECounter = 0;                                      // Clear the eeprom counter to update eeprom
  366. }
  367. /**
  368. On timer, start with the previous set time, if the timer is not running
  369. */
  370. void OnTimer(void)
  371. {
  372.     if(FanOn == 1)                                      // Only start Timer when fan on
  373.     {
  374.         if(!TimerRunning)                               // Nothing to do if already started
  375.         {
  376.             TimerRunning = 1;                           // Start the timer
  377.             Time = eeprom_read(1);                      // Get time  eeprom
  378.             if(Time == 0)                               // If zero, switch on timer with a non zero value, i.e one hour
  379.                 Time++;
  380.             TimeCounter = TIME_COUNT;                   // Reload the counter
  381.             EETimeUpdate = 1;                           // Update time in the eeprom
  382.             EECounter = 0;                              // Clear the eeprom counter to update eeprom
  383.         }
  384.     }
  385. }
  386. /**
  387. Set the counters for the timer. When the counter reached zero, the fan will be turned off
  388. If the timer not running, it reload time value with the last saved value  the eeprom,
  389. otherwise adjust counters as required, and clear eeprom counter to update time value in the
  390. eeprom, for the same it set a EETimeUpdate flag
  391. */
  392. void SetTimer(void)
  393. {
  394.     if(Time & 0x80)                                     // A neg, so clear it
  395.         Time = 0;
  396.     if(Time > 8)
  397.         Time = 8;                                       // Max 8 hours
  398.     if(FanOn == 0)                                      // Nothing to do if fan is not running
  399.         return;
  400.     if(!TimerRunning && (Time != 0)) {                  // If decrementing, and time reached zero, on further
  401.         Time = eeprom_read(1);                          // decrements never start the timer, only start on
  402.         TimerRunning = 1;                               // increments, i.e when time not zero.
  403.         if(Time == 0)                                   // If zero, start with a non zero value
  404.             Time++;                                     // i.e. set to one
  405.     }
  406.     if(Time == 0)                                       // Stop timer, if time is zero
  407.         TimerRunning = 0;
  408.     TimeCounter = TIME_COUNT;                           //
  409.     EETimeUpdate = 1;                                   // Update time in the eeprom
  410.     EECounter = 0;                                      // Clear the eeprom counter to update eeprom
  411. }
  412. /**
  413. Set the speed and update phase angle for a given speed. If start fan flag is set, and fan not running
  414. it starts fan will full speed for a second, then changes to ed speed.
  415. */
  416. void SetSpeed(void)
  417. {
  418.     if(Speed & 0x80)                                    // A neg, keep it as zero
  419.         Speed = 0;
  420.     if(Speed >= 10)                                     // Reach the max.
  421.         Speed = 9;
  422.     if(Speed == 0){
  423.         StartFan = 0;                                   // For a zero speed, switch off
  424.         FanOn = 0;
  425.     }
  426.     if(StartFan){                                       // If required, try to start the fan
  427.         if(!FanOn){                                     // Already running?
  428.             FanOn = 1;                                  // No. Switch on fan
  429.             PhaseAngle = STable[9];                     // If just swiched on run it on full speed
  430.             Delay2s();                                  // for a short time
  431.         }
  432.         StartFan = 0;                                   // Clear the flag
  433.     }
  434.     if(FanOn == 0) OffTimer();
  435.     PhaseAngle = STable[Speed];                         // Set the phase angle for the speed
  436.     EECounter = 0;                                      // Update EEPROM
  437. }
  438. /**
  439. Decode the IR data received in NEC format
  440. */
  441. void NECDecoder(void)
  442. {
  443.     static unsigned int IRBitTime, PrevIRTimer;
  444.     #if 0
  445.     static unsigned char Port;
  446.     if((Port ^ GPIO) & IR_PIN_MASK)                     // IR line changed
  447.     {
  448.         *((unsigned char*)&IRTime) = TMR1L;             // Copy the current Timer 1 value (LSB)
  449.         *((unsigned char*)&IRTime + 1) = TMR1H;         // -- do -- (MSB)
  450.         Port = GPIO;
  451.         IRBitTime = IRTime - PrevIRTimer;
  452.         PrevIRTimer = IRTime;
  453.         if(IRBitTime & 0x0800)
  454.             IRState = IR_IDLE;               // Idle for more than 16 ms
  455.         IRRx = 0;
  456.     #else
  457.     if(IRRx)
  458.     {
  459.         IRBitTime = IRTime - PrevIRTimer;
  460.         PrevIRTimer = IRTime;
  461.         if(IRBitTime & 0x0800)
  462.             IRState = IR_IDLE;              // Idle for more than 16 ms
  463.         IRRx = 0;
  464.     #endif
  465.         Error = 0;
  466.         switch(IRState)
  467.         {
  468.             case IR_IDLE:
  469.             if(IsIRDataBitHigh())           // If it is a one, IR starting
  470.                 IRState++;                  // Now is IR_MARK
  471.             IRDataCount = 0;
  472.             IRData._dword = 0;
  473.             break;
  474.  
  475.             case IR_MARK:                   // Now IR Mark just over
  476.             if(IRBitTime < IR_MARK_MIN_TIME)
  477.             {
  478.                 Error = 1;                  // Less than specified mark time
  479.             }
  480.             IRState++;
  481.             break;
  482.  
  483.             case IR_SPACE:                  // Now IR space just over
  484.             if(IRBitTime < IR_SPACE_MIN_TIME)
  485.             {
  486.                 Error = 1;                  // Less than specified space time
  487.             }
  488.             if(IRBitTime < IR_SPACE_MIN_TIME * 2)
  489.             {
  490.                 IRState = IR_REPEAT;        // If it is less than 4.5 ms, it may be a repeat command
  491.                 break;
  492.             }
  493.             IRState++;                      // Space is 4.5 ms, now IR high
  494.             break;
  495.  
  496.             case IR_HIGH:                   // IR high just over, check it
  497.             if(((unsigned char) IRBitTime < MIN_IR_BIT_TIME) || ((unsigned char) IRBitTime > MAX_IR_BIT_TIME))
  498.             {
  499.                 Error = 1;                  // Too short or too long pulse
  500.             }
  501.             IRState++;
  502.             break;
  503.  
  504.             case IR_LOW:                    // IR low just over, check it
  505.             if(((unsigned char) IRBitTime < MIN_IR_BIT_TIME) || ((unsigned char) IRBitTime > MAX_IR_BIT_TIME * 3))
  506.             {
  507.                 Error = 1;                  // Too short or too long pulse
  508.             }
  509.             if((unsigned char) IRBitTime >= MIN_IR_BIT_TIME * 3)
  510.             {
  511.                 AddOneToIRData();           // Longer low time, add a one
  512.             }
  513.             else
  514.             {
  515.                 AddZeroToIRData();          // Short low time add a zero
  516.             }
  517.             IRDataCount++;                  // Increment the counter
  518.             IRState--;                      // Now is IR High
  519.             break;
  520.  
  521.             case IR_REPEAT:                 // In repeat, the 560us IR burst just over, check it now
  522.             if(((unsigned char) IRBitTime < MIN_IR_BIT_TIME) || ((unsigned char) IRBitTime > MAX_IR_BIT_TIME))
  523.             {
  524.                 IRCmdRepeat = 0;
  525.                 Error = 1;
  526.             }
  527.             IRCmdRepeat = 1;
  528.             IRState = IR_IDLE;
  529.             break;
  530.  
  531.         }// switch(IRState)
  532.         if(Error)
  533.         {
  534.             InitIR();
  535.         }
  536.         if(IRDataCount == 32)
  537.         {
  538.             IRNewHit = 1;
  539.             IRState = IR_IDLE;
  540.             IRDataCount = 0;
  541.             //IROff = 0;
  542.         }
  543.         IR05Seconds = 0;
  544.     }// if(IRRx)
  545. }
  546. /**
  547. Initialise IR states
  548. */
  549. void InitIR( void ) // initial IR engine
  550. {
  551.     IRState = IR_IDLE;
  552.     IRNewHit = 0;
  553.     IRCmdRepeat = 0;
  554.     IRDataCount = 0;
  555. }
  556. /**
  557. Read variables  eeprom
  558. */
  559. void GetEEVariables(void)
  560. {
  561.     Speed = eeprom_read(0);
  562.     Time = eeprom_read(1);
  563.     Status._byte = eeprom_read(2);
  564. }
  565. /**
  566. Write to eeprom, the variables
  567. */
  568. void SetEEVariables(void)
  569. {
  570.     // Compare with the eeprom variables and update if necessory
  571.     if(Speed != eeprom_read(0))
  572.         eeprom_write(0, Speed);
  573.     if(EETimeUpdate)                                    // Time may change while running, so only update
  574.     {                                                   // if user make changes
  575.         if(Time != eeprom_read(1))
  576.             eeprom_write(1, Time);
  577.         EETimeUpdate = 0;
  578.     }
  579.     if(Status._byte != eeprom_read(2))
  580.         eeprom_write(2, Status._byte);
  581. }
  582. /**
  583. Create a 2 seconds delay, used to start the fan
  584. */
  585. void Delay2s(void)
  586. {
  587.     unsigned char Count;
  588.     Count = 200;                                        // Make a 200 x 10 ms delay
  589.     while(--Count != 0)
  590.         __delay_ms(10);
  591. }
  592. /**
  593. Delay after a key press. This function retuns after a specified time or when no key pressed down
  594. */
  595. void KeyDelay(void)
  596. {
  597.     unsigned char ms;
  598.     ms = 250;                                           // 500 ms delay
  599.     do
  600.     {
  601.         if(!ANY_KEY)                                    // If key released, return
  602.             break;
  603.         __delay_ms(2);
  604.     }while(--ms != 0);
  605. }
  606.  
  607. void interrupt isr(void)
  608. {
  609.     static unsigned char PortStatus, PortChanges;
  610.     if(GPIF)
  611.     {
  612.         PortChanges = PortStatus;                       // Copy the previous value
  613.         PortStatus = GPIO;                              // Update PortStatus
  614.         GPIF = 0;                                       // Clear interrrupt
  615.         PortChanges ^= PortStatus;                      // Find the differences
  616.         if(PortChanges & ZC_PIN_MASK)                   // Zero cross
  617.         {
  618.             TMR0 = PhaseAngle;                          // Phase angle is controlled via TMR0, on interrupt it trigger
  619.             if(FanOn && (PhaseAngle >= STable[9])){     // For full speed hold trigger  now, and TMR0 interrupt (delayed
  620.                 TriacOn();                              // to reach TRIAC holding current) clear the trigger
  621.             }
  622.             Ticks++;                                    // Ticks @ 10 ms
  623.             {
  624.             #asm
  625.             INCFSZ      _KeyCount,W                     // Inc Key Count, but not beyond 255
  626.             MOVWF       _KeyCount
  627.             CLRW                                        // Clear W
  628.             BTFSS       SW_UP                           // Up Key pressed?
  629.             MOVLW       0x81                            // Y. Load W with 0x81
  630.             BTFSS       SW_DN                           // Down Key pressed?
  631.             MOVLW       0x82                            // Y. Load W with 0x82
  632.             MOVWF       _Key                            // Save W to Key
  633.             BTFSS       _Key,7                          // Has any key pressed?
  634.             CLRF        _KeyCount                       // N. Clear the counter
  635.             #endasm
  636.             }
  637.         }//if(PortChanges & ZC_PIN_MASK)
  638.         if(PortChanges & IR_PIN_MASK)                   // IR line changed
  639.         {
  640.             *((unsigned char*)&IRTime) = TMR1L;         // Copy the current Timer 1 value (LSB)
  641.             *((unsigned char*)&IRTime + 1) = TMR1H;     // -- do -- (MSB)
  642.             IRRx = 1;
  643.         }
  644.     }
  645.     if(T0IF)                                            // Interrupt depends on phase angle (TMR0 is set by phase angle)
  646.     {
  647.         if(FanOn){
  648.             TriacOn();                                  // Triac triggered
  649.         }
  650.         T0IF = 0;                                       // Clear flag
  651.         NOP();
  652.         NOP();
  653.         NOP();
  654.         NOP();
  655.         TriacOff();                                     // Triac off, beacuse already triggered
  656.     }//if(T0IF)
  657.  
  658.     if(TMR1IF)                                          // @ 524ms; This interrupt is not set, but polled
  659.     {                                                   // with other interrupts
  660.         TMR1IF = 0;
  661. #ifdef  TIMER_ENABLE
  662.         if(TimerRunning && (--TimeCounter == 0))        // If timer running, decrement counter
  663.         {
  664.             TimeCounter = TIME_COUNT;                   // Reload counter
  665.             if(--Time == 0)                             // The time expired, switch off fan and counter
  666.             {
  667.                 OffTimer();                             // Switch off timer
  668.                 FanOn = 0;
  669.             }
  670.         }
  671. #endif
  672.         {
  673.         #asm
  674.         INCFSZ  _EECounter,W                            // Inc eeprom timer, but not beyond 255
  675.         MOVWF   _EECounter
  676.         #endasm
  677.         }
  678.         if(EECounter == 8)                              // After 4 seconds since clearing the counter
  679.             EEPromWrite = 1;                            // set eeprom write flag
  680.         if(IR05Seconds)                                 // After 0.5 seconds of inactivity
  681.             IRCmdRepeat = 0;                            // clear the repeat command
  682.         IR05Seconds = 1;
  683.     }//if(TMR1IF)
  684. }
what will change in codes:
(#) Broy hozzászólása Jún 14, 2022
Sziasztok!
A segítségeteket szeretném kérni. Van egy low pin count boardom és abba tettem egy 16F1823-at. Egy éve még teljesen jól tudtam programozni a rendszert, de most újra elővettem és bármit csinálok (pl. üres főciklus, üres timer1), a beírás után a négy LED-ből (RC0-RC3) az RC0-ra és az RC2-re kötött LEDek felgyulladnak és úgy is maradnak, a másik kettő nem ég (ez a helyes állapot). Ha bármilyen programot égetek be, ugyanezt tapasztalom. Természetesen a regisztereket megfelelően beállítom és törlöm (régebben nem volt a programmal semmi gond, csak a teszt miatt töröltem ki a végrehajtó részeket). Egy másik 1823-at beletettem, ugyanazt az eredményt kaptam. A belső RC oszcillátor frekvenciája 4 MHz.
MPLAB X IDE V6-ot használok, de az 5.4-el is ugyanez volt. Az MPLAB nem ír hibát, minden rendben lezajlik. A használt számítógép is ugyanaz. Az égető egy PICKIT3.
Mivel tesztelhetném, hogy hol lehet a gond?
(#) spenyo hozzászólása Ápr 4, 2022
Nos kipróbáltam ...
A timer1 indítása (setup_timer_) után kell átállítani az RD16 bitet a T1CON regiszterben és azután már működik a timer1L és timer1H regiszter irkafirkálása a régi módon.
Sajna ezt minden timer1 indítás után el kell játszani...
A buffer regiszter nem elérhető közvetlenül a felhasználó számára, ezért ilyenkor csak a set_timer(xx) utasítás marad a "H" regiszterbe íráshoz - ez egyszerre írja az "L" és a "H" regisztert is.
Sajna ez nekem nem jó, mert már valamennyi érték beleketyeg az "L" regiszterbe amikor nekem írni kell/vagy nem a "H" regisztert.
Tehát marad az indításonkénti átállítási procedúra ...
Köszönöm az infókat .. a segítségetek megoldotta a problémát.
(#) helektro válasza spenyo hozzászólására (») Ápr 4, 2022
A 8 bites PIC-ek timer-ének 16 bites mód haszálatakor a felső byte történő írása két részletben történik meg. A pdf 19.6 timer1 16-Bit Read/Write Mode (és a Figure 19-3. timer1 16-Bit Read/Write Mode Block Diagram ábra) leírja, ill. szemlélteti ezt. Az MSB ténylegesen csak akkor íródik be, ha utána az LSB-t is írod.
Következő: »»   1 / 41
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