Fórum témák

» Több friss téma
Fórum
Keresés
Lapozás: OK   2 / 42
(#) 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.
(#) spenyo hozzászólása Ápr 4, 2022
Sziasztok,
Tudna valaki segíteni.
A PIC18F47Q10 típusú kontrollerrel gyűlt meg a bajom. A timer1 16bites számláló legfelső bitjét kéne "1"-be állítani, de valamiért nem működnek az eddigi megszokott dolgok (bit_set(timer1H, 7), #bit, ..) csak a set_timer1(32768); és nem tudom mi a gond.
Az adatlap szerint - ami új ismeret - eleve be lehet állítani, hogy 8 vagy 16 bites működési módja legyen (RD1 bit) a számlálónak. Lehet, hogy ez a gond, mert hiába próbálom beállítani a 0x0FCD regiszter (timer1H) 7. bitjét, az sehogy se sikerül...
Ha valaki tud használható segítséget adni azt nagyon megköszönném...
Köszönöm.
(#) KoblogPerGyok hozzászólása Márc 14, 2022
Kiegészítés:

A PWM kitöltési tényezőjét a Timer3 interrup-jában állítom. A Timer 3 jó értéket ad.

  1.   void PWM_2_duty(unsigned char P2)
  2.      {
  3.  
  4.          //P1DC1 = (2UL*P1TPER+2)*PWM_DUTY/100;
  5.          P2DC1 = (unsigned long int)P2;
  6.       }
  7.  
  8.       void PWM_2_init(unsigned long int Fcy, unsigned long int PWM_2_Frekvencia){
  9.          //setup output pins
  10.          LATBbits.LATB8=0;
  11.          TRISBbits.TRISB8 = 0;
  12.  
  13.          //setup PWM ports
  14.          PWM2CON1 = 0;                //clear all bits (use defaults)
  15.          PWM2CON1bits.PMOD1 = 0;     //PWM1Ly,PWM1Hy are in independent running mode
  16.          PWM2CON1bits.PEN1L = 0;     //PWM1L1 NORMAL I/O
  17.          PWM2CON1bits.PEN1H = 1;     //PWM1H1 PWM OUTPUT
  18.  
  19.          //PWM mode and prescaler
  20.          //PWM1, MOTORS 0,1,2    
  21.          P2TCON = 0;                    //clear all bits (use defaults)
  22.          P2TCONbits.PTMOD = 0b00;    //Free-runing mode
  23. //         P1TCONbits.PTCKPS = 0b11;    // 1:64 prescaler
  24.          P2TCONbits.PTCKPS = 0b00;    // 1:1 prescaler
  25.  
  26.          //setup desired frequency by setting period for 1:64 prescaler
  27. //         P1TPER = ((Fcy  / (64 * PWM_Frekvencia)) - 1);    
  28.          P2TPER = ((Fcy  / (PWM_2_Frekvencia)) - 1);
  29.  
  30.          //PWM_duty((unsigned int)(2UL*P1TPER+2)*0.5);      
  31.       }
  32.       void PWM_2_start()
  33.       {
  34.          //PWM2 engedélyezése:
  35.          P2TMR = 0;
  36.          P2TCONbits.PTEN = 1;  
  37.       }
  38.      void PWM_2_stop()
  39.       {
  40.          //PWM2 tiltása:
  41.          P2TMR = 0;
  42.          P2TCONbits.PTEN = 0;  
  43.       }


És a main C-ben meghívom az PWM_2_init -et, és a timer3 interruptban:

  1. void __attribute__((__interrupt__, no_auto_psv)) _T3Interrupt(void)
  2. {
  3. /* Interrupt Service Routine code goes here */
  4. IFS0bits.T3IF = 0; // Clear Timer3 Interrupt Flag
  5.  
  6. ////Ide kell a PWM kitöltési tényezoje
  7. if (t3_szamlalo<255)
  8.     {
  9.     t3_szamlalo+=1;
  10.        
  11.     }
  12. else
  13.     {
  14.         t3_szamlalo =(unsigned long int)0;
  15.     }
  16. P2DC1 =(unsigned long int)t3_szamlalo;
  17. }
A hozzászólás módosítva: Márc 14, 2022
(#) GPeti1977 válasza Ferkógyerek hozzászólására (») Feb 23, 2022
8 bites AVR-rel biztos nem lehet üzembiztosra, mert egyszerre történik az analóg komparátor, vagy négyszög jel esetén az INT0 megszakítás, az UART vétel megszakításával, valahogy összeakadnak mert nincs se prioritás, semmi, ja és még a millis() micros() hoz alapból fut a timer0, meg az oszcillátorhoz a timer1 de az itt nem zavar be.
(#) Pethical válasza pisti hozzászólására (») Jan 13, 2022
Ebben az esetben valóban nem lesz jó, mert kezelni kell az érzékelőket is. Ami neked jó lehet, az az időzítő megszakítása:

  1. /*
  2.  * Arduino 101: timer and interrupts
  3.  * 2: timer1 overflow interrupt example
  4.  * created by RobotFreak
  5.  */
  6.  
  7. #define ledPin 13
  8.  
  9. void setup()
  10. {
  11.   pinMode(ledPin, OUTPUT);
  12.  
  13.   // initialize timer1
  14.   noInterrupts();           // disable all interrupts
  15.   TCCR1A = 0;
  16.   TCCR1B = 0;
  17.  
  18.   TCNT1 = 34286;            // preload timer 65536-16MHz/256/2Hz
  19.   TCCR1B |= (1 << CS12);    // 256 prescaler
  20.   TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  21.   interrupts();             // enable all interrupts
  22. }
  23.  
  24. ISR(timer1_OVF_vect)        // interrupt service routine that wraps a user defined function supplied by attachInterrupt
  25. {
  26.   TCNT1 = 34286;            // preload timer
  27.   digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
  28. }
  29.  
  30. void loop()
  31. {
  32.   // your program here...
  33. }


A kódot nem én írtam, csak idemásoltam Forrás
(#) asch válasza szitko hozzászólására (») Dec 27, 2021
Interrupttal is ki lehet küszöbölni a prellt könnyen:

Konfigurálsz egy timert, hogy mondjuk 50 milliszekundumonként fusson le (nagyjából, nem kell pontosnak lennie).

Ezt írod az interruptba:

  1. static uint8_t prevSample=0;
  2. ISR(timer1_ovf)
  3. {
  4. uint8_t sample=PINA&_BV(3);
  5. if(sample==prevSample) // prellmentesites
  6. {
  7.     if(sample!=0)
  8.     {
  9.     PORTB|=_BV(5);
  10.     }else
  11.     {
  12.     PORTB&=~_BV(5);
  13.     }
  14. }
  15. prevSample=sample;
  16. }


Azért is jó ez a megoldás, mert a CPU terhelése állandó lesz, a másik elvben "éheztetheti" a többi taszkot, ha a bemenet sokáig prellezik.
A hozzászólás módosítva: Dec 27, 2021
(#) GPeti1977 válasza Kera_Will hozzászólására (») Okt 29, 2021
Tiszta jitter mentes a jele, meg rezgőkörrel már leszinuszosítottam, egy DDS modul lett volna ott de nem találom.
Az ardu csak a timer0 használja, timer1, timer2 szabad
A hozzászólás módosítva: Okt 29, 2021
(#) Bakman válasza Massawa hozzászólására (») Okt 12, 2021
Gondolod hogy csak úgy mérek valamit és kijelentem, hogy az a hálózat frekvenciája? Min kellene elgondolkoni?

Nem kell semmilyen extra mérésben gondolkodni. 12 VAC, optocsatoló (6N137). A kimenet, némi szűrés után, a PIC komparátorára csatlakoztatva, az a timer1 kapuzását indítja, állítja. timer1 pedig 500 ns-os felbontásra állítva.

Nem a miértre, hanem a mennyire voltam kíváncsi. A kapott értékek jól összecsengenek az online adatokkal. Az érdekesség számomra annyi, hogy sokkal jobban ingadozik, mint gondoltam.
(#) Bakman válasza kriszrap hozzászólására (») Okt 1, 2021
Ha jól emlékszem, abban a kontrollerben (PIC18F46K22) összesen hét Timer van: Timer0, timer1, 3, 5 és Timer2, 4, 6.

Kösd át SPI-re a meghajtó IC-ket, sokat spórólhatsz az erőforrásokkal.
(#) Bakman válasza BLY94A hozzászólására (») Aug 18, 2021
Sok RF modul jól működik, mondhatni remek ár/érték arányt képviselnek a szegmensben. Ugyanakkor a µs-os pontosságú időméréshez ezek messze-messze nem alkalmasak. Semmi sem garantálja hogy a késleltetés állandó és fix, ezek az RF modulok nem ilyen feladathoz lettek tervezve. Ráadásul 9600-as Baud mellett egy bájt kb. 1 ms idő alatt jön ki egy TX lábon. A logikai áramkörös, RF modulos történet szerintem eleve zsákutca.

Infra (lézeres) kapu -> kábel -> mikrokontroller.

Pl. egyszerű 8 bites PIC mikrokontrollerrel, 32 MHz-es órajel mellett, timer1 segítségével könnyen elérhető a 250 ns-os felbontás is.
(#) Bakman hozzászólása Júl 10, 2021
Nagyot!

PIC16F1825, CCP modul, Compare mode: toggle output on match. Ha a timer1 előosztója 2, 4 vagy 8, akkor a kimenet folyamatosan alacsony szinten van. Akkor működik a kimenet váltogatása, ha a timer1 előosztója 1:1. Régi téma: Bővebben: Link. Tud valaki megoldásról?
(#) szikorapéter válasza szikorapéter hozzászólására (») Máj 24, 2021
Ezt a programot Githubon találtam ( Link ) , ezen már tudom változtatni a PWM frekijét, az viszont jó kérdés hogy a kimeneti freki mekkora? Ami másik fura hogy a szkópon néha mintha nem ellenfázisú jelet mutatna hanem azonost? Ez lehet a szkópom egyik mérőkábelének hibája is de lehet a kódé, az előző fix 50hz-es kódnál stabil volt a képem, itt ugrál kicsit.

A0 a bemenet a potmétertől 10-13-as láb az SPWM jel kimenet, elvileg ellenfázisban egymással.

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3.  
  4. #define LookupEntries (512)
  5.  
  6. //Varible declaration
  7. static int microMHz = 16; // Micro clock frequency
  8. static int freq;     // Sinusoidal frequency
  9. static long int period;   // Period of PWM in clock cycles. 1600 gives 10KHz.
  10. static unsigned int lookUp[LookupEntries];
  11. static char theTCCR1A = 0b10000010; //varible for TCCR1A
  12. static unsigned long int phaseinc, switchFreq;
  13. static double phaseincMult;
  14.  
  15. //Function prototypes
  16. int setFreq(int _freq);
  17. int setSwitchFreq(int sfreq);
  18. void registerInit(void);
  19.  
  20.  
  21. void setup(){
  22.   Serial.begin(9600);
  23.   setSwitchFreq(10000);  
  24.   setFreq(50);
  25.   registerInit();
  26. }
  27.  
  28. void loop(){
  29.   /*
  30.   // Un-comment inorder to read from A1 to change the switching frequency, note that if you have a noisey potentiometer the
  31.   // it will disrupt the signal as the lookup table needs to be regenerated everytime the switing frequency is changed
  32.   int sensorValue = analogRead(A1);
  33.   static int sensorValue2;
  34.   if(sensorValue > sensorValue2*1.01 || sensorValue < sensorValue2*0.99){
  35.     sensorValue2 = sensorValue;
  36.     setSwitchFreq(map(sensorValue, 0, 1023, 1000, 19000));
  37.    
  38.     Serial.println(switchFreq);
  39.     Serial.print(phaseinc>>23);
  40.     Serial.print(".");
  41.     Serial.print(phaseinc&0x007FFFFF);
  42.     Serial.print("\n");  
  43.   }*/
  44.  
  45.   // Value read in from A0 changes the frequency of the sine wave
  46.   int sensorValue = analogRead(A0);
  47.   static int sensorValue2;
  48.   if(sensorValue > sensorValue2*1.01 || sensorValue < sensorValue2*0.99){
  49.     sensorValue2 = sensorValue;
  50.     setFreq(map(sensorValue, 0, 1023, 5, 300));
  51.    
  52.     Serial.print(phaseinc>>23);
  53.     Serial.print(".");
  54.     Serial.print(phaseinc&0x007FFFFF);
  55.     Serial.print("\n");  
  56.   }
  57. }
  58.  
  59. ISR(timer1_OVF_vect){
  60.   static unsigned long int phase, lastphase;
  61.   static char delay1, trig = LOW;
  62.  
  63.   phase += phaseinc;
  64.  
  65.   if(delay1 > 0){ // toggle the output pins one ISR call after phase has overflowed
  66.     theTCCR1A ^= 0b10100000;// Toggle connect and disconnect of compare output A and B.
  67.     TCCR1A = theTCCR1A;
  68.     delay1 = 0;  
  69.   }
  70.   else if((phase>>31 != lastphase>>31) && !(phase>>31)){ //if phase has overflowed . . .
  71.     delay1++;      
  72.     trig = !trig;
  73.     digitalWrite(13,trig); // pin can be used as triggre on oscilloscope
  74.   }
  75.   lastphase = phase;
  76.  
  77.   OCR1A = OCR1B = lookUp[phase >> 23];
  78. }
  79.  
  80. int setFreq(int _freq){
  81.   if(_freq < 0 || _freq > 1000){ // returns 0 if the frequency value is invalid
  82.     return 0;
  83.   } else {
  84.     freq = _freq;
  85.     phaseinc = (unsigned long int) phaseincMult*_freq;
  86.     return 1; // returns 1 if freqency set sucessfully
  87.   }
  88. }
  89.  
  90. int setSwitchFreq(int sfreq){
  91.   double temp;
  92.  
  93.   if(sfreq <= 0 || sfreq > 20000){
  94.     return 0;
  95.   } else {
  96.     switchFreq = sfreq;
  97.     period = microMHz*1e6/sfreq;
  98.     cli(); //disable global interupts while lookup table is made
  99.     TCCR1A = 0b00000010; //disconnect compare A and B while lookup table is generated
  100.     ICR1   = period;
  101.     for(int i = 0; i < LookupEntries; i++){ // Generating the look up table.
  102.       temp = sin(i*M_PI/LookupEntries)*period;
  103.       lookUp[i] = (int)(temp+0.5);       // Round to integer.    
  104.     }
  105.     //sindevisions*decimalbits/1MHz =
  106.     //1024*2^23/1e6 = 8,589.934592
  107.     phaseincMult = (double) period*8589.934592/microMHz;
  108.     phaseinc = (unsigned long int) phaseincMult*freq;
  109.     TCCR1A = theTCCR1A; // reconnect compare outputs
  110.     sei(); //re-enable interupts now that table has been made
  111.     return 1;
  112.   }
  113. }
  114.  
  115. void registerInit(void){
  116.   // Register initilisation, see datasheet for more detail.
  117.   TCCR1A = theTCCR1A; // 0b10000010;
  118.   /*10 clear on match, set at BOTTOM for compA.
  119.    00 compB disconected initially, toggled later to clear on match, set at BOTTOM.
  120.    00
  121.    10 WGM1 1:0 for waveform 15.
  122.    */
  123.   TCCR1B = 0b00011001;
  124.   /*000
  125.    11 WGM1 3:2 for waveform 15.
  126.    001 no prescale on the counter.
  127.    */
  128.   TIMSK1 = 0b00000001;
  129.   /*0000000
  130.    1 TOV1 Flag interrupt enable.
  131.    */
  132.   sei();             // Enable global interrupts.
  133.   // Set outputs pins.
  134.   DDRB   = 0b00000110; // Set PB1 and PB2 as outputs.
  135.   pinMode(13, OUTPUT); // Set trigger pin to output
  136. }
(#) mateatek válasza szikorapéter hozzászólására (») Máj 20, 2021
Még azt is meg lehetne oldani, hogy a timer1 működik ugyanilyen frekvenciával, mnt most és a táblázat tökéletes lesz. De a megszakítást, ami a frekvenciát állítja, azt átdrótozni a timer2-re. Sajnos, az csak 8 bites, ezért vélhetőleg nem tudod majd olyan finoman állítani a frekit. Ha szükséges a freki nagyon finom állítása, akkor át kell állni olyan MCU-ra amiben van 2 darab 16 bites timer. (atmega328pb, lgt8f328p, esetleg atmega2560)
(#) szikorapéter hozzászólása Máj 18, 2021
Sziasztok.
Van egy programom ami SPWM jelet állít elő az arduino 2 kimenetén, egymással ellenfázisban.
Olyan kérdésem volna hogy ha átírom hogy A0 bemeneten a szokásos potméteres szabályozással 2hz-200hz közt tudjam változtatni az SPWM frekvenciáját, akkor az nem lenne már túl sok számítás az arduino részére?
A két kimenet a 9-es és 10-es PWM lábon jön le.

A kódot lentebb beillesztem.

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3.  
  4. // Look up tables with 200 entries each, normalised to have max value of 1600 which is the period of the PWM loaded into register ICR1.
  5. int lookUp1[] = {
  6. 50 ,100 ,151 ,201 ,250 ,300 ,349 ,398 ,446 ,494 ,
  7. 542 ,589 ,635 ,681 ,726 ,771 ,814 ,857 ,899 ,940 ,
  8. 981 ,1020 ,1058 ,1095 ,1131 ,1166 ,1200 ,1233 ,1264 ,1294 ,
  9. 1323 ,1351 ,1377 ,1402 ,1426 ,1448 ,1468 ,1488 ,1505 ,1522 ,
  10. 1536 ,1550 ,1561 ,1572 ,1580 ,1587 ,1593 ,1597 ,1599 ,1600 ,
  11. 1599 ,1597 ,1593 ,1587 ,1580 ,1572 ,1561 ,1550 ,1536 ,1522 ,
  12. 1505 ,1488 ,1468 ,1448 ,1426 ,1402 ,1377 ,1351 ,1323 ,1294 ,
  13. 1264 ,1233 ,1200 ,1166 ,1131 ,1095 ,1058 ,1020 ,981 ,940 ,
  14. 899 ,857 ,814 ,771 ,726 ,681 ,635 ,589 ,542 ,494 ,
  15. 446 ,398 ,349 ,300 ,250 ,201 ,151 ,100 ,50 ,0 ,
  16. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  17. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  18. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  19. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  20. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  21. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  22. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  23. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  24. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  25. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0};
  26.  
  27. int lookUp2[] = {
  28. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  29. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  30. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  31. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  32. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  33. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  34. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  35. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  36. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  37. 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
  38. 50 ,100 ,151 ,201 ,250 ,300 ,349 ,398 ,446 ,494 ,
  39. 542 ,589 ,635 ,681 ,726 ,771 ,814 ,857 ,899 ,940 ,
  40. 981 ,1020 ,1058 ,1095 ,1131 ,1166 ,1200 ,1233 ,1264 ,1294 ,
  41. 1323 ,1351 ,1377 ,1402 ,1426 ,1448 ,1468 ,1488 ,1505 ,1522 ,
  42. 1536 ,1550 ,1561 ,1572 ,1580 ,1587 ,1593 ,1597 ,1599 ,1600 ,
  43. 1599 ,1597 ,1593 ,1587 ,1580 ,1572 ,1561 ,1550 ,1536 ,1522 ,
  44. 1505 ,1488 ,1468 ,1448 ,1426 ,1402 ,1377 ,1351 ,1323 ,1294 ,
  45. 1264 ,1233 ,1200 ,1166 ,1131 ,1095 ,1058 ,1020 ,981 ,940 ,
  46. 899 ,857 ,814 ,771 ,726 ,681 ,635 ,589 ,542 ,494 ,
  47. 446 ,398 ,349 ,300 ,250 ,201 ,151 ,100 ,50 ,0};
  48.  
  49.  
  50. void setup(){
  51.     // Register initilisation, see datasheet for more detail.
  52.     TCCR1A = 0b10100010;
  53.        /*10 clear on match, set at BOTTOM for compA.
  54.          10 clear on match, set at BOTTOM for compB.
  55.          00
  56.          10 WGM1 1:0 for waveform 15.
  57.        */
  58.     TCCR1B = 0b00011001;
  59.        /*000
  60.          11 WGM1 3:2 for waveform 15.
  61.          001 no prescale on the counter.
  62.        */
  63.     TIMSK1 = 0b00000001;
  64.        /*0000000
  65.          1 TOV1 Flag interrupt enable.
  66.        */
  67.     ICR1   = 1600;     // Period for 16MHz crystal, for a switching frequency of 100KHz for 200 subdevisions per 50Hz sin wave cycle.
  68.     sei();             // Enable global interrupts.
  69.     DDRB = 0b00000110; // Set PB1 and PB2 as outputs.
  70.     pinMode(13,OUTPUT);
  71. }
  72.  
  73. void loop(){; /*Do nothing . . . . forever!*/}
  74.  
  75. ISR(timer1_OVF_vect){
  76.     static int num;
  77.     // change duty-cycle every period.
  78.     OCR1A = lookUp1[num];
  79.     OCR1B = lookUp2[num];
  80.    
  81.     if(++num >= 200){ // Pre-increment num then check it's below 200.
  82.        num = 0;       // Reset num.
  83.      }
  84. }
(#) Laja1 válasza foxi63 hozzászólására (») Máj 16, 2021
A segítséget megköszönném, mert a Timer kezelése gondot okoz. Próbáltam már, de nem sikerült. Váltottam egy olyan kontrollerre, amiben van belső órajel: PIC16F627A.
Ez volna a program __delay paranccsal. Ami a Proteus 8 szimulációval jól is működik, de csak 20 Mhz-nél. Ha sokkal alacsonyabb, akkor a másodpercek lassabban telnek. A valóságban pedig minden összevisszaság van. Ki van kommentelve a Timer-es próbálkozásom.
A program (még PIC16F718-ra):
  1. #include <xc.h>
  2. #define _XTAL_FREQ 20000000 //define crystal frequency to 20MHz
  3.  
  4. // CONFIG
  5. #pragma config FOSC = RC     // Oscillator Selection bits (RC oscillator)
  6. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  7. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  8. #pragma config BOREN = OFF       // Brown-out Reset Enable bit (BOR disabled)
  9. #pragma config CP = OFF      // Flash Program Memory Code Protection bit (Code protection off)
  10.  
  11.  
  12. #define gomb RA0
  13. int k=0;
  14. int z=3;
  15. int t;
  16. int n=1;
  17.  
  18.  
  19.  
  20.  
  21. void main() {
  22.     ADCON1 = 0x0F;  //digitális bemenet és nem analóg
  23.     TRISB = 0x00; //Port-B as Output
  24.     TRISA = 0x01; //RA as input
  25.     //T1CON = 0x30;  //Timer beállítás. ki kell számolni 1 sec alatti m?veletek számát: XTAL_FREQ/4/Prescaler= 1 sec alatti m?veletszám
  26.  
  27.     // megszakítások beállítása
  28.     /* PIE1bits.TMR1IE=1;              // timer1 megszak. engedélyezés
  29.      PIR1bits.TMR1IF=0;              // timer1 megszakításjelz? törlése
  30.      INTCONbits.PEIE=1;              // periféria megszak. engedélyezés
  31.      INTCONbits.GIE=1;            */   // globális megszak. engedélyezés  
  32.        
  33.        // TMR1H=0x0B;  Feltöltés 16 bit-es timernél a fels? és als? 8 bitet külön adjuk meg. Vagy hexadec vagy rendes számmal.
  34.         //TMR1L=0xDB;  Innen fog indulni egyesével felfelé a számláló és FFFF-nél túlcsordul, akkor indul 0-ról vagy újabb feltöltésnél onnantól
  35.     //TMR1=3035;
  36.            
  37.      
  38.         /*T1CONbits.TMR1ON=0;   //Timer nem indul  
  39.         PIR1bits.TMR1IF=0;  //Nincs túlcsordulva*/
  40.        
  41.        
  42.     while (1)
  43.     {
  44.            
  45.       if (gomb==1)
  46.       {
  47.          
  48.           __delay_ms(300);
  49.      
  50.                  if (gomb==1)
  51.               {__delay_ms(2000);
  52.                  if (gomb==1)
  53.                  { PORTBbits.RB6=1;
  54.                  __delay_ms(1000);
  55.                  PORTBbits.RB6=0;
  56.                  
  57.                   __delay_ms(1000);
  58.                   PORTBbits.RB6=1;
  59.                  // T1CONbits.TMR1ON=1;
  60.                   z=0;
  61.                    while (n)
  62.           {__delay_ms(1000);
  63.           // if (PIR1bits.TMR1IF==1)  //ha túlcsordult
  64.            // { PIR1bits.TMR1IF=0;
  65.                 z=z+1;
  66.            if (gomb==1) {n=0;}
  67.                    }
  68.                
  69.                  
  70.                  // T1CONbits.TMR1ON=0;
  71.                   PORTBbits.RB6=0;
  72.            
  73.          
  74.                  
  75.                  
  76.                  }
  77.                 // n=1;
  78.                  
  79.                  }  
  80.      
  81.                  else
  82.                  {
  83.           PORTBbits.RB3=1;
  84.          // T1CONbits.TMR1ON=1;
  85.           k=0;
  86.          
  87.           while (k<z+2)
  88.           {
  89.               __delay_ms(1000);
  90.            //if (PIR1bits.TMR1IF==1)  //ha túlcsordult
  91.            // { PIR1bits.TMR1IF=0;
  92.        
  93.             k=k+1;
  94.          if (k==1)
  95.          {
  96.           PORTBbits.RB5=1;  
  97.          }
  98.            if (gomb==1)
  99.            {PORTBbits.RB5=0;}
  100.          if (k==z+1)
  101.          {
  102.           PORTBbits.RB5=0;  
  103.          }
  104.          if (k==z+2)
  105.          {
  106.           PORTBbits.RB3=0;  }
  107.          }
  108.          
  109.           //T1CONbits.TMR1ON=0;
  110.          
  111.                  }
  112.          
  113.          
  114.      
  115.       }
  116.       else
  117.       {PORTBbits.RB3=0;
  118.       PORTBbits.RB5=0;
  119.       PORTBbits.RB6=0;}
  120.     }
  121. }


Működés:
A nyomógombra egy relé meghúz, majd 1 sec múlva egy másik is behúz. 3 sec múlva a második elenged és ezután 1 sec múlva az első is elenged.
Ha hosszan nyomjuk a gombot, akkor egy LED felvillan és onnantól számolja a másodperceket, ha ismét megnyomjuk a gombot, akkor leáll. Ezt az időt azért számolja, mert innentől kezdve a második relé már nem 3 sec-ig fog behúzva lenni, hanem eddig a megváltoztatott ideig.
Köszönöm!!
(#) Laja1 hozzászólása Máj 10, 2021
Sziasztok!
Ezt a programot szeretném UPP628-as programozóval beégetni:
  1. #include <xc.h>
  2. #define _XTAL_FREQ 2097120 //define crystal frequency to 20MHz
  3.  
  4. // CONFIG
  5. #pragma config FOSC = XT     // Oscillator Selection bits (RC oscillator)
  6. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  7. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  8. #pragma config BOREN = OFF       // Brown-out Reset Enable bit (BOR disabled)
  9. #pragma config CP = OFF      // Flash Program Memory Code Protection bit (Code protection off)
  10.  
  11.  
  12. #define gomb RA0
  13. int k=0;
  14. int z=3;
  15. int t;
  16. int n=1;
  17.  
  18.  
  19.  
  20.  
  21. void main() {
  22.     ADCON1 = 0x0F;  //digitális bemenet és nem analóg
  23.     TRISB = 0x00; //Port-B as Output
  24.     TRISA = 0x01; //RA as input
  25.     T1CON = 0x30;  //Timer beállítás. ki kell számolni 1 sec alatti m?veletek számát: XTAL_FREQ/4/Prescaler= 1 sec alatti m?veletszám
  26.  
  27.     // megszakítások beállítása
  28.     /* PIE1bits.TMR1IE=1;              // timer1 megszak. engedélyezés
  29.      PIR1bits.TMR1IF=0;              // timer1 megszakításjelz? törlése
  30.      INTCONbits.PEIE=1;              // periféria megszak. engedélyezés
  31.      INTCONbits.GIE=1;            */   // globális megszak. engedélyezés  
  32.        
  33.        // TMR1H=0x0B;  Feltöltés 16 bit-es timernél a fels? és als? 8 bitet külön adjuk meg. Vagy hexadec vagy rendes számmal.
  34.         //TMR1L=0xDB;  Innen fog indulni egyesével felfelé a számláló és FFFF-nél túlcsordul, akkor indul 0-ról vagy újabb feltöltésnél onnantól
  35.     //TMR1=3035;
  36.            
  37.      
  38.         T1CONbits.TMR1ON=0;   //Timer nem indul  
  39.         PIR1bits.TMR1IF=0;  //Nincs túlcsordulva
  40.        
  41.        
  42.     while (1)
  43.     {
  44.            
  45.       if (gomb==1)
  46.       {
  47.          
  48.           __delay_ms(300);
  49.      
  50.                  if (gomb==1)
  51.               {__delay_ms(2000);
  52.                  if (gomb==1)
  53.                  { PORTBbits.RB6=1;
  54.                  __delay_ms(1000);
  55.                  PORTBbits.RB6=0;
  56.                  
  57.                   __delay_ms(1000);
  58.                   PORTBbits.RB6=1;
  59.                  // T1CONbits.TMR1ON=1;
  60.                   z=0;
  61.                    while (n)
  62.           {__delay_ms(1000);
  63.           // if (PIR1bits.TMR1IF==1)  //ha túlcsordult
  64.            // { PIR1bits.TMR1IF=0;
  65.                 z=z+1;
  66.            if (gomb==1) {n=0;}
  67.                    }
  68.                
  69.                  
  70.                  // T1CONbits.TMR1ON=0;
  71.                   PORTBbits.RB6=0;
  72.            
  73.          
  74.                  
  75.                  }
  76.                  n=1;
  77.                  }
  78.                  
  79.      
  80.           PORTBbits.RB3=1;
  81.           T1CONbits.TMR1ON=1;
  82.           k=0;
  83.          
  84.           while (k<z+2)
  85.           {
  86.            if (PIR1bits.TMR1IF==1)  //ha túlcsordult
  87.             { PIR1bits.TMR1IF=0;
  88.        
  89.             k=k+1;}
  90.          if (k==1)
  91.          {
  92.           PORTBbits.RB5=1;  
  93.          }
  94.            if (gomb==1)
  95.            {PORTBbits.RB5=0;}
  96.          if (k==z+1)
  97.          {
  98.           PORTBbits.RB5=0;  
  99.          }
  100.          if (k==z+2)
  101.          {
  102.           PORTBbits.RB3=0;  
  103.          }
  104.           }
  105.           T1CONbits.TMR1ON=0;
  106.          
  107.          
  108.          
  109.          
  110.       }
  111.    
  112. }
  113. }


A program szépen lefordult, az égetés után azt írja "Konfig word hiba".
Az ellenőrzésre pedig ezt:
"Kód hiba itt:0x0000 Kiolvasva 0x3FFF, ellenőrizva: 0x2FF2"

Mi lehet az oka?
Köszönöm!
(#) Hp41C válasza Laja1 hozzászólására (») Ápr 21, 2021
Az lehet a gond, hogy a tmr1 tovább számol a TMR1IF beállítása után, de a program megint csak a 3035=65536-62500 -at tölti bele, azaz néhány számlálás elveszik másodpercenként.

A jó módszer a TMR1 aktuális értékéhez való hozzáadás lenne, ami nem egyszerű a 16 bites érték és a módosítás közbeni alsó byte átfordulás miatt. (ld.timer1 Errata).

Jobb lett volna a TMR2 -t használni. Vele nem lehet 1s időt előállítani, de ha hozzáteszünk egy szoftver számlálót, akkor meg lehet csinálni.

16F716.c
    
(#) Laja1 válasza Hp41C hozzászólására (») Ápr 21, 2021
A Te megoldásod nem működik nálam, de a tőletek kapott segítségekből összeraktam a saját elképzelésemet és ez így tökéletes. Most még csak annyit tud, hogy az egyik kimenet a nyomógombra azonnal magas lesz, egy másik csak később. A többi szükséges verziót már össze tudom hozni. Köszönöm!
  1. #include <xc.h>
  2. #define _XTAL_FREQ 20000000 //define crystal frequency to 20MHz
  3.  
  4. // CONFIG
  5. #pragma config FOSC = XT     // Oscillator Selection bits (RC oscillator)
  6. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  7. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  8. #pragma config BOREN = OFF       // Brown-out Reset Enable bit (BOR disabled)
  9. #pragma config CP = OFF      // Flash Program Memory Code Protection bit (Code protection off)
  10.  
  11.  
  12. #define gomb RA0
  13. int k=0;
  14.  
  15. void main() {
  16.     ADCON1 = 0x0F;
  17.     TRISB = 0x00; //Port-B as Output
  18.     TRISA = 0xFF; //RA as input
  19.     T1CON = 0x30;
  20.  
  21.     // megszakítások beállítása
  22.     /* PIE1bits.TMR1IE=1;              // timer1 megszak. engedélyezés
  23.      PIR1bits.TMR1IF=0;              // timer1 megszakításjelző törlése
  24.      INTCONbits.PEIE=1;              // periféria megszak. engedélyezés
  25.      INTCONbits.GIE=1;            */   // globális megszak. engedélyezés  
  26.        
  27.         TMR1H=0xD9;
  28.         TMR1L=0xDB;
  29.            
  30.      
  31.        
  32.         T1CONbits.TMR1ON=0;    
  33.        PIR1bits.TMR1IF=0;
  34.        
  35.     while (1)
  36.     {
  37.            
  38.       if (gomb==1)
  39.       {
  40.           PORTBbits.RB3=1;
  41.            T1CONbits.TMR1ON=1;}
  42.          
  43.      
  44.            
  45.       if (PIR1bits.TMR1IF==1)
  46.      { PIR1bits.TMR1IF=0;
  47.          TMR1H=0xD9;
  48.         TMR1L=0xDB;
  49.          
  50.          k=k+1;
  51.          if (k==30)
  52.          {
  53.           PORTBbits.RB5=1;  
  54.          }
  55.      
  56.          
  57.       }
  58.       }
  59.     }
(#) Zsora válasza Laja1 hozzászólására (») Ápr 20, 2021
Nem ártana engedélyezni a megszakításokat (a while(1) ciklus előtt).
  1. // megszakítások beállítása
  2.     PIE1bits.TMR1IE=1;              // timer1 megszak. engedélyezés
  3.     PIR1bits.TMR1IF=0;              // timer1 megszakításjelző törlése
  4.     INTCONbits.PEIE=1;              // periféria megszak. engedélyezés
  5.     INTCONbits.GIE=1;               // globális megszak. engedélyezés

Továbbá ha regiszterek bitjeire hivatkozol, akkor ne felejtsd el odaírni azt hogy 'bits', mint ahogy az a fenti példában is látható.
A hozzászólás módosítva: Ápr 20, 2021
(#) Pali79 válasza miki79 hozzászólására (») Ápr 11, 2021
Ha ilyen nagy időközönként kell bármit csinálnia, akkor szerintem a legegyszerűbb ha olyan PIC-et használsz aminél a timer1-et lehet külön külső kvarcról hajtani. Ha erre teszel egy 32,764 kHz-es óra kvarcot akkor alapból 2 másodpercenként generál megszakítást. 2 másodperc rengeteg idő, közben csinálhat mást a PIC.
(#) mateatek válasza matyas98 hozzászólására (») Márc 8, 2021
  1. pinMode (9, OUTPUT);
  2. pinMode (10, OUTPUT);
  3. TCCR1A = 0;
  4. TCCR1B = 0;
  5. TCCR1A = _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1);
  6. TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(CS12) | _BV(WGM12);
  7. ICR1   = 31249; //periódus idő, 2 másodperc
  8. OCR1A = 15000; //D9 kitöltés
  9. OCR1B = 15000; //D10 kitöltés


Az ICR1 regiszter a periódus időt határozza meg. 65535-nél nagyobb nem lehet. Az kicsit több, mint 4 másodperces periódus időt tesz ki. Most 2 másodpercre van állítva. Az OCR1x regiszter a két kimenet PWM értékét tartalmazza. Maximum értéke az ICR1 lehet.
Max 4,19 másodperces periódus idő a maximum, amit tud a timer1 16 MHz-es órajel mellett fast PWM-ben, 1024-es előosztó mellett. Fázis korrekt PWM-ben a dupláját. Ha ennél is hosszabb periódus idő kell, akkor már az MCU órajel előosztóját is osztásra kell állítani, ami lassítja a műveletek elvégzését. De azzal cirka 2145 másodperces periódus időt lehet elérni. Ha ennél is nagyobb periódus idő kell, akkor már le kell cserélni lassabbra a kvarcot.
(#) Bakman válasza Peet19 hozzászólására (») Dec 22, 2020
A timer1 megszakítás engedélyezve van de ez nincs kezelve sehol. Biztos ami biztos, kapcsold ki a teszt idejére.
  1. PIE4bits.TMR1IE = 0;
Nem vagyok benne biztos, hogy összehasonlító (compare) módban biztosan nem keletkezik ott megszakítás, lévén egy külön modul, csak éppen kapcsolódik másik modulhoz is, jelen esetben.

compare: összehasonlít

A komparátort kis hazánkban analóg összehasonlítóra használjuk, az adatlapban is kétféle elnevezés van: Comparator és Compare module. Ne keverd a kettőt.

Te váltogatni akarod a LAT regisztert, ezért kell azt olvasni és módosítani. Ha azt akarod invertálni, akkor azt is kell olvasni, nem egy másikat, még ha összefüggés is van a kettő közt.
A hozzászólás módosítva: Dec 22, 2020
(#) Peet19 válasza Bakman hozzászólására (») Dec 22, 2020
Hát, nem is tudom. Amit írtál kódot az gyakorlatilag ugyanaz. LAT -al írok PORT -al olvasok (így tanultam).
Amúgy a PORT regisztert soha nem írom, csak beolvasom az épp aktuális jelszintet.
Ha a LAT -ból olvasok az csak a pufferből olvassa vissza a beállított szintet, nem pedig a valós jelszintet adja vissza. De lehet rosszul tudom, Te vagy a szaki
Bemásolom az egészet hátha felfedezel valami extra hibát:

  1. /************ 8MHz külső kristállyal **********/
  2. #include <xc.h>
  3. #include <pic18f27k40.h>
  4. #include "config.h"
  5.  
  6. /************ Globális változók ***********/
  7. volatile unsigned int cnt = 0;
  8.  
  9. /*************** Deklarációk **************/
  10. void init_base(void);
  11. void init_interrupt(void);
  12. void init_tmr1(void);
  13.  
  14. void __interrupt(high_priority) Isr(void);
  15.  
  16. void main(void) {
  17.    
  18.     init_base();
  19.     init_interrupt();
  20.     init_tmr1();
  21.    
  22.     /************** Főprogram *************/
  23.     while(1){
  24.        
  25.        
  26.        
  27.     }
  28.    
  29.     return;
  30. }
  31.  
  32. /***************** Alapbeállítások ****************/
  33. void init_base(void){
  34.    
  35.     // Az összes lábat analógról digitálisra állítom
  36.     ANSELA = 0;
  37.     ANSELB = 0;
  38.     ANSELC = 0;
  39.    
  40.     // Az összes lábat kimenetnek állítom be
  41.     TRISA = 0;
  42.     TRISB = 0;
  43.     TRISC = 0;
  44.    
  45.     // Az összes láb jelszintjét alacsonyra állítom
  46.     LATA = 0;
  47.     LATB = 0;
  48.     LATC = 0;
  49.    
  50. }
  51.  
  52. /**************** Megszakítás beállításai ***************/
  53. void init_interrupt(void){
  54.    
  55.     INTCONbits.GIE_GIEH  = 1;   // Globális megszakítás engedélyezve
  56.     INTCONbits.PEIE_GIEL = 1;   // Perifériás megszakítás engedélyezve
  57.     INTCONbits.IPEN      = 0;   // Megszakítások prioritása letiltva
  58.     PIE4bits.TMR1IE      = 1;   // timer1 megszakítás engedélyezve
  59.     PIE6bits.CCP1IE      = 1;   // Komparátor modul megszakítás engedélyezve
  60.    
  61. }
  62.  
  63. /***************** timer1 beállításai ***************/
  64. void init_tmr1(void){
  65.    
  66.     T1CONbits.ON    = 0;       // timer1 kikapcsolása a beállítások előtt
  67.     T1CONbits.CKPS  = 0b11;    // Előosztó 1:8
  68.     T1CONbits.RD16  = 1;       // 16 bites mód beállítása
  69.    
  70.     TMR1CLKbits.CS  = 0b0001;  // Órajelforrás Fosc/4
  71.     TMR1            = 0;       // Számláló kezdőérték nullázása
  72.    
  73.     /* 8 MHz -es kristállyal 500ns -onként fogja léptetni a számlálót. Ha 1:1 az előosztó.
  74.      * 8 lépés 1us.
  75.      * Ha 1:8 az előosztó, akkor 4us-onként lépteti a számlálót.
  76.      * A számláló 16 bites akkor 65535-ig tud számolni. 2500 lépés 10ms, akkor a komparátor
  77.      * regisztereit 2500-ra kell állítani. Ez a CCPR1H és a CCPR1L. */
  78.    
  79.     CCP1CONbits.EN   = 0;        // CCP1 letiltása a beállítások előtt
  80.     //CCP1CONbits.MODE = 0b1011;   // CCP1 Compare mód beállítása "Pulse output; clear TMR1"
  81.     CCP1CONbits.MODE = 0b0010;   // CCP1 Compare mód beállítása "Toggle output" váltogatja a kimenetet
  82.     CCPR1            = 2500;     // Komparálási érték beállítása.
  83.     CCP1CONbits.EN   = 1;        // CCP1 indítása a beállítások után
  84.     T1CONbits.ON     = 1;        // timer1 indítása a beállítások után
  85. }
  86.  
  87. /*************** Megszakításkor lefutó függvény ***************/
  88. void Isr(void){
  89.    
  90.     // Ha a komparátor okozott megszakítást
  91.     if(PIR6bits.CCP1IF){       // Eltelt 10ms
  92.         PIR6bits.CCP1IF = 0;   // Törlöm a megszíktást jelző bitet
  93.         /*cnt++;
  94.         if(cnt == 50){
  95.             LATCbits.LATC2 = ~PORTCbits.RC2;
  96.             cnt            = 0;
  97.         }*/
  98.     }
  99.    
  100.     // Ha timer1 okozott megszakítást
  101.     if(PIR4bits.TMR1IF){
  102.         //LATCbits.LATC2 = 1;
  103.         // Komparátor módban a timer1 soha nem fog túlcsordulni, mert az összehasonlításkor
  104.         // ha megegyeznek a beállított értékek akkor automatikusan törlődik a számláló
  105.         // lenullázódik és kezdődik a számolás előlről.
  106.     }
  107.    
  108. }
(#) mateatek válasza sdrlab hozzászólására (») Dec 17, 2020
Tehát, ez a kód, ami fagy, vagy újraindulást eredményez néha. A kód még közel sem kész, a hardver konfigurálásához használom (használnám) egyenlőre.

Szerk: ha a megszakítást nem tiltom le az LCD kezelése előtt, akkor az enkóder első kattanására befagy. A 13-as lábon lévő LED-et azért villogtatom, hogy lássa, van-e fagyás.

  1. #include <Adafruit_MCP4728.h>
  2. #include <Wire.h>
  3. #include <LiquidCrystal_I2C.h>
  4.  
  5. Adafruit_MCP4728 mcp;
  6.  
  7. LiquidCrystal_I2C lcd(0x26, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
  8.  
  9. byte A = 0;
  10. volatile unsigned int lepes = 0;
  11. unsigned int lepesv = 1;
  12. unsigned int szam = 0;
  13.  
  14.  
  15. void setup() {
  16.   analogReference(EXTERNAL);
  17.   mcp.begin();
  18.   lcd.begin(16, 2);
  19.   lcd.setCursor(4, 0);
  20.   lcd.print("F\x01mkeres\x07");
  21.   delay(1000);
  22.   lcd.clear();
  23.   DDRB |= _BV (2);
  24.   DDRB |= _BV (3);
  25.   DDRB |= _BV (4);
  26.   DDRD |= _BV (0);
  27.   DDRD |= _BV (1);
  28.   DDRB |= _BV (1);
  29.   DDRD &= ~_BV (7);
  30.   DDRD &= ~_BV (4);
  31.   PORTD |= _BV (4);
  32.   PORTD |= _BV (7);
  33.   DDRB |= _BV (5);
  34.   lcd.clear();
  35.   mcp.setChannelValue(MCP4728_CHANNEL_A, 4095, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
  36.   mcp.setChannelValue(MCP4728_CHANNEL_B, 4095, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
  37.   mcp.setChannelValue(MCP4728_CHANNEL_C, 1024, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
  38.   mcp.setChannelValue(MCP4728_CHANNEL_D, 3066, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
  39.   Wire.setClock(300000);
  40.   PCICR = 0b00000100;
  41.   PCMSK2 = 0b10010000;
  42. }
  43.  
  44. void loop() {
  45.   delay(1000);
  46.   PORTB |= _BV (5);
  47.   delay(1000);
  48.   PORTB &= ~_BV (5);
  49.   PCICR = 0;
  50.   PCIFR = 0;
  51.   lcd.setCursor(0, 0);
  52.   lcd.print(lepes);
  53.   lcd.print("  ");
  54.   lcd.print(szam);
  55.   delay(1);
  56.   PCICR = 0b00000100;
  57.   if (lepes != lepesv) {
  58.     if (lepes >= 4) {
  59.       lepes = 0;
  60.     }
  61.     if (lepes == 0) {
  62.       timer10();
  63.     }
  64.     if (lepes == 1) {
  65.       timer15();
  66.     }
  67.     if (lepes == 2) {
  68.       Timer20();
  69.     }
  70.     if (lepes == 3) {
  71.       Timer25();
  72.     }
  73.     lepesv = lepes;
  74.   }
  75. }
  76.  
  77. void Timer25() {
  78.   PCICR = 0;
  79.   PCIFR = 0;
  80.   lcd.setCursor(0, 1);
  81.   lcd.print("25kHz");
  82.   delay(1);
  83.   PCICR = 0b00000100;
  84.   PORTB &= ~_BV (2);
  85.   PORTB &= ~_BV (3);
  86.   PORTB &= ~_BV (4);
  87.   int setgnd = 0;
  88.   noInterrupts();
  89.   TCCR1A = 0;
  90.   TCCR1B = 0;
  91.   TCCR3A = 0;
  92.   TCCR3B = 0;
  93.   TCCR3A = 0;
  94.   TCCR3B = 0;
  95.   TCCR1A = _BV(WGM11) | _BV(COM1A1);
  96.   TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
  97.   ICR1   = 639;
  98.   OCR1A = 319;
  99.   TCNT1 = setgnd;
  100.   TCCR3A = _BV(WGM31) | _BV(COM3A1);
  101.   TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
  102.   ICR3   = 639;
  103.   OCR3A = 319;
  104.   TCNT3 = setgnd;
  105.   TCCR4A = _BV(WGM41) | _BV(COM4A1);
  106.   TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
  107.   ICR4   = 639;
  108.   OCR4A = 319;
  109.   TCNT4 = setgnd;
  110.   interrupts();
  111. }
  112.  
  113.  
  114. void Timer20() {
  115.   PCICR = 0;
  116.   PCIFR = 0;
  117.   lcd.setCursor(0, 1);
  118.   lcd.print("20kHz");
  119.   delay(1);
  120.   PCICR = 0b00000100;
  121.   PORTB |= _BV (2);
  122.   PORTB &= ~_BV (3);
  123.   PORTB &= ~_BV (4);
  124.   int setgnd = 0;
  125.   noInterrupts();
  126.   TCCR1A = 0;
  127.   TCCR1B = 0;
  128.   TCCR3A = 0;
  129.   TCCR3B = 0;
  130.   TCCR3A = 0;
  131.   TCCR3B = 0;
  132.   TCCR1A = _BV(WGM11) | _BV(COM1A1);
  133.   TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
  134.   ICR1   = 799;
  135.   OCR1A = 399;
  136.   TCNT1 = setgnd;
  137.   TCCR3A = _BV(WGM31) | _BV(COM3A1);
  138.   TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
  139.   ICR3   = 799;
  140.   OCR3A = 399;
  141.   TCNT3 = setgnd;
  142.   TCCR4A = _BV(WGM41) | _BV(COM4A1);
  143.   TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
  144.   ICR4   = 799;
  145.   OCR4A = 399;
  146.   TCNT4 = setgnd;
  147.   interrupts();
  148. }
  149.  
  150. void timer15() {
  151.   PCICR = 0;
  152.   PCIFR = 0;
  153.   lcd.setCursor(0, 1);
  154.   lcd.print("15kHz");
  155.   delay(1);
  156.   PCICR = 0b00000100;
  157.   PORTB |= _BV (2);
  158.   PORTB |= _BV (3);
  159.   PORTB &= ~_BV (4);
  160.   int setgnd = 0;
  161.   noInterrupts();
  162.   TCCR1A = 0;
  163.   TCCR1B = 0;
  164.   TCCR3A = 0;
  165.   TCCR3B = 0;
  166.   TCCR3A = 0;
  167.   TCCR3B = 0;
  168.   TCCR1A = _BV(WGM11) | _BV(COM1A1);
  169.   TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
  170.   ICR1   = 1065;
  171.   OCR1A = 532;
  172.   TCNT1 = setgnd;
  173.   TCCR3A = _BV(WGM31) | _BV(COM3A1);
  174.   TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
  175.   ICR3   = 1065;
  176.   OCR3A = 532;
  177.   TCNT3 = setgnd;
  178.   TCCR4A = _BV(WGM41) | _BV(COM4A1);
  179.   TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
  180.   ICR4   = 1065;
  181.   OCR4A = 532;
  182.   TCNT4 = setgnd;
  183.   interrupts();
  184. }
  185.  
  186. void timer10() {
  187.   PCICR = 0;
  188.   PCIFR = 0;
  189.   lcd.setCursor(0, 1);
  190.   lcd.print("10kHz");
  191.   delay(1);
  192.   PCICR = 0b00000100;
  193.   PORTB |= _BV (2);
  194.   PORTB |= _BV (3);
  195.   PORTB |= _BV (4);
  196.   int setgnd = 0;
  197.   noInterrupts();
  198.   TCCR1A = 0;
  199.   TCCR1B = 0;
  200.   TCCR3A = 0;
  201.   TCCR3B = 0;
  202.   TCCR3A = 0;
  203.   TCCR3B = 0;
  204.   TCCR1A = _BV(WGM11) | _BV(COM1A1);
  205.   TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
  206.   ICR1   = 1599;
  207.   OCR1A = 799;
  208.   TCNT1 = setgnd;
  209.   TCCR3A = _BV(WGM31) | _BV(COM3A1);
  210.   TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
  211.   ICR3   = 1599;
  212.   OCR3A = 799;
  213.   TCNT3 = setgnd;
  214.   TCCR4A = _BV(WGM41) | _BV(COM4A1);
  215.   TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
  216.   ICR4   = 1599;
  217.   OCR4A = 799;
  218.   TCNT4 = setgnd;
  219.   interrupts();
  220. }
  221.  
  222. ISR(PCINT2_vect) {
  223.   A = A + ((PIND & _BV (4)) == 0) << 1;
  224.   A = A + ((PIND & _BV (7)) == 0) << 1;
  225.   A = A << 2;
  226.   if (A == 136) lepes--;
  227.   if (A == 144) lepes++;
  228.   szam++;
  229. }
A hozzászólás módosítva: Dec 17, 2020
(#) Peet19 hozzászólása Okt 19, 2020
Sziasztok!

Mi a baj az alábbi kóddal? A rand() -al nem stimmel valami? Ha kiveszem a kódból akkor lefut rendesen hiba nélkül, de ha ott van akkor hibát jelez.
  1. //megszakításkor lefutó függvény
  2.  void myHighISR(void){
  3.    
  4.     /* Ha Timer0 okozta a megszakítást */
  5.      if(INTCONbits.T0IF){
  6.         // Eltelt 1ms
  7.         INTCONbits.T0IF = 0;   // A tulcsordulást jelző bitet 0-ra állítom
  8.         TMR0 = 131;            // Timer0 beállítása hogy honnan induljon.
  9.         t0_cnt++;              // 1ms -onként léptetem a számlálót
  10.         if(t0_cnt >= 1000){
  11.             // Eltelt 1s
  12.             t1 = 65511 + ( rand() % 10 ); // Beállítom az új random frekvenciát
  13.         }
  14.      }
  15.    
  16.     /* Ha timer1 okozta a megszakítást */
  17.     if(PIR1bits.TMR1IF){
  18.         PIR1bits.TMR1IF = 0;           // A tulcsordulást jelző bitet 0-ra állítom
  19.         GPIObits.GP5 = ~GPIObits.GP5;  // A kimeneti láb szintjét megfordítom.
  20.         TMR1 = t1;                     // timer1 beállítása hogy honnan induljon.
  21.     }
  22.    
  23.  }


Be van includolva az stdlib.h. Ha jól tudom abban van a rand definíciója.
A hozzászólás módosítva: Okt 19, 2020
(#) Peet19 válasza Bakman hozzászólására (») Okt 8, 2020
Próbálom a timer1-et beállítani de nem teljesen tiszta minden. Bemásolom az eddigi kódom, majd nézzétek meg hogy jó-e:

  1. void main(void) {
  2.    
  3.     ANSEL = 0x0;              // az összes analóg kimenet letiltva. Digitálisra állítva.
  4.     ADCON0bits.ADON = 0;      // A/D átalakító letiltva. Nem fogyaszt áramot.
  5.     TRISIObits.TRISIO5 = 0;   // A GP5-ös láb kimenet
  6.  
  7.     PIE1bits.TMR1IE = 1;      // timer1 megszakítást engedélyező bit bekapcsolva
  8.     INTCONbits.GIE = 1;       // Globális megszakítás engedélyezése
  9.     INTCONbits.PEIE = 1;      // Periféria megszakítás engedélyezése
  10.    
  11.     T1CONbits.TMR1GE = 0;     // 6.bit. Tiltókapu kikapcsolva. timer1 állandóan működik.
  12.     T1CONbits.T1CKPS1 = 0;    // 5.bit. Előosztó első bitje
  13.     T1CONbits.T1CKPS0 = 1;    // 4.bit. Előosztó második bitje. Ez így 1:2 -es osztási arány
  14.     T1CONbits.T1OSCEN = 0;    // 3.bit. timer1 oszcillátor kikapcsolva
  15.     T1CONbits.nT1SYNC = 0;    // 2.bit. Külső órajelszinkroizálónak most nincs szerepe
  16.     T1CONbits.TMR1CS = 0;     // 1.bit. Belső órajel kiválasztása
  17.     T1CONbits.TMR1ON = 0;     // 0.bit. timer1 még nincs bekapcsolva
  18.    
  19.     GPIObits.GP5 = 1;         // GP5 kimenet magas szintű
  20.    
  21.    
  22.     return;
  23. }


Csak magamnak részleteztem ennyire tanulás céljából. Tudom hogy sokkal egyszerűbben is meg lehet oldani, de nekem ez így most átláthatóbb mintha binárisan adtam volna meg a T1CON-t.
Az egyik kérdésem az lenne, hogy a timer1 beállításai így jók-e? A másik hogy ha megszakítás érkezik akkor a PIR1 - TMR1IF bitet kell ellenőrizni? Vagyis nem non-stop pörgetek egy while-t, hanem ha megszakítás történik akkor a proci "szól" a programnak és lefut egy szubrutin ahol ellenőrzöm a TMR1IF bitet?
(#) Bakman válasza niedziela hozzászólására (») Szept 28, 2020
Nem próbáltam de nem tűnik űtrechnikának. A másodlagos oszcillátort (Secondary oscillator) kell bekapcsolni és megmondani a timer1-nek, hogy az órajel onnan jön. Egy trükk van, ha másodpercenkénti megszakítást szeretnél: a Timer 1 számlálóregisztereit fel kell tölteni minden megszakítás után, különben csak két másodpercenként kapsz megszakítást.

tmr1h = 0x80;
tmr1l = 0x00;

Az órakvarc 23 768 Hz-en működik, a Timer 1 regiszterei viszont 65 535-ig számolnak (2^16).
(#) Bakman válasza Firefighter1 hozzászólására (») Aug 22, 2020
Nem értem az egész koncepciót, esetleg te nem érted a SW PWM lényegét. Legfőképpen az kérdés számomra, miért akarsz két szoftveres PWM-et használni, amikor van egy PWM modul is a kontrollerben. Utóbbi kb. 0 erőforrást eszik a kontroller idejéből.

Ha a Timer0 és timer1 órajelét külső forrásra állítod, akkor külön kell biztosítanod az órajelüket.
(#) troby hozzászólása Aug 15, 2020
Sziasztok, el netes kalkulátor alapján összeraktam egy elég gyors timert mert 100-300ns-ot kellene mérnem és az a problémám hogy a főprogramom csak egyszer fut le. Valamit nem jól konfiguráltam esetleg? Egy leegyszerűsített részét beillesztem ide.
  1. #define ledPin 13
  2. void setuptimer1() {
  3.   noInterrupts();
  4.   TCCR1A = 0;
  5.   TCCR1B = 0;
  6.   TCNT1 = 0;
  7.   OCR1A = 1;
  8.   TCCR1B |= (1 << WGM12);
  9.   TCCR1B |= (1 << CS11);
  10.   TIMSK1 |= (1 << OCIE1A);
  11.   interrupts();
  12. }
  13. void setup() {
  14.   pinMode(ledPin, OUTPUT);
  15.   setuptimer1();
  16.   Serial.begin (9600);
  17. }
  18. void loop() {
  19.   Serial.println ("A");
  20. }
  21. ISR(timer1_COMPA_vect) {
  22.   digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
  23. }
(#) mateatek válasza Kovidivi hozzászólására (») Aug 7, 2020
Megkövetlek. Felületesen olvastam el. Túlzottan a timerből indultam ki. Szoftveresen kompenzálja.
Le is teszteltem:

  1. volatile unsigned long ezred = 0;
  2.  
  3. void setup() {
  4.   Serial.begin(115200);
  5.   noInterrupts();
  6.   TCCR1A = 0x2;
  7.   TCCR1B = 0x1A;
  8.   ICR1   = 0x7CF;
  9.   TIMSK1 = 0x2;
  10.   ezred = millis();
  11.   interrupts();
  12. }
  13.  
  14. ISR(timer1_COMPA_vect) {
  15.   ezred++;
  16. }
  17.  
  18. void loop() {
  19.   Serial.println(millis());
  20.   Serial.println(ezred);
  21.   Serial.println("###");
  22.   delay(1000);
  23. }
Következő: »»   2 / 42
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