Fórum témák

» Több friss téma
Fórum
Keresés
Lapozás: OK   1 / 25
(#) glaci hozzászólása Márc 13, 2025

12f683

Sziasztok!
pic12f683 picet használok. A GPIO5 lábat kimenetként szeretném használni, de nem akar kimenetként működni. Igazából lóg a levegőben. A mainban lehet, hogy hiányzik valami.
  1. void main()
  2. {
  3.   OPTION_REG         = 0x82;      //megszakítás a felfutó élnél,  előosztás 1/8
  4.   tmr0=255;
  5.   // IOC= 9;           // megszakítás engedélyezés a 0,3 bemeneteken
  6.   // INTCON=0b11001000;  //GIE és GPIE bitek engedélyével a perifériás megszakítás engedély
  7.  
  8.   INTCON=0b11101000;
  9.   /* INTCON.GIE=1;  //globális megszakítás engedély
  10.    INTCON.PEIE=1;  //perifériás megszakítás engedély
  11.    INTCON.T0IE=1;  //timer0 tulcsordulás megszakítás engedély
  12.                     //A T0IF lábat törölni kell megszakítás után
  13.    INTCON.GPIE=1;  //az input-output lábakon történő változás okozta megszakítás engedély
  14.                     //A GPIF lábat törölni kell megszakítás után  */
  15.    OSCCON=0b01110001;   // 8mhz belső oszcillátor
  16.    CMCON0=7;         //komparátor kikapcsolva
  17.  
  18.    ANSEL=0;          //analóg csatornák kikapcsolva
  19.    //         543210
  20.    //TRISIO=0b00001001;    // 0,3 láb bemenet
  21.    TRISIO=0x9;
  22.    GPIO=0;
  23.    GPIO.GP5=1;
  24.    figyel=0;
  25.    delay_ms(500);
(#) Pali79 válasza Bakman hozzászólására (») Okt 13, 2024
Átírtam, de így sem megy.
  1. HW_PWM_setup
  2.         movlw   b'00000101'
  3.         movwf   RE5PPS
  4.         clrf    CCPTMRS0
  5.         clrf    CCPTMRS1
  6.         movlw   .200
  7.         movwf   T2PR
  8.         movlw   .125
  9.         movwf   CCPR1L
  10.         movwf   CCPR1H
  11.         movlw   b'10001100'
  12.         movwf   CCP1CON
  13.         movlw   b'00000001'
  14.         movwf   T2CLKCON
  15.         movlw   b'10000000'
  16.         movwf   T2CON


Viszont közben lett egy másik probléma is. Beállítottam egy timer0 megszakítást, de ez sem működik. A szimulátor szerint a timer fut, de nem fut megszakításra, mert a bsf PIE0,tmr0IE nem hajtódik végre.

  1. tmr0_setup
  2.         movlw   b'00000000'
  3.         movwf   T0CON0
  4.         movlw   b'01000000'
  5.         movwf   T0CON1
  6.         bsf     INTCON,GIE
  7.         bsf     INTCON,PEIE
  8.         bsf     PIE0,tmr0IE
  9.         bcf     IPR0,tmr0IP
  10.         bsf     T0CON0,T0EN
(#) Taki33 válasza tandem hozzászólására (») Júl 1, 2024
Szia.

Összedobtam egy példát, ami a timer0-át használja, kb. 5 perc múlva kikapcsolja a GP0 lábat, Proteusba teszteltem.

  1. /*
  2.  * File:   main.c
  3.  * Author: taki
  4.  *
  5.  * CPU: PIC 12F675
  6.  * FREQ: 4 MHz belső
  7.  * Compiler: XC8
  8.  * IDE: MPLAB X v4.10
  9.  *
  10.  *                        PIC 12F675
  11.  *                    ------------------
  12.  *                 --|VDD            VSS|--
  13.  *                 --|GP5            GP0|-- LED+
  14.  *                 --|GP4            GP1|--
  15.  *                 --|GP3            GP2|--
  16.  *                    ------------------
  17.  * 5 perces időzítő példa, ami a timer0-át használja
  18.  * kb 5. perc múlva kikapcsolja GP0-án a LED-et.
  19.  *
  20.  * Created on 2024. július 1.
  21.  */
  22.  
  23.  
  24. #include <xc.h>
  25.  
  26. #pragma config FOSC = INTRCIO     // INTOSC oszcillátor; GP4 - GP5 láb I/O
  27. #pragma config WDTE = OFF         // Watchdog Timer Letiltva
  28. #pragma config PWRTE = OFF        // Power-Up Timer Letiltva
  29. #pragma config MCLRE = OFF        // GP3/MCLR láb digitális I/O, MCLR belsőleg VDD-re kötve)
  30. #pragma config BOREN = OFF        // Brown-out Detect Letiltva
  31. #pragma config CP = OFF           // A programmemória kódvédelme kikapcsolva
  32. #pragma config CPD = OFF          // Az adatmemória kódvédelme kikapcsolva
  33.  
  34. #define IDO 29856                 // 5 perc = 300000ms tehát kb. 300000/10.048 = 29856 megszakítás
  35.  
  36. unsigned int time = 0;
  37.  
  38. //Megszakítások
  39.  
  40. void interrupt isr(void)
  41. {
  42.   if (T0IF == 1)                // Timer0 megszakítás 10.048ms-kor
  43.   {
  44.     tmr0 = 99;                  // tmr0 regiszter feltöltése
  45.     T0IF = 0;                   // A TM0 jelzőbit törlése
  46.  
  47.     if (time > 0)               // Ha time értéke nagyobb mint 0 akkor
  48.     {
  49.       time--;                   // eggyel csökkentjük az értékét      
  50.     } else                      // Ha már nem nagyobb akkor kikapcsoljuk a GPIO0 lábat
  51.     {
  52.       GPIO0 = 0;                // GP0 láb alacsony
  53.     }
  54.   }
  55. }
  56.  
  57. //Főprogram
  58.  
  59. void main(void)
  60. {
  61.   VRCON = 0x00;                    // Voltage reference Letiltva
  62.   CMCON = 0b00000111;              // Comparator Letiltva
  63.   ANSEL = 0x00;                    // A/D Letiltva
  64.   GPIO = 0;                        // GPIO Törlése
  65.   TRISIO = 0b00000000;             // összes láb kimenet
  66.   WPU = 0;                         // Felhúzó ellenállások letiltva
  67.   INTCON = 0b10100000;             // Globális Megszakítások Engedélyezve, tmr0 Megszakítás Engedélyezve
  68.   tmr0 = 99;                       // tmr0 regiszter feltöltése, megszakítás minden 10.048ms-kor
  69.   OPTION_REG = 0b00000101;         // Timer0 Indítása, 1:64 előosztó beállítása
  70.   time = IDO;                      // Az time változó feltöltése
  71.   GPIO0  = 1;                      // GP0 láb magas    
  72.  
  73.   while (1)
  74.   {
  75.     //Egyéb utasítások
  76.   }
  77. }
(#) glaci hozzászólása Ápr 15, 2024
Sziasztok!
Sikerült megszakítást kicsiholni picből de a megszakítás mintegy 7sec múlva indul el. Utána rendesen megy. Van rá magyarázat?

  1. void interrupt() iv 0x0004 ics ICS_AUTO
  2.  {
  3.      if(T0IF_bit==1)
  4.      {
  5.          T0IF_bit=0;
  6.          tmr0=6;
  7.              rendben++;
  8.      if(rendben==1000)     //1s
  9.      {
  10.        rendben=0;
  11.        ido++;                  // 120   2óra
  12.        GPIO.GP2=~GPIO.GP2;
  13.          
  14.      }
  15.      }
  16.  }
  17.  
  18.  
  19. void main()
  20. {
  21.   OPTION_REG         = 0x82;
  22.   tmr0=255;
  23.   // IOC= 9;           // megszakítás engedélyezés a 0,3 bemeneteken
  24.   // INTCON=0b11001000;  //GIE és GPIE bitek engedélyével a perifériás megszakítás engedély
  25.  
  26.   INTCON=0b11101000;
  27.   /* INTCON.GIE=1;  //globális megszakítás engedély
  28.    INTCON.PEIE=1;  //perifériás megszakítás engedály
  29.    INTCON.T0IE=1;  //timer0 tulcsordulás megszakítás engedély
  30.                     //A T0IF lábat törölni kell megszakítás után
  31.    INTCON.GPIE=1;  //az input-output lábakon történő változás okozta megszakítás engedély
  32.                     //A GPIF lábat törölni kell megszakítás után  */
  33.    OSCCON=0b01110001;   // 8mhz belső oszcillátor
  34.    CMCON0=7;         //komparátor kikapcsolva
  35.  
  36.    ANSEL=0;          //analóg csatornék kikapcsolva
  37.  
  38.    TRISIO=0b00001001;    // 0,3 láb bemenet
  39.    GPIO=0;
  40.  
  41.    while(1)
  42.    {
  43.        if(ido>60)
  44.        {
  45.          GPIO.GP1=1; ido=0; delay_ms(500); GPIO.GP4=1;
  46.        }
  47.      /*  if(GPIO.GP0==0)
  48.        {
  49.         GPIO.GP1=1; delay_ms(500); GPIO.GP4=1;
  50.        }
  51.        if(GPIO.GP3==0)
  52.        {
  53.         GPIO.GP1=0; delay_ms(100); GPIO.GP4=0;
  54.        } */
  55.    }
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62. }
(#) glaci hozzászólása Ápr 14, 2024
Sziasztok!
Megint bajom támadt a 12F683-mal. Nem tudok megszakítást produkálni. A config word 0FD4, ami 8MHz belső oszcillátort állít be.

  1. int ido, rendben;
  2.  //Timer0
  3. //Prescaler 1:8; tmr0 Preload = 6; Actual Interrupt Time : 1 ms
  4.  
  5. //Place/Copy this part in declaration section
  6.  
  7.  
  8.  
  9. void InitTimer0(){
  10.   OPTION_REG         = 0x82;
  11.   tmr0                 = 6;
  12.   INTCON         = 0xA0;
  13. }
  14.  
  15. void Interrupt(){
  16.   if (T0IF_bit){         //  TMR
  17.     T0IF_bit         = 0;
  18.     tmr0                 = 6;
  19.     //Enter your code here
  20.  
  21.     rendben++;
  22.     if(rendben==1000)     //1s
  23.      {
  24.        rendben=0;
  25.        ido++;                  // 120   2óra
  26.        GPIO.GP2=~GPIO.GP2;
  27.  
  28.      }
  29.    
  30.   }
  31.  
  32. }
  33.  
  34.  
  35.  
  36. void main()
  37. {
  38.  
  39.    IOC= 9;           // megszakítás engedélyezés a 0,3 bemeneteken
  40.    INTCON=0b11001000;  //GIE és GPIE bitek engedélyével a perifériás megszakítás engedély
  41.                         //A GPIF lábat törölni kell megszakítás után
  42.    OSCCON=0b01110001;   // 8mhz belső oszcillátor
  43.    CMCON0=7;
  44.  
  45.    ANSEL=0;
  46.  
  47.    TRISIO=0b00001001;    // 0,3 láb bemenet
  48.    GPIO=0;
  49.    InitTimer0();
  50.  
  51. }


Nem tudom hol hibáztam?
(#) Laja1 válasza Bakman hozzászólására (») Jan 6, 2024
Ez volna a próbaprogram:
  1. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
  2. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  3. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  4. #pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
  5. #pragma config LVP = ON         // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
  6. #pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  7. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  8. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  9.  
  10. #include <xc.h>
  11. #include <pic.h>
  12.  
  13.  
  14.  
  15. #define uzemmod2  PORTBbits.RB5  // 0-100 C
  16.  
  17. #define RD4  PORTDbits.RD4
  18.  
  19. //__CONFIG( FOSC_HS & WDTE_OFF & PWRTE_OFF & CP_OFF & BOREN_ON & LVP_OFF & CPD_OFF & DEBUG_OFF);
  20. #define _XTAL_FREQ 20000000
  21.  
  22.  
  23.  
  24.  
  25.  
  26. int i, n, k,u, m, o, csak;
  27. int long j;
  28. int t=0, flag=0;
  29. unsigned int t2cnt,  sz;
  30.  
  31.  void  __interrupt() megszak (void)
  32.  {
  33.         if(PIR1bits.TMR2IF)
  34.         {
  35.             t2cnt++;
  36.             if(t2cnt==30000){t2cnt=0;flag=1;}// lej?rt 1 min
  37.            
  38.                
  39.           PIR1bits.TMR2IF=0;
  40.          }
  41.  }
  42.  
  43. void main()
  44. {
  45.    
  46.     // OPTION_REG = 0x55; // Set tmr0 configuration and enable PORTB pullups    
  47.      INTCON = 0b11000000; // ' Enable global interrupts, Disables all peripheral interrupts, disable timer0 interrupt        
  48.       //CMCON = 0x07 ;  // anal?g kompar?torok kikapcsolva, RA0-1 digit?lis port!
  49.      
  50.       // timer2 be?ll?t?sa
  51.       PR2=249;                  //timer2 250?rajel ut?n ujrakezdi a sz?mol?st
  52.       T2CON= 0b01001001 ;       //4 el?oszt?  modul on 10 ut?oszt?
  53.       PIE1bits.TMR2IE=1;        // tmr2 irq enable
  54.      
  55.    
  56.     CMCON=0b11000010;
  57.   //  CVRCON=0xC0;
  58.    
  59.     TRISB=0b11111111;
  60.     TRISC=TRISD=0;
  61.     TRISA0=TRISA1=TRISA2=TRISA3=1;
  62.    
  63.    
  64.  
  65.     while (1)
  66.     {        
  67.         // if (uzemmod1==1) u=1;
  68.          if (uzemmod2==1)
  69.          {
  70.           RD4=1;
  71.          T2CONbits.TMR2ON=1;
  72.          }  
  73.          
  74.           if(flag)
  75.           {RD4=0;
  76.          
  77.           }
  78.          
  79.    
  80.          
  81.      
  82.       }
  83.  
  84.  
  85.  
  86.  
  87.  
  88.   }
(#) treshold válasza treshold hozzászólására (») Dec 29, 2023
Úgy tűnik ezzel működik:

PROCESSOR 18F25K50

#include <xc.inc>

goto start

ledRedOn:
bcf TRISC,6
return

ledRedOff:
bsf TRISC, 6
return

start:
bcf LATC, 6 ; Set up the red LED

; Enable Timer 0 as a 16-bit timer with 1:256 prescaler:
; since the instruction speed is 12 MHz, this overflows about
; every 1.4 seconds.
movlw 10000111B
movwf T0CON

mainLoop:
movf tmr0L, W ; Trigger an update of tmr0H

; Blink the red LED with a period of 1.4 s.
btfss tmr0H, 7
rcall ledRedOff
btfsc tmr0H, 7
rcall ledRedOn

goto mainLoop

end

OK.png
    
(#) treshold hozzászólása Dec 29, 2023
Még mindíg a MPLAB X IDE V6.15 assembly-vel küzdök. Nem sikerül a fordítás. Újra installáltam, ellenőríztem a beállítási útvonalakat, de nem sikerül a fordítás. Néztem Youtube videókat is, bár többnyire csak régebbi verziókról van.
Ki tudná próbálni valaki pl az alábbival? Esetleg egy régebbi verzióval is?

#include <p18f25k50.inc>

org 0x2000
goto start

org 0x2020
ledRedOn:
bcf TRISC, 6
return

ledRedOff:
bsf TRISC, 6
return

start:
bcf LATC, 6 ; Set up the red LED

; Enable Timer 0 as a 16-bit timer with 1:256 prescaler:
; since the instruction speed is 12 MHz, this overflows about
; every 1.4 seconds.
movlw b'10000111'
movwf T0CON

mainLoop:
movf tmr0L, W ; Trigger an update of tmr0H

; Blink the red LED with a period of 1.4 s.
btfss tmr0H, 7
rcall ledRedOff
btfsc tmr0H, 7
rcall ledRedOn

goto mainLoop

end
(#) asch válasza sonajkniz hozzászólására (») Okt 29, 2023
Nem vagyok PIC-es, de szerintem:

1. Kell hogy legyen IRQ handler a timer interruptnak. Van? Ez vagy üres legyen, vagy a tmr0IF-et törölni kell benne: lásd adatlap, hogy ez magától törlődik, vagy ha nem, akkor hogyan kell tölölni?
2. Az INTCON-ban a GIE és a tmr0IE bit aktív kell hogy legyen, különben nem lesz timer overflow interrupt.

Én úgy tesztelném először, hogy egyáltalán működik-e a timer, hogy az IRQ-ban egy debug pint billegtetnék, és ezt megfigyelném voltmérővel, vagy szkóppal. Ha ez már biztosan működik, akkor utána vinném csak altatásba a procit.

Szerk.: Bakman válasza érvénytelenítette amit írtam, de már nem törlöm.
A hozzászólás módosítva: Okt 29, 2023
(#) kissi válasza sonajkniz hozzászólására (») Okt 29, 2023
Szia!

tmr0-val külső jelet számoltatsz/figyelsz ?!
A hozzászólás módosítva: Okt 29, 2023
(#) niedziela válasza djadji hozzászólására (») Feb 3, 2023
tmr0-t is be lehet állítani kerek frekvenciára egy sor c-vel, meg némi matekkal.
Csak ahogy mást is, ennek a fránya picnek is az elején kellene kezdeni a tanulását mert igy csak egy sötét folyosón szédelegsz.
(#) don_peter válasza sonajkniz hozzászólására (») Jan 20, 2023
Megnézted a teljes beállításom és kódot a lap tetején lévő első hozzászólásban?
Megszakításban az újra töltés:
  1. if (INTCONbits.tmr0IF)
  2.             {
  3.                     tmr0L = 0x01;   // 200nS / megszakítás
  4.                     Timer0Count++;
  5.                     INTCONbits.tmr0IF = 0;   // clear the flag
  6.             }

Ez 256szor fut le?
Az elő töltés határozza meg, hogy mennyi ideig tart 1 megszakítás nem?
Mindjárt meg méreg egy szkóppal, hogy milyen ciklussal villog a led a megszakításba.
(#) sonajkniz válasza don_peter hozzászólására (») Jan 20, 2023
Idézet:
„Timer0 megszakításának ideje (feljebb a teljes kód): FOSC/4/2/1 vagy is 40MHz/4/2/1 = 5MHz és ebből jön ki az idő, ami 1/5MHz = 200nS”

Szerintem itt van az amit elnéztél. Ha a Timer0 8 bites üzemmódban van, és tmr0 regiszterrel nem csinálsz semmit, akkor a beállításod szerinti megszakítási időd 200nS*256. Azaz 51,2usec lesz.
(#) don_peter válasza asch hozzászólására (») Jan 19, 2023
Indítok egy timer0-át 8bit-es módban. Beállítottam a leggyorsabb megszakításra, amely minimum 200nS / megszakítás. A megszakításban egy változót növelek.
1. timer0 indul
2. 1 byte adat lekérése SPI x 100 alkalom
3. timer0 leállít
Timer0 adatát megkapom: 128nS
Ez úgy jön ki, hogy timer0-ban növelt változó értéke 0.64, ezt úgy kaptam meg, hogy egymás után 100 alkalommal kérdezem le ugyan azt, majd ezt átlagolom. így jön ki a 0.64.
Timer0 200ns/megszakítás, 200*0.64 = 128nS
Minden más értéket is ugyan így mértem.
  1. // Időméréshez látrehozott megszakítás
  2. void HighIntTimer0(void)
  3. {
  4.         // Számoláshoz, 8bit-es mód
  5.         // (FOSC/4) / Prescaler / tmr0H tmr0L
  6.     // (40M/4) /        2               / 1
  7.         INTCON2bits.tmr0IP = 1;         // Timer0 megszakítás magas prioritású legyen
  8.        
  9.         T0CONbits.tmr0ON = 0;           // Timer0 kikapcsolva
  10.         T0CONbits.T08BIT = 1;           // 8 bites mód kiválasztás
  11.         T0CONbits.T0CS = 0;                     // Meghajtás belső órajelről
  12.         T0CONbits.T0SE = 0;                     // Külső órajel fel- vagy lefutó élének választása
  13.         T0CONbits.PSA = 0;                      // Előosztás bekapcsolása
  14.         //Előosztási arány beállítása (000 = 1:2, 001 = 1:4, 010 = 1:8, 011 = 0:16,
  15.                                                                 // 100 = 1:32, 101 = 1:64, 110 = 1:128, 111 = 1:256)
  16.         T0CONbits.T0PS2 = 0;            // Előosztás 1:2 osztásra állítása
  17.         T0CONbits.T0PS1 = 0;
  18.         T0CONbits.T0PS0 = 0;
  19.         INTCONbits.tmr0IE = 1;                  // Timer tiltása
  20.         //tmr0H = 0xCD;
  21.         tmr0L = 0x01;   // 200nS / megszakítás
  22. }

Mérés:
  1. HighIntTimer0();
  2.     Timer0Count = 0;
  3.     MemCim.value = 0x259;
  4.     T0CONbits.tmr0ON = 1;
  5.    
  6.     Sample = MemRead(MemCim);   // 128nS alatt fut le
  7. Sample = MemRead(MemCim);
  8. Sample = MemRead(MemCim);
  9. Sample = MemRead(MemCim);
  10. Sample = MemRead(MemCim);
  11. Sample = MemRead(MemCim);
  12. Sample = MemRead(MemCim);
  13. Sample = MemRead(MemCim);
  14. Sample = MemRead(MemCim);
  15. Sample = MemRead(MemCim);
  16.  
  17. // ...még 10 ilyen 10-es blokk lefele
  18.  
  19. T0CONbits.tmr0ON = 0;

Megszakítás:
  1. if (INTCONbits.tmr0IF)
  2.         {
  3.                 tmr0L = 0x01;   // 200nS / megszakítás
  4.                 Timer0Count++;
  5.                 INTCONbits.tmr0IF = 0;   // clear the flag
  6.         }

Breakpointtal állítom le a programot, debug módban.
A hozzászólás módosítva: Jan 19, 2023
(#) Bakman válasza makait1 hozzászólására (») Nov 9, 2022
Jobb klikk a tmr0 megszakításra -> Tulajdonságok -> Tulajdonságok gomb.

Clock Source Select: Transition on T0CKI pin helyett Internal clock (CLKO)
A hozzászólás módosítva: Nov 9, 2022
(#) 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
(#) 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:
(#) Laja1 hozzászólása Feb 27, 2022
Sziasztok!

Készítettem egy stoppert. Abban tudnátok segíteni, hogy az óra miért siet? 1 óra alatt 11 másodpercet siet.
Ha a PR2-t 249-ről 250-re állítom, akkor meg késik, óránként 7 másodpercet.
PIC16F628A. Belső 4 Mhz órával.
Én így állítottam be:
(Részlet a programból)

void __interrupt() megszak (void)
{
if(PIR1bits.TMR2IF)
{

if(mpcount==100){mpcount=0;mpflag = 1;} // lejárt az 1 sec
PIR1bits.TMR2IF=0;
}
}


void main (void)
{






PCONbits.OSCF=1; // a bels? oszc. 4 Mhz



OPTION_REG = 0x55; // Set tmr0 configuration and enable PORTB pullups
INTCON = 0b11000000; // ' Enable global interrupts, Disables all peripheral interrupts, disable timer0 interrupt
CMCON = 0x07 ; // analóg komparátorok kikapcsolva, RA0-1 digitális port!
PORTB = 0b00000111;
PORTA = 0;
TRISA = 0b00100000; // RA0, RA7 port bemenet, relé vagy LED
TRISB = 0b00001111; // RB2 és RB3 bemenet, a többi kimenet

// timer2 beállítása
PR2=249; //timer2 250órajel után ujrakezdi a számolást
T2CON= 0b01001101 ; //4 el?osztó modul on 10 utóosztó
PIE1bits.TMR2IE=1; // tmr2 irq enable


Köszönöm szépen!
(#) Bakman hozzászólása Feb 20, 2022
Hajónapló kiegészítés:

Az új kontrollerekben a Timer0 modul 8 bites üzemmódban hasonlóan működik mint a Timer2, a tmr0H regiszter mint periódus regiszter funkcionál. Az ehhez kapcsolódó számítást is tudja már a program, lásd melléklet.

A frissített változatok elérhetőek itt: PICTimerCalculator - pCloud mappa.

Telepítéshez semmi extra nem kell. Törlöd a régit, az újat a helyére másolod.
(#) Bakman válasza nedudgi hozzászólására (») Feb 10, 2022
Timer2 esetén van ilyen opció. Timer0 és 1 esetén nincs, marad a preload számítási táblázat.

tmr0 esetén van 8 vagy 16 bit, előosztó, utóosztó, előtöltési lehetőség. 16 bites üzemmód esetén:

16 [prescaler lehetőségek] * 16 [postscaler lehetőségek] * 65536 [preload lehetőség]. Mire ezeken végigszalad a program, lemegy a nap. Pláne azoknál, akik nem kvantumszámítógéppel bírnak, rájuk is kell gondolni. Aki tudja mire való és hogyan kell használni az előtöltést hasznos lehet így is, aki nem, annak lényegtelen a dolog.

szerk.:
A cikk, ahol bemutatom a programot, elbírálás alatt.
A hozzászólás módosítva: Feb 10, 2022
(#) Laja1 hozzászólása Jan 26, 2022
De abban mégis kérném a segítségeteket, hogy miért van az, hogy a stopper szépen számol másodpercenként, akár másfél, két percig is, utána valamiért várakozik 2-3 másodpercet, majd újra szépen fut. Mi lehet ennek az oka?
  1. #include <xc.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. //#define _XTAL_FREQ 4000000 ;
  6. #pragma config FOSC = INTOSCIO     // Oscillator ion bits (RC oscillator)
  7. #pragma config WDTE = OFF    // Watchdog Timer Enable bit (WDT disabled)
  8. #pragma config PWRTE = OFF   // Power-up Timer Enable bit (PWRT disabled)
  9. #pragma config BOREN = OFF   // Brown-out Reset Enable bit (BOR disabled)
  10. #pragma config CP = OFF      // Flash Program Memory Code Protection bit (Code protection off)
  11. #pragma config MCLRE = ON
  12. #pragma config LVP = OFF  
  13.  
  14.  
  15. #define bnyomogomb  PORTBbits.RB2
  16. #define jnyomogomb  PORTBbits.RB1
  17. #define oragomb  PORTBbits.RB0;
  18. #define valtas  PORTBbits.RB3  
  19.  
  20.  
  21. #define __delay_ms(x) _delay((unsigned long)((x)*(8000000/4000.0)))
  22. // set up the timing for the LCD delays
  23. #define LCD_delay 0.05 // ~5mS
  24. #define LCD_Startup 17 // ~15mS
  25.  
  26. // Command set for Hitachi 44780U LCD display controller
  27. #define LCD_CLEAR 0x01  // It clears everythings
  28. #define LCD_HOME 0x02  // set the cursor to first line and first row
  29. #define LCD_CURSOR_BACK 0x10 // moves curson one position back
  30. #define LCD_CURSOR_FWD 0x14 //moves curson one position forward
  31. #define LCD_PAN_LEFT 0x18   // used to scroll text left side to scroll text
  32. #define LCD_PAN_RIGHT 0x1C  // used to scroll text right side to scroll text
  33. #define LCD_CURSOR_OFF 0x0C // stops display curson on screen
  34. #define LCD_CURSOR_ON 0x0E  // turns on cursor display
  35. #define LCD_CURSOR_BLINK 0x0F // curson keeps blinking
  36. #define LCD_CURSOR_LINE2 0xC0  // move curson to scond line or second row
  37.  
  38. // display controller setup commands  page 46 of Hitachi datasheet
  39. #define FUNCTION_SET 0x2C // 4 bit interface, 2 lines, 5x10 font
  40. #define ENTRY_MODE 0x06 // increment mode
  41. #define DISPLAY_SETUP 0x0C // display on, cursor off, blink offd
  42.  
  43. #define LCDLine1() LCDPutCmd(LCD_HOME) // legacy support
  44. #define LCDLine2() LCDPutCmd(LCD_CURSOR_LINE2) // legacy support
  45. #define shift_cursor() LCDPutCmd(LCD_CURSOR_FWD) // legacy support
  46. #define cursor_on() LCDPutCmd(LCD_CURSOR_ON) // legacy support
  47. #define DisplayClr() LCDPutCmd(LCD_CLEAR) // Legacy support
  48.  
  49.  
  50. //----------------------------------------------------------------------
  51. // Definitions specific to the PICDEM 2 Plus
  52. // These apply to the Black (2011) version.
  53. //----------------------------------------------------------------------
  54.  
  55. // single bit for ing command register or data register
  56. #define instr 0
  57. #define data 1
  58.  
  59. // These #defines create the pin connections to the LCD in case they are changed on a future demo board
  60. #define LCD_PORT PORTA
  61. #define LCD_PWR 1 // LCD power pin
  62. #define LCD_EN PORTAbits.RA6 // LCD enable
  63. #define LCD_RW 0 // LCD read/write line
  64. #define LCD_RS PORTAbits.RA7 // LCD register  line
  65. #define led PORTBbits.RB5
  66. #define ledgomb PORTBbits.RB7
  67.  
  68. #define NB_LINES 2 // Number of display lines
  69. #define NB_COL 16 // Number of characters per line
  70.  
  71.    
  72. void LCD_Initialize(void);
  73. void LCDPutChar(char ch);
  74. void LCDPutCmd(char ch);
  75. void LCDPutStr(const char *);
  76. void LCDWriteNibble(char ch, char rs);
  77. void LCDGoto(char pos, char ln);
  78. void UpdateTimer (void) ;
  79. //unsigned int k=0;
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.     /**/
  87.     unsigned char t2cnt,mpflag,mpcount,villog, bgomb, bgombold, jgomb, jgombold, flag,bkeycnt=0, jkeycnt=0, r1cnt,r2cnt,time1=60, time2=30, s,ki, bk=0,
  88.             jk=0, bv=51, jv=51, ogomb, ora, min, sec=0, l, tsec;
  89.      
  90.     void  __interrupt() megszak (void)
  91.     {
  92.         if(PIR1bits.TMR2IF)
  93.         {
  94.             t2cnt++;
  95.             if(t2cnt==10){t2cnt=0;flag |=1;}// lejárt 0,1 sec frissülhet a f?progi
  96.             mpcount++ ;
  97.             if(mpcount==100){mpcount=0;mpflag = 1;} // lejárt az 1 sec        
  98.           PIR1bits.TMR2IF=0;
  99.         }
  100.     }
  101.    
  102.      
  103.     void main (void)
  104.     {
  105.      
  106.      
  107.    
  108.  
  109.  
  110.      
  111.       PCONbits.OSCF=1;  // a bels? oszc. 4 Mhz
  112.      
  113.      
  114.      
  115.       OPTION_REG = 0x55; // Set tmr0 configuration and enable PORTB pullups    
  116.      INTCON = 0b11000000; // ' Enable global interrupts, Disables all peripheral interrupts, disable timer0 interrupt        
  117.       CMCON = 0x07 ;  // analóg komparátorok kikapcsolva, RA0-1 digitális port!
  118.       PORTB = 0b00000111;
  119.        PORTA = 0;
  120.       TRISA = 0b00100000;  //  RA0, RA7 port bemenet, relé vagy LED
  121.       TRISB = 0b00001111; // RB2 és RB3 bemenet, a többi kimenet
  122.      
  123.       // timer2 beállítása
  124.       PR2=249;                  //timer2 250órajel után ujrakezdi a számolást
  125.       T2CON= 0b01001101 ;       //4 el?osztó  modul on 10 utóosztó
  126.       PIE1bits.TMR2IE=1;        // tmr2 irq enable
  127.      
  128.      
  129.        LCD_Initialize();
  130.       while(1)
  131.       {
  132.      
  133.          
  134.           if(mpflag)
  135.            {
  136.                 villog =  ~villog ;   //LED villogtató
  137.                 led =  villog ;
  138.                 mpflag = 0   ;    
  139.            }  
  140.          
  141.           if(flag)              // 0.1 sec lejárt f?program frissítése
  142.           {
  143.             flag=0;
  144.            
  145.             bgombold = bgomb ;
  146.             bgomb = bnyomogomb ;
  147.            
  148.             jgombold = jgomb ;
  149.             jgomb = jnyomogomb ;
  150.             ogomb =oragomb;
  151.            
  152.             if(bgomb == 0 & ogomb ==0) l=1;
  153.              if (l==1)
  154.             {
  155.                
  156.                  
  157.                  UpdateTimer ();
  158.                
  159.                     LCDGoto(4,1);
  160.                     LCDPutChar((ora/10)+0x30);
  161.                     LCDPutChar((ora%10)+0x30);
  162.                     LCDPutChar(0x3A);
  163.                
  164.                    
  165.                     LCDPutChar((min/10)+0x30);
  166.                     LCDPutChar((min%10)+0x30);
  167.                     LCDPutChar(0x3A);
  168.                
  169.                    
  170.                     LCDPutChar((sec/10)+0x30);
  171.                     LCDPutChar((sec%10)+0x30);
  172.                    
  173.             }
  174.            
  175.                
  176.                
  177.                
  178.                
  179.            
  180.             if (bgomb == 0 & bgombold == 1 /*& bv>50 */)   //lenyomtuk a gombot, magasból alacsony szintre vált a bemenet
  181.             {  bv=0;  
  182.                 if (valtas) bk--;
  183.                 else        bk++;
  184.                 bkeycnt=0;
  185.          
  186.             }
  187.              bv++;  
  188.            
  189.             if(bgomb == 0)     //ha még mindig nyomva
  190.             {
  191.                
  192.                  
  193.                 bkeycnt++;
  194.              
  195.                  
  196.             }
  197.              
  198.              
  199.          
  200.             if (bgomb == 1 & bgombold == 0)   //elengedtük a gombot, alacsonyból magas szintre vált a bemenet    
  201.             {
  202.                
  203.                
  204.                 if(bkeycnt>50) //sokáig nyomva volt
  205.                 {
  206.                    ledgomb=1;
  207.                    bk=0;
  208.                    
  209.                  LCDGoto(0,0);
  210.                  LCDPutChar(0x30);
  211.                   LCDPutStr (" ");
  212.                 }
  213.                 else
  214.                 {  
  215.                    
  216.                 LCDGoto(0,0);
  217.                 if(bk<10) LCDPutChar(bk+0x30);
  218.                 else
  219.                     {LCDPutChar((bk/10)+0x30);
  220.                     LCDPutChar((bk%10)+0x30);
  221.                 }  }
  222.                  
  223.          
  224.             }  
  225.           if (jgomb == 0 & jgombold == 1 /*& jv>50 */)   //lenyomtuk a gombot, magasból alacsony szintre vált a bemenet
  226.             {  jv=0;
  227.               if (valtas) jk--;
  228.                 else        jk++;
  229.              
  230.                 jkeycnt=0;
  231.          
  232.             }
  233.                
  234.              jv++;
  235.             if(jgomb == 0)     //ha még mindig nyomva
  236.             {
  237.                
  238.                  
  239.                 jkeycnt++;
  240.              
  241.                  
  242.             }
  243.              
  244.              
  245.          
  246.             if (jgomb == 1 & jgombold == 0)   //elengedtük a gombot, alacsonyból magas szintre vált a bemenet    
  247.             {
  248.                
  249.                
  250.                 if(jkeycnt>50) //sokáig nyomva volt
  251.                 {
  252.                    ledgomb=1;
  253.                    jk=0;
  254.                    
  255.                  LCDGoto(14,0);
  256.                  LCDPutChar(0x30);
  257.                  LCDPutStr (" ");
  258.                 }
  259.                 else
  260.                 {
  261.                 LCDGoto(14,0);
  262.                 if(jk<10) LCDPutChar(jk+0x30);
  263.                 else
  264.                     {LCDPutChar((jk/10)+0x30);
  265.                     LCDPutChar((jk%10)+0x30);
  266.                 }  }
  267.                  
  268.          
  269.             }  
  270.             if (jk==bk & bk>0)
  271.             {
  272.                 LCDGoto(5,0);
  273.                 LCDPutStr ("EGYENLo");
  274.                
  275.             }
  276.            
  277.             if (abs(jk-bk)>=10)
  278.             {LCDGoto(5,0);
  279.                 LCDPutStr ("MOCSING");
  280.                
  281.             }
  282.             if (jk!=bk & abs(jk-bk)<10)
  283.                 {LCDGoto(5,0);
  284.                 LCDPutStr ("       ");}
  285.       }
  286.      
  287.     }
  288.     }
  289.    
  290. void LCD_Initialize()
  291. {
  292. // clear latches before enabling TRIS bits
  293. //LCD_PORT = 0;
  294.     PORTAbits.RA0=0;
  295.     PORTAbits.RA1=0;
  296.     PORTAbits.RA2=0;
  297.     PORTAbits.RA3=0;
  298.     PORTAbits.RA6=0;
  299.     PORTAbits.RA7=0;
  300.  
  301. TRISA = 0b00100000;
  302.  
  303. // power up the LCD
  304. //LCD_PWR = 1;
  305.  
  306. // required by display controller to allow power to stabilize
  307. __delay_ms(LCD_Startup);
  308.  
  309. // required by display initialization
  310. LCDPutCmd(0x32);
  311.  
  312. // set interface size, # of lines and font
  313. LCDPutCmd(FUNCTION_SET);
  314.  
  315. // turn on display and sets up cursor
  316. LCDPutCmd(DISPLAY_SETUP);
  317.  
  318. DisplayClr();
  319.  
  320. // set cursor movement direction
  321. LCDPutCmd(ENTRY_MODE);
  322.  
  323. }
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330. void LCDWriteNibble(char ch, char rs)
  331. {
  332. // always send the upper nibble
  333. ch = (ch >> 4);
  334.  
  335. // mask off the nibble to be transmitted
  336. ch = (ch & 0x0F);
  337.  
  338. // clear the lower half of LCD_PORT
  339. LCD_PORT = (LCD_PORT & 0xF0);
  340.  
  341. // move the nibble onto LCD_PORT
  342. LCD_PORT = (LCD_PORT | ch);
  343.  
  344. // set data/instr bit to 0 = insructions; 1 = data
  345. LCD_RS = rs;
  346.  
  347. // RW - set write mode
  348. //LCD_RW = 0;
  349.  
  350. // set up enable before writing nibble
  351. LCD_EN = 1;
  352.  
  353. // turn off enable after write of nibble
  354. LCD_EN = 0;
  355. }
  356.  
  357. void LCDPutChar(char ch)
  358. {
  359. __delay_ms(LCD_delay);
  360.  
  361. //Send higher nibble first
  362. LCDWriteNibble(ch,data);
  363.  
  364. //get the lower nibble
  365. ch = (ch << 4);
  366.  
  367. // Now send the low nibble
  368. LCDWriteNibble(ch,data);
  369. }
  370.  
  371.  
  372. void LCDPutCmd(char ch)
  373. {
  374. __delay_ms(LCD_delay);
  375.  
  376. //Send the higher nibble
  377. LCDWriteNibble(ch,instr);
  378.  
  379. //get the lower nibble
  380. ch = (ch << 4);
  381.  
  382. __delay_ms(1);
  383.  
  384. //Now send the lower nibble
  385. LCDWriteNibble(ch,instr);
  386. }
  387.  
  388.  
  389. void LCDPutStr(const char *str)
  390. {
  391. char i=0;
  392.  
  393. // While string has not been fully traveresed
  394. while (str[i])
  395. {
  396. // Go display current char
  397. LCDPutChar(str[i++]);
  398. }
  399.  
  400. }
  401.  
  402. void LCDGoto(char pos,char ln)
  403. {
  404. // if incorrect line or column
  405. if ((ln > (NB_LINES-1)) || (pos > (NB_COL-1)))
  406. {
  407. // Just do nothing
  408. return;
  409. }
  410.  
  411. // LCD_Goto command
  412. LCDPutCmd((ln == 1) ? (0xC0 | pos) : (0x80 | pos));
  413.  
  414. // Wait for the LCD to finish
  415. __delay_ms(LCD_delay);
  416. }
  417.  
  418.  
  419. void UpdateTimer (void)
  420. {
  421.      if(mpflag)
  422.                  {
  423.                     sec++;
  424.                 mpflag = 0   ;    
  425.                  }  
  426.    
  427.                
  428.                    
  429.                if (sec==60)
  430.                 {sec=0; min++;}
  431.                
  432.                 if (min==60)
  433.                 {min=0; ora++;}
  434.                
  435.                if (ora==24)  ora= 0;  
  436. }
(#) Laja1 válasza Hp41C hozzászólására (») Jan 23, 2022
PIC16F877A-an fut ez a megoldás. Én csak a PORT-okat írtam át.
Most csináltam egy olyat, hogy a PORTA-n van az LCD, a gombok a PORTB-n. Mindent lecsupaszítottam, csak a Hello World-t kellene kiírnia, de már ezt se tudja. Nem tudom, mi lehet a baja.
  1. #include <xc.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5.  
  6. #pragma config FOSC = INTOSCIO     // Oscillator ion bits (RC oscillator)
  7. #pragma config WDTE = OFF    // Watchdog Timer Enable bit (WDT disabled)
  8. #pragma config PWRTE = OFF   // Power-up Timer Enable bit (PWRT disabled)
  9. #pragma config BOREN = OFF   // Brown-out Reset Enable bit (BOR disabled)
  10. #pragma config CP = OFF      // Flash Program Memory Code Protection bit (Code protection off)
  11. #pragma config MCLRE = ON
  12. #pragma config LVP = OFF  
  13.  
  14.  
  15. #define bgomb  PORTBbits.RB2
  16. #define jobbgomb  PORTBbits.RB1
  17. #define oragomb  PORTAbits.RB0
  18. #define valtas  PORTAbits.RA7  
  19.  
  20.  
  21. #define __delay_ms(x) _delay((unsigned long)((x)*(8000000/4000.0)))
  22. // set up the timing for the LCD delays
  23. #define LCD_delay 5 // ~5mS
  24. #define LCD_Startup 15 // ~15mS
  25.  
  26. // Command set for Hitachi 44780U LCD display controller
  27. #define LCD_CLEAR 0x01  // It clears everythings
  28. #define LCD_HOME 0x02  // set the cursor to first line and first row
  29. #define LCD_CURSOR_BACK 0x10 // moves curson one position back
  30. #define LCD_CURSOR_FWD 0x14 //moves curson one position forward
  31. #define LCD_PAN_LEFT 0x18   // used to scroll text left side to scroll text
  32. #define LCD_PAN_RIGHT 0x1C  // used to scroll text right side to scroll text
  33. #define LCD_CURSOR_OFF 0x0C // stops display curson on screen
  34. #define LCD_CURSOR_ON 0x0E  // turns on cursor display
  35. #define LCD_CURSOR_BLINK 0x0F // curson keeps blinking
  36. #define LCD_CURSOR_LINE2 0xC0  // move curson to scond line or second row
  37.  
  38. // display controller setup commands  page 46 of Hitachi datasheet
  39. #define FUNCTION_SET 0x2C // 4 bit interface, 2 lines, 5x10 font
  40. #define ENTRY_MODE 0x06 // increment mode
  41. #define DISPLAY_SETUP 0x0C // display on, cursor off, blink offd
  42.  
  43. #define LCDLine1() LCDPutCmd(LCD_HOME) // legacy support
  44. #define LCDLine2() LCDPutCmd(LCD_CURSOR_LINE2) // legacy support
  45. #define shift_cursor() LCDPutCmd(LCD_CURSOR_FWD) // legacy support
  46. #define cursor_on() LCDPutCmd(LCD_CURSOR_ON) // legacy support
  47. #define DisplayClr() LCDPutCmd(LCD_CLEAR) // Legacy support
  48.  
  49.  
  50.  
  51.  
  52. // single bit for ing command register or data register
  53. #define instr 0
  54. #define data 1
  55.  
  56. // These #defines create the pin connections to the LCD in case they are changed on a future demo board
  57. #define LCD_PORT PORTA
  58. #define LCD_PWR 1 // LCD power pin
  59. #define LCD_EN PORTAbits.RA6 // LCD enable
  60. #define LCD_RW 0 // LCD read/write line
  61. #define LCD_RS PORTAbits.RA4 // LCD register  line
  62. #define led PORTAbits.RA7
  63.  
  64. #define NB_LINES 2 // Number of display lines
  65. #define NB_COL 16 // Number of characters per line
  66.  
  67.    
  68. void LCD_Initialize(void);
  69. void LCDPutChar(char ch);
  70. void LCDPutCmd(char ch);
  71. void LCDPutStr(const char *);
  72. void LCDWriteNibble(char ch, char rs);
  73. void LCDGoto(char pos, char ln);
  74. unsigned int k=0;
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.     /**/
  82.     unsigned char t2cnt,mpflag,mpcount,villog, bnyomogomb, bgombold,flag,keycnt,r1cnt,r2cnt,time1=60, time2=30, s,ki,  max;
  83.      
  84.  
  85.      
  86.     void main (void)
  87.     {
  88.      
  89.      
  90.    
  91.  
  92.  
  93.      
  94.       PCONbits.OSCF=1;  // a bels? oszc. 4 Mhz
  95.      
  96.      
  97.      
  98.       OPTION_REG = 0x55; // Set tmr0 configuration and enable PORTB pullups    
  99.          
  100.       CMCON = 0x07 ;  // analóg komparátorok kikapcsolva, RA0-1 digitális port!
  101.       PORTB = 0b00000111;
  102.        PORTA = 0;
  103.       TRISA = 0b00000000;  //  RA0, RA7 port bemenet, relé vagy LED
  104.       TRISB = 0b00001111; // RB2 és RB3 bemenet, a többi kimenet
  105.      
  106.      
  107.        LCD_Initialize();
  108.       while(1)
  109.       {
  110.       LCDPutStr(" Hello World!");
  111.        __delay_ms(3000);
  112.          
  113.        
  114.      
  115.     }
  116.     }
  117.    
  118. void LCD_Initialize()
  119. {
  120. // clear latches before enabling TRIS bits
  121. LCD_PORT = 0;
  122.  
  123. TRISA = 0b00000000;
  124.  
  125. // power up the LCD
  126. //LCD_PWR = 1;
  127.  
  128. // required by display controller to allow power to stabilize
  129. __delay_ms(LCD_Startup);
  130.  
  131. // required by display initialization
  132. LCDPutCmd(0x32);
  133.  
  134. // set interface size, # of lines and font
  135. LCDPutCmd(FUNCTION_SET);
  136.  
  137. // turn on display and sets up cursor
  138. LCDPutCmd(DISPLAY_SETUP);
  139.  
  140. DisplayClr();
  141.  
  142. // set cursor movement direction
  143. LCDPutCmd(ENTRY_MODE);
  144.  
  145. }
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152. void LCDWriteNibble(char ch, char rs)
  153. {
  154. // always send the upper nibble
  155. ch = (ch >> 4);
  156.  
  157. // mask off the nibble to be transmitted
  158. ch = (ch & 0x0F);
  159.  
  160. // clear the lower half of LCD_PORT
  161. LCD_PORT = (LCD_PORT & 0xF0);
  162.  
  163. // move the nibble onto LCD_PORT
  164. LCD_PORT = (LCD_PORT | ch);
  165.  
  166. // set data/instr bit to 0 = insructions; 1 = data
  167. LCD_RS = rs;
  168.  
  169. // RW - set write mode
  170. //LCD_RW = 0;
  171.  
  172. // set up enable before writing nibble
  173. LCD_EN = 1;
  174.  
  175. // turn off enable after write of nibble
  176. LCD_EN = 0;
  177. }
  178.  
  179. void LCDPutChar(char ch)
  180. {
  181. __delay_ms(LCD_delay);
  182.  
  183. //Send higher nibble first
  184. LCDWriteNibble(ch,data);
  185.  
  186. //get the lower nibble
  187. ch = (ch << 4);
  188.  
  189. // Now send the low nibble
  190. LCDWriteNibble(ch,data);
  191. }
  192.  
  193.  
  194. void LCDPutCmd(char ch)
  195. {
  196. __delay_ms(LCD_delay);
  197.  
  198. //Send the higher nibble
  199. LCDWriteNibble(ch,instr);
  200.  
  201. //get the lower nibble
  202. ch = (ch << 4);
  203.  
  204. __delay_ms(1);
  205.  
  206. //Now send the lower nibble
  207. LCDWriteNibble(ch,instr);
  208. }
  209.  
  210.  
  211. void LCDPutStr(const char *str)
  212. {
  213. char i=0;
  214.  
  215. // While string has not been fully traveresed
  216. while (str[i])
  217. {
  218. // Go display current char
  219. LCDPutChar(str[i++]);
  220. }
  221.  
  222. }
  223.  
  224. void LCDGoto(char pos,char ln)
  225. {
  226. // if incorrect line or column
  227. if ((ln > (NB_LINES-1)) || (pos > (NB_COL-1)))
  228. {
  229. // Just do nothing
  230. return;
  231. }
  232.  
  233. // LCD_Goto command
  234. LCDPutCmd((ln == 1) ? (0xC0 | pos) : (0x80 | pos));
  235.  
  236. // Wait for the LCD to finish
  237. __delay_ms(LCD_delay);
  238. }
(#) Laja1 hozzászólása Jan 21, 2022
Sziasztok!

Tudnátok segíteni, hogy az LCD-re miért nem írja ki a "k" értékét? Szerintem az LCD iniciálásánál lehet a probléma az LCD_PORT-nál. Nem igazán értem, hogy ott mit kellene megadni.
Köszönöm!
  1. #include <xc.h>
  2. //#include <stdio.h>
  3. //#include <string.h>
  4. //#include <stdlib.h>
  5. //#define _XTAL_FREQ 4000000 ;
  6. #pragma config FOSC = INTOSCIO     // Oscillator ion bits (RC oscillator)
  7. #pragma config WDTE = OFF    // Watchdog Timer Enable bit (WDT disabled)
  8. #pragma config PWRTE = OFF   // Power-up Timer Enable bit (PWRT disabled)
  9. #pragma config BOREN = OFF   // Brown-out Reset Enable bit (BOR disabled)
  10. #pragma config CP = OFF      // Flash Program Memory Code Protection bit (Code protection off)
  11. #pragma config MCLRE = ON
  12. #pragma config LVP = OFF  
  13.  
  14.  
  15. #define bgomb  PORTBbits.RB2
  16. #define jobbgomb  PORTBbits.RB1
  17. #define oragomb  PORTAbits.RB0
  18. #define valtas  PORTAbits.RA7  
  19.  
  20.  
  21. #define __delay_ms(x) _delay((unsigned long)((x)*(4000000/4000.0)))
  22. // set up the timing for the LCD delays
  23. #define LCD_delay 5 // ~5mS
  24. #define LCD_Startup 15 // ~15mS
  25.  
  26. // Command set for Hitachi 44780U LCD display controller
  27. #define LCD_CLEAR 0x01  // It clears everythings
  28. #define LCD_HOME 0x02  // set the cursor to first line and first row
  29. #define LCD_CURSOR_BACK 0x10 // moves curson one position back
  30. #define LCD_CURSOR_FWD 0x14 //moves curson one position forward
  31. #define LCD_PAN_LEFT 0x18   // used to scroll text left side to scroll text
  32. #define LCD_PAN_RIGHT 0x1C  // used to scroll text right side to scroll text
  33. #define LCD_CURSOR_OFF 0x0C // stops display curson on screen
  34. #define LCD_CURSOR_ON 0x0E  // turns on cursor display
  35. #define LCD_CURSOR_BLINK 0x0F // curson keeps blinking
  36. #define LCD_CURSOR_LINE2 0xC0  // move curson to scond line or second row
  37.  
  38. // display controller setup commands  page 46 of Hitachi datasheet
  39. #define FUNCTION_SET 0x2C // 4 bit interface, 2 lines, 5x10 font
  40. #define ENTRY_MODE 0x06 // increment mode
  41. #define DISPLAY_SETUP 0x0C // display on, cursor off, blink offd
  42.  
  43. #define LCDLine1() LCDPutCmd(LCD_HOME) // legacy support
  44. #define LCDLine2() LCDPutCmd(LCD_CURSOR_LINE2) // legacy support
  45. #define shift_cursor() LCDPutCmd(LCD_CURSOR_FWD) // legacy support
  46. #define cursor_on() LCDPutCmd(LCD_CURSOR_ON) // legacy support
  47. #define DisplayClr() LCDPutCmd(LCD_CLEAR) // Legacy support
  48.  
  49.  
  50. //----------------------------------------------------------------------
  51. // Definitions specific to the PICDEM 2 Plus
  52. // These apply to the Black (2011) version.
  53. //----------------------------------------------------------------------
  54.  
  55. // single bit for ing command register or data register
  56. #define instr 0
  57. #define data 1
  58.  
  59. // These #defines create the pin connections to the LCD in case they are changed on a future demo board
  60. #define LCD_PORT PORTBbits.RB4, PORTBbits.RB5,PORTBbits.RB6,PORTBbits.RB7
  61. #define LCD_PWR 1 // LCD power pin
  62. #define LCD_EN PORTBbits.RB3 // LCD enable
  63. #define LCD_RW 0 // LCD read/write line
  64. #define LCD_RS PORTAbits.RA0 // LCD register  line
  65.  
  66. #define NB_LINES 2 // Number of display lines
  67. #define NB_COL 16 // Number of characters per line
  68.  
  69.    
  70. void LCD_Initialize(void);
  71. void LCDPutChar(char ch);
  72. void LCDPutCmd(char ch);
  73. void LCDPutStr(const char *);
  74. void LCDWriteNibble(char ch, char rs);
  75. void LCDGoto(char pos, char ln);
  76. unsigned int k=0;
  77.  
  78.  
  79.  
  80. void LCD_Initialize()
  81. {
  82. // clear latches before enabling TRIS bits
  83. LCD_PORT = 0;
  84.  
  85. TRISB = 0b00000111;
  86.  
  87. // power up the LCD
  88. //LCD_PWR = 1;
  89.  
  90. // required by display controller to allow power to stabilize
  91. __delay_ms(LCD_Startup);
  92.  
  93. // required by display initialization
  94. LCDPutCmd(0x32);
  95.  
  96. // set interface size, # of lines and font
  97. LCDPutCmd(FUNCTION_SET);
  98.  
  99. // turn on display and sets up cursor
  100. LCDPutCmd(DISPLAY_SETUP);
  101.  
  102. DisplayClr();
  103.  
  104. // set cursor movement direction
  105. LCDPutCmd(ENTRY_MODE);
  106.  
  107. }
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114. void LCDWriteNibble(char ch, char rs)
  115. {
  116. // always send the upper nibble
  117. ch = (ch >> 4);
  118.  
  119. // mask off the nibble to be transmitted
  120. ch = (ch & 0x0F);
  121.  
  122. // clear the lower half of LCD_PORT
  123. LCD_PORT = (LCD_PORT & 0xF0);
  124.  
  125. // move the nibble onto LCD_PORT
  126. LCD_PORT = (LCD_PORT | ch);
  127.  
  128. // set data/instr bit to 0 = insructions; 1 = data
  129. LCD_RS = rs;
  130.  
  131. // RW - set write mode
  132. //LCD_RW = 0;
  133.  
  134. // set up enable before writing nibble
  135. LCD_EN = 1;
  136.  
  137. // turn off enable after write of nibble
  138. LCD_EN = 0;
  139. }
  140.  
  141. void LCDPutChar(char ch)
  142. {
  143. __delay_ms(LCD_delay);
  144.  
  145. //Send higher nibble first
  146. LCDWriteNibble(ch,data);
  147.  
  148. //get the lower nibble
  149. ch = (ch << 4);
  150.  
  151. // Now send the low nibble
  152. LCDWriteNibble(ch,data);
  153. }
  154.  
  155.  
  156. void LCDPutCmd(char ch)
  157. {
  158. __delay_ms(LCD_delay);
  159.  
  160. //Send the higher nibble
  161. LCDWriteNibble(ch,instr);
  162.  
  163. //get the lower nibble
  164. ch = (ch << 4);
  165.  
  166. __delay_ms(1);
  167.  
  168. //Now send the lower nibble
  169. LCDWriteNibble(ch,instr);
  170. }
  171.  
  172.  
  173. void LCDPutStr(const char *str)
  174. {
  175. char i=0;
  176.  
  177. // While string has not been fully traveresed
  178. while (str[i])
  179. {
  180. // Go display current char
  181. LCDPutChar(str[i++]);
  182. }
  183.  
  184. }
  185.  
  186. void LCDGoto(char pos,char ln)
  187. {
  188. // if incorrect line or column
  189. if ((ln > (NB_LINES-1)) || (pos > (NB_COL-1)))
  190. {
  191. // Just do nothing
  192. return;
  193. }
  194.  
  195. // LCD_Goto command
  196. LCDPutCmd((ln == 1) ? (0xC0 | pos) : (0x80 | pos));
  197.  
  198. // Wait for the LCD to finish
  199. __delay_ms(LCD_delay);
  200. }
  201.  
  202.  
  203.  
  204.     /**/
  205.     unsigned char t2cnt,mpflag,mpcount,villog, bnyomogomb, bgombold,flag,keycnt,r1cnt,r2cnt,time1=60, time2=30, s,ki, led, max;
  206.      
  207.     void  __interrupt() megszak (void)
  208.     {
  209.         if(PIR1bits.TMR2IF)
  210.         {
  211.             t2cnt++;
  212.             if(t2cnt==10){t2cnt=0;flag |=1;}// lejárt 0,1 sec frissülhet a f?progi
  213.             mpcount++ ;
  214.             if(mpcount==100){mpcount=0;mpflag = 1;} // lejárt az 1 sec        
  215.           PIR1bits.TMR2IF=0;
  216.         }
  217.     }
  218.    
  219.      
  220.     void main (void)
  221.     {
  222.      
  223.      
  224.    
  225.  
  226.  
  227.      
  228.       PCONbits.OSCF=1;  // a bels? oszc. 4 Mhz
  229.       OPTION_REG = 0x55; // Set tmr0 configuration and enable PORTB pullups    
  230.       INTCON = 0b11000000; // ' Enable global interrupts, Disables all peripheral interrupts, disable timer0 interrupt        
  231.       CMCON = 0x07 ;  // analóg komparátorok kikapcsolva, RA0-1 digitális port!
  232.       PORTB = 0b00000111;
  233.       TRISA = 0b10000000;  //  RA0, RA7 port bemenet, relé vagy LED
  234.       TRISB = 0b00000111; // RB2 és RB3 bemenet, a többi kimenet
  235.      
  236.       // timer2 beállítása
  237.       PR2=249;                  //timer2 250órajel után ujrakezdi a számolást
  238.       T2CON= 0b01001101 ;       //4 el?osztó  modul on 10 utóosztó
  239.       PIE1bits.TMR2IE=1;        // tmr2 irq enable
  240.      
  241.       LCD_Initialize();
  242.      
  243.       while(1)
  244.       {
  245.          
  246.           if(mpflag)
  247.            {
  248.                 villog =  ~villog ;   //LED villogtató
  249.                // led2 =  villog ;
  250.                 mpflag = 0   ;    
  251.            }
  252.          
  253.           if(flag)              // 0.1 sec lejárt f?program frissítése
  254.           {
  255.             flag=0;
  256.             bgombold = bgomb ;
  257.             bgomb = bnyomogomb ;
  258.            
  259.             if (bgomb == 0 & bgombold == 1)   //lenyomtuk a gombot, magasból alacsony szintre vált a bemenet
  260.             {
  261.                LCDGoto(3,1);
  262.                 LCDPutStr(" SLTisztaterter");
  263.                
  264.                
  265.             }
  266.            
  267.             if(bgomb == 0)     //ha még mindig nyomva
  268.             {
  269.                
  270.                  
  271.                 keycnt++;
  272.                 if(keycnt>5){led=1;  
  273.                 // rele2=1;
  274.                 r1cnt++ ; r2cnt++;}
  275.                         //0.5 secnél led on késleltetés frissítés felfüggesztve
  276.                    
  277.               if (keycnt > max)   //100x0.1 mp, azaz 10 mp az alap id?, ha ezt túllépjük, akkor növeljük a bekapcsolási id?t
  278.               {keycnt = max;
  279.                  
  280.              
  281.               led=0; }
  282.                  
  283.             }
  284.              
  285.              
  286.          
  287.             if (bgomb == 1 & bgombold == 0)   //elengedtük a gombot, alacsonyból magas szintre vált a bemenet    
  288.             {
  289.                
  290.                
  291.                 if(keycnt>5) //sokáig nyomva volt
  292.                 {
  293.                  
  294.                     k==0;
  295.                    
  296.                  
  297.                 }
  298.                 k++;
  299.                 LCDGoto(3,1);
  300.                 LCDPutStr(" SL Tisztaterte");
  301.                 if(k<10) LCDPutChar(k+0x30);
  302.                 else
  303.                     {LCDPutChar((k/10)+0x30);
  304.                     LCDPutChar((k%10)+0x30);
  305.                     }  
  306.            
  307.      
  308.            
  309.            
  310.          
  311.          
  312.            
  313.          
  314.                
  315.             }  
  316.          
  317.          
  318.       }
  319.      
  320.     }
  321.     }
(#) kaqkk válasza Bakman hozzászólására (») Dec 25, 2020
Melyik az a program ami nem úgy néz ki ? A villogó tmr0 nevű lcd példa csak segéd változót használ a kijelző "mozgatásához" a megszakítás még csak makróhívást sem tartalmaz , most tegyél fel olyan példát ami szerintünk jó.
A hozzászólás módosítva: Dec 25, 2020
(#) kaqkk válasza Bakman hozzászólására (») Dec 25, 2020
Idézet:
„Azt írod, nem megszakításból csinálod a multiplexelést,”
Ezt hol írtam ?
Mi az ami zavaros ? Azt írtam hogy a multiplex a tmr0 ból segédváltozóval van vezérelve , az "óra" meg a tmr2 ből ... Egyébként meg az a lényeg hogy a kérdező megkapta a választ a többivel meg nem törődünk ...
A hozzászólás módosítva: Dec 25, 2020
(#) kaqkk válasza Bakman hozzászólására (») Dec 25, 2020
Láttad a fájlt amit feltettem ? Ahhoz írd hozzá a tmr0-t( tuti nem fog ugatni a fordító) Egy szóval nem mondtam hogy a megszakításban akarom kezelni az LCD-t Sőt a multiplex vezérléseim is csak az időzítést (léptetést) kapják a megszakításból teljesen külön makróban dolgoznak ! A villogtatásról volt szó ráadásul segédváltozóval .
A hozzászólás módosítva: Dec 25, 2020
(#) kaqkk válasza Bakman hozzászólására (») Dec 25, 2020
Mondjuk ez nekünk természetes hogy segédváltozóval villogtatjuk (ott van az x változó én tmr0 ból csinálnám) és ha szükség van rendes megszakításra azt a tmr2 ből intézném . De mivel "csak" menü lesz ezért elég ha időzítést használ .
A hozzászólás módosítva: Dec 25, 2020
(#) eSDi válasza Peet19 hozzászólására (») Dec 18, 2020
Hali!

Úgy látom a legtöbb kérdésre már választ kaptál.

Ennél a PIC-nél a Timer0 16bit-es módjánál a tmr0H egy átmeneti puffer, a tmr0L olvasásakor kerül bele az aktuális érték (azt hiszem debug-kor nem is látod számlálni a tmr0H-t), illetve a tmr0L beírásakor kerül át a valódi regiszterbe a tmr0H-ból. Így biztosítják a pontos érték kiolvasását/beírását.
Ez a puffer a timerhez tartozik, nem foglal több memóriát. Lásd adatlap.

Nekem van olyan programom, ahol fix 20ms a ciklusidő. Ezt egy timer hozza létre megszakítással. Minden művelet ebben a 20ms-ben történik (kicsit PLC szerűen), nem tudom mennyi idő alatt, sosem mértem meg. Itt semmit nem adok át a fő programnak. A fő program csak az őrkutya buksiját simogatja állandóan.

Megszakításban a hosszú időzítéseket kell kerülni, mert akkor a fő programodat úgy fogod látni, mintha akadna/lefagyna.
(#) Hp41C válasza Peet19 hozzászólására (») Dec 17, 2020
  1. void Isr(void){

E sorhoz több utasítás is fordul. Menteni kell a W és a STATUS regiszterek értékét. Minimálisan 3 utasítás kell hozzá, de a fordító beállításai több munkát is adhatnak.
  1. if(PIR0bits.tmr0IF){

A bit vizsgálata valóban 1 utasítás, de a feltétel nem teljesülésekor ugrani kell, így 2 utasításnyi időt kell számolni.
  1. tmr0H     = 255;

Tudni kellene a fhasznált kontroller típusát. PIC18 esetén 1, PIC12-PIC16 esetén 2 utasítás.
  1. tmr0L     = 5;

2 utasítás.
  1. tmr0_cnt++;

Minimum 1 utasítás, de függ attól, hogy hova foglaltuk a változót - bankváltás.
  1. PIR0bits.tmr0IF = 0;

Minimum 1 utasítás, de függ attól, hogy hova foglaltuk a változót - bankváltás.
  1. }

A visszatéréskor a mentett értékeket vissza kell állítani a STAUS és a W regiszterekbe, ill. amit még előírt a fordító. Minimum 4 utasítás és még egy a retfie.

Az MpLab -ban van lehetőség programrészletek futási idejét "megmérni". Ki kell választani a Simulator -t nyomkövetőnek, újra kell fordítania kódot. A rutin elejére kell állítani a programszámlálót. Be kell állítani az órajel frekvenciáját és el kell helyezni egy töréspontot a rutin végére. A Stopwatch ablakot megnyitva láthatjuk a végrehajtott utasítások számát és idejét is.
A hozzászólás módosítva: Dec 17, 2020
(#) Peet19 válasza eSDi hozzászólására (») Dec 17, 2020
Még valamit nem értek, Bocsi
Idézlek:
Idézet:
„A tmr0H-t előbb kell beírni, mert az pufferelt és a tmr0L beírásakor az is átmásolódik a Timer-be.”

A tmr0H:tmr0L az maga a számláló ha jól tudom (16biten). Hogy kell értelmezni ezt a puffer dolgot?
Gondolom az egy átmeneti tároló egy foglalt memóriaterület, de akkor nem mindegy a sorrend? Úgyis csak akkor záródik le az áttöltés ha minden bit a helyére került.
Következő: »»   1 / 25
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