PIC мк. Эксперимент №10. Использование модуля CCP (Capture/Compare).

В данном эксперименте попробуем исследовать такой замечательный модуль PIC микроконтроллеров как CCP(Capture/Compare/PWM).

Ну в общем приступим…

Исходя из названия модуля можно предположить, что он может:

1. Захватить

2. Сравнить

3. Зашимить :)

Продолжение внутри.

Главный здесь регистр ССP1CON:

CCP1X:CCP1Y – биты, про которые будет рассказано слегка попозже

CCP1M<3:0> – выбор режима:

0000 = все вырублено

0100 = захват, каждый ниспадающий импульс0101 = захват, по каждому возрастающему фронту

0110 = захват, по каждому 4 возрастающему фронту

0111 = захват, по каждому 16 возрастающему фронту

1000 = сравнение, перевод выходного пина в 1 при совпадении

1001 = сравнение, очистка выходного пина при совпадении

1010 = сравнение, генерация софтового прерывания

1011 = сравнение, переключение специального события (сам пока толком не понял что это за зверь)

11хх = режим ШИМ

Для начала рассмотрим модуль захвата:

В этом режиме содержимое регистров TMR1H и TMR1L копируется в регистры CCPR1H и CCP1L в следующих ситуациях:

  • По каждому спаду на RB3
  • По каждому возрастающему импульсу на RB3
  • По каждому 4 возрастающему импульсу на RB3
  • По каждому 16 возрастающему импульсу на RB3

Для корректной работы модуля нужно соблюсти два условия:

  • Пин RB3 должен быть сконфигурирован как вход
  • TMR1 должен работать как таймер или как счетчик

По записи может происходить прерывание (флаг ССP1IF). Пример программы приводить не буду, т.к. тут надо еще подумать как извлекать инфу нужную (подключать дисплей и т.д., а это засорит код).

Сравнение: В этом режиме значение регистра CCP1 сравнивается со значением в регистре таймера TMR1. В случае совпадения величин может изменяться состояние порта RB3 или генерироваться прерывание

Для корректной работы режима нужно обеспечить следующие условия:

  • Порт RB3 должен быть сконфигурирован как выход
  • Таймер TMR1 синхронизируется внутренним тактированием (Focs/4)

Составим небольшую программку для проверки работы компаратора, в данном примере будем генерировать импульсы шириной 1 мс.


#include <htc.h>
#define _XTAL_FREQ 4000000

__CONFIG(WDTDIS & UNPROTECT & MCLREN & LVPDIS);

void main() {
unsigned char x;
__delay_ms(100);
TRISB = 0x00;
PORTB = 0x00;

CCPR1H = 0b00000011; CCPR1L = 0b11101000; // 1000 in CCPR1
CCP1M3 = 1;                               // Сравнение, при совпадении генерим прерывание
CCP1M2 = 0;
CCP1M1 = 1;
CCP1M0 = 0;

T1CKPS1 = 0;
T1CKPS0 = 0;  // Prescaler = 0

T1OSCEN = 0;
TMR1CS = 0;   // Fosc/4
TMR1ON = 1;
T1SYNC = 0;

GIE = 1;
PEIE = 1;
CCP1IE = 1;

for (;;) {

}

}

void interrupt isr() {
if (CCP1IF) {
RB3 = !RB3;
TMR1H = 0x00; TMR1L = 0x00;
CCP1IF = 0;
}

}

Результат на осциллограмме из протеуса:
oscil

Исходники здесь
О самом интересном применении модуля CCP – ШИМе будет рассказано в следующем эксперименте о PIC микроконтроллерах, дабы не было помеси инфы в голове (в том числе моей)

PIC мк. Эксперимент №10. Использование модуля CCP (Capture/Compare).: 61 комментарий

  1. Сейчас точно не скажу, но полагаю, что нужно просто завести переменную, присвоить ей значение регистра CCPR1L, а затем произвести преобразование обратное расчету параметров таймера TMR1

    ps. Попозже постараюсь дописать этот пункт в статью

    Ответить

  2. DOBROE VREMYA SUTOK . MOJETE PODROBNO OPISAT CCP V REJIMA ZAHVATA DLYA RASCHETA OBOROTOV DVIGATELYA .

    Ответить

    sarge Ответил:

    Доброго, сейчас времени нету совсем, постараюсь на неделе вспомнить что и как, будет лучше если вы напомните мне об этом :)

    Ответить

  3. ZDRASTVUETE , VI SKAZALI NAPOMNIT PRIMER PASCHETA OBOROTA DVIGATELYA V REJIME ZAHVATA CCP . YA SAM PROBOVAL MOJETE POSMOTRET PRAVILNOLI YA SDELAL . PO KAKOY FORMULE PRAVILNO RASCHITAETSA OBOROT V MINUTU .

    int N_overflows;
    unsigned long int N_start, N_end;
    long int N;
    
    #define _XTAL_FREQ         8000000 // частота генератора в Гц
    
    //определим входы/выходы
    
    #define   led_1  RA0 //;
    #define   led_2  RA1 //; 
    #define   led_3  RA2 //; 
    #define   led_4  RA3  //; 
    #define   led_5  RA4 //; 
    #define   led_6  RA5 //; 
    #define   led_7  RA6 //; 
    #define   led_8  RA7  //; 
    
    #define   led_9  RB0  //; 
    #define   led_10  RB1 //; 
    void main(void)
    {
      PORTA=0;
      PORTB=0; 
      PORTC=0;// .
      PORTD=0;
      PORTE=0;
    
       ADCON1=0b00000110; // vivodi nastroeni kak sifrovoy 
       ADCON0=0b00000000;//modul ADC vikluchen
      TRISA= 0b00000000;
      TRISB= 0b00000000;
      TRISC= 0b00000100; //RC2 VHOD 
      TRISD= 0b00000000;
      TRISE= 0b00000000;
      INTCON=0b00000000;
      OPTION_REG=0b00000111; //бит 3:0 = предделитель включен перед TMR0.
        //коэффициента деления предделителя = 111- 1:256 
       OSCCON=0b01111101;//8MHZ
      ANSEL=0;
      ANSELH=0;
      C1ON=0;//komparator vikluchen
      C2ON=0;//komparator vikluchen
      CCP1CON=0b000000101; //0101 = захват по каждому переднему фронту сигнала
    
      T1CON=0b00010001; //TMR1 vkluchen.0 = внутренний источник Fosc/4,
                        //биты 5-4: Выбор коэффициента деления предделителя TMR1,01 = 1:2
             //частота таймера 1 МГц и 1 тик таймера будет равен 1/1000000 Гц = 1 мкс.,
             // т.е. за 65536 мкс произойдет одно прерывание таймера
    
       CCP1IE = 1;// razresheniya prerivaniya ot CCP
       TMR1IE=1;
                 //разрешаем прерывания от таймера
       GIE=1; 
       PEIE = 1;
        CCP1IF=0;    // CCP1IF: Флаг прерывания от модуля CCP1
         // Режим захвата
         //1 = выполнен захват значения TMR1 (сбрасывается программно)
         //0 = захвата значения TMR1 не происходило
      TMR1IF=0;  
          // TMR1IF: Флаг прерывания по переполнению TMR1
         //1 = произошло переполнение TMR1 (сбрасывается программно)
         //0 = переполнения TMR1 не было
    
    
      //  CMCON = 0b00000111; //Отключить компаратор
    
    //*******************************************************************************************************************/
    
      while(1)
       { 
    
    
       }   
    }
    
    void interrupt isr() {
      if(TMR1IF)  //
      {
       TMR1IF=0;  //
      
       ++N_overflows;
      }
    
    if (CCP1IF) {
     // N_end =  (CCPR1L &amp; 0x00ff);//   CCP1;
        N_end =  256*CCPR1H+CCPR1L;
      N = (N_overflows * 65536) + N_end - N_start ;
     f=1000000/N ;
    t=f*60 ;// kolichestva oborotov  v minutu 
     if (t &gt;500) led_1=1;
       else   
           led_1=0;    // if(t1000) led_2=1;
            else    
                led_2=0;        // if(t1500) led_3=1;
            else    
                led_3=0; 
          if (t &gt;2000) led_4=1;
            else    
                led_4=0; 
      if (t &gt;2500) led_5=1;
            else    
                led_5=0; 
     if (t &gt;3000) led_6=1;
            else    
                led_6=0; 
     if (t &gt;3500) led_7=1;
            else    
                led_7=0; 
     if (t &gt;4000) led_8=1;
            else    
                led_8=0;
      if (t &gt;4500) led_9=1;
            else    
                led_9=0; 
     if (t &gt;5000) led_10=1;
            else    
                led_10=0; 
    
    
    
    // RB3 = !RB3;
    TMR1H = 0x00; TMR1L = 0x00;
    CCP1IF = 0;
      N_start = N_end;
      N_overflows = 0;
    }
     
    }
    

    Ответить

    sarge Ответил:

    Доброго дня,

    Давайте не будем спешить, начнем с того, что я в принципе никогда с похожими вещами дела не имел, поэтому быстро не сориентируюсь.
    Формулы простой тоже я так понимаю не будет, т.к. это зависит от того что там выдает импульсы.
    Мой главный вопрос, каким образом мотор подсоединяется к модулю захвата? Что там выдает импульсы и в какой момент?

    Ответить

  4. dlya primera mojem proveryat na proteuse . ya prochital v interrnete chto;
    1500 об/мин = 50 Гц
    3000 об/мин = 100 Гц
    6000 об/мин = 200 Гц
    na vhod mojem podat signal ot generatora 3.5-4.5V .pryamougolniy formi

    Ответить

    sarge Ответил:

    Ого, интересные цифры у вас в интернете:

    Чтобы перейти к частоте от оборотов в минуту, нужно сначала перейти к угловой скорости, а потом уже к частоте

    http://en.wikipedia.org/wiki/Revolutions_per_minute

    Приблизительная формула перехода N_Hz = N_rpm/60, то есть 1500 об/мин = 25 Гц, а не 50, 3000 об/мин = 50 Гц, а не 100, ну и т.д.

    Меня не этот вопрос то в общем интересовал, а вопрос – откуда конкретно в реальном моторе будут идти импульсы – энкодер, датчик, что-то еще? В зависимости от этого по идее будут считаться обороты в минуту, так например у разных энкодеров разное количество импульсов соответствует полному обороту вокруг оси.

    Дальнейший расчет в принципе элементарен и не составляет никаких сложностей.

    Ответить

  5. DA VI PRAVI YA TOJE HOTEL PODROBNO RAZOBRATSA , A DALNEYWEM UJE MOJNO RASCHITAT . NO YA PO IDEI PRO AVTOMOBILNIY TAHOMETR ,TAM 2 IMPULSA DAET 1POLNIY OBOROT .POETOMU YA PISAL 1500 об/мин = 50 Гц
    3000 об/мин = 100 Гц
    6000 об/мин = 200 Гц
    SIGNAL POSTUPAET OT PRERIVATELYA AVTOMOBILYA CHEREZ TRANZISTORNIY KLUCH ILI REZISTORNIY DELITEL NAPRYAJENIYA .

    Ответить

    sarge Ответил:

    Вот, уже картинка начинает складываться.
    Два импульса один полный оборот, все остальное пока лишнее. Дальше, какой мк вы собрались использовать? Я смотрю на ваш код и вижу что там до фига портов, а у меня статья по pic16f628a, соответственно не могу пока дать точный совет.

    В целом вроде код выглядит правильным, за исключением того что:

    1. Формула перехода от Гц к rpm у вас забита как N = F*60, а нужно (если два импульса = 1 оборот) N = F*30
    2. Значения регистров таймера TMR1H, TMR1L реинициализируются только по срабатыванию модуля захвата, то есть ваш N_overflows по идее будет всегда либо 0 либо 1.

    В остальном надо пробовать, в том же протеусе, вроде все ок выглядит и я не понимаю зачем вам нужна помощь :)

    Ответить

  6. u menya mk pic 16f887 , mogu perevesti na 628 , mne ne ponyatno to ya izmeryuy ;1 .pereud signala . 2. kak etot period pravilno perevesti na chastoti
    N = N_end – N_start ;esli N pereud F=1/N i oboroti N1=F*30 tak budet pravilno . i echo kak pravilno prisvoit znachenie ccp. N_end = 256*CCPR1H+CCPR1L; ,N_end = (CCPR1L & 0x00ff); .N_end = CCPR1L+(CCPR1H << 8);

    Ответить

    sarge Ответил:

    1. По захвату каждого возрастающего фронта вы измеряете период сигнала
    2. F = 1/T

    Но ваш T может состоять из нескольких прогонов таймера, и я бы делал скорее всего не так, а как то вот так:
    1. Рассчитываю период сигнала – T = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)) * 128 us (кварц 8 МГц, предделитель 256)
    2. Рассчитываю частоту сигнала F = 1/T
    3. Рассчитываю обороты в минуту N = F*30

    По правильному присвоению подойдут оба варианта и можно еще кучу новых напридумывать, например:
    N_end = 0;
    N_end = CCPR1L | (CCPR1H<<8);

    Ответить

  7. mojete obyasnit eto ; 1. Рассчитываю период сигнала – T = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)) * 128 us (кварц 8 МГц, предделитель 256) // * 128 us (кварц 8 МГц, предделитель 256) TMR1 ;
    биты 5-4: T1CKPS1:T1CKPS0: Выбор коэффициента деления предделителя TMR1
    11 = 1:8
    10 = 1:4
    01 = 1:2
    00 = 1:1

    Ответить

    sarge Ответил:

    Прошу прощения, перепутал TMR1 c TMR0, вы правы максимальный предделитель здесь 8

    T = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)) * 4 us (кварц 8 МГц, предделитель 8)

    Ответить

  8. YA SEYCHAS PROVERIL ,SIGNAL PODAYU DO 30 HZ CHASTOTA PRAVILNO POKAZIVAET PRI OTLADKE V PROTEUSE S VISHE 30HZ NACHINAET SBIVATSAY CHASTOTI ; PRI CHASTOTE 34HZ f=10HZ,50HZ f=11 , PRI 101HZ f=13HZ .
    N = ((N_overflows+1)*65536 + (256*CCPR1H+CCPR1L)); (кварц 8 МГц, предделитель 2)
    f=1000000/N;
    t=f*30 ;// kolichestva oborotov v minutu

    Ответить

    sarge Ответил:

    Сбросьте весь проект архивом с настроенным файлом под протеус.

    Ответить

    sarge Ответил:

    Все как то очень странно, я вообще не смог обработать пока ни одного прерывания по захвату, они попросту не происходят, завтра еще поковыряю.

    Ответить

  9. KAK MOJNO PREKREPIT ZIP FAYL?

    Ответить

    sarge Ответил:

    Выложите на файлообменник или на сервисы типа дропбокса, яндекс диска и т.д.
    К моему сайту прикреплять нельзя.

    Ответить

  10. ya skachal yandex disk . ya postavil fayl tuda . chto ya doljen vam otpravit chtobi vi mogli posmotret fayl

    Ответить

    sarge Ответил:

    Ссылку на файл.
    Выделили папку/файл и выбрали “Поделиться ссылкой”, все после этого можно скидывать ссылку.

    Ответить

  11. samoe interesnoe ne mogu nayti adress ssilki .

    Ответить

    sarge Ответил:

    Блин, пришлите мне просто ваш архив на sargein@gmail.com

    Ответить

    sarge Ответил:

    Мне не нужен ваш пароль и логин, я уже могу скачать вашу папку, она доступна и мне.
    Так что я потру ваш предыдущий пост, ждите в общем, я пока поеду домой и поздним вечером постараюсь повтыкать в ваш проект.

    Ответить

  12. ZDRASTVUETE , KOGDA CHASTOTA S 18-30 HZ PROISHODIT ZAHVAT PRAVILNO POKAZIVAET f ,POSLE 30HZ OSHIBKI , NE IZ ZA ETOGO (256*CCPR1H+CCPR1L))???

    Ответить

    sarge Ответил:

    Ни один из ваших светодиодов в протеусе не срабатывает при частоте 25 Гц.
    Нет, не изза этого, я даже светодиод пока зажечь не смог по прерыванию модуля захвата

    кстати
    CCP1CON=0b000000101;
    В этой строчке вы ноль лишний добавили.

    Ответить

    sarge Ответил:

    Блин есть большое подозрение что протеус не справляется с данной задачей, не работает даже такой простой код:

    #include &lt;htc.h&gt;
    //#include &lt;stdio.h&gt;
    
    #define _XTAL_FREQ 8000000
    
    
    __CONFIG(WDTDIS &amp; UNPROTECT &amp; LVPDIS &amp; HS &amp; BOREN);
    
    
    void main()
    {
      ADCON1 = 0xFF;
      ADCON0 = 0;
      CMCON = 0x07;
      TRISD0 = 0; 
      TRISC2 = 1;
      RD0 = 1;
      
    
      CCP1CON=0b00000101; //0101 = захват по каждому переднему фронту сигнала
      T1CON = 0;
      TMR1L = 0; TMR1H = 0;
      CCPR1L = 0; CCPR1H = 0;
       
      GIE=1; 
      PEIE = 1;                  
      CCP1IE = 1;// razresheniya prerivaniya ot CCP
      TMR1ON = 1;
      
      while(1){};
    }
    
    void interrupt isr() {
    
    
    
    if (CCP1IF) 
    {
    
      RD0 = 0;
      TMR1H = 0x00; TMR1L = 0x00;
      CCP1IF = 0;
    
    }
     
    }
    

    Вы можете проверить на реальном девайсе работоспособность кода? А то мне сдается, что я ща ковыряюсь впустую.

    Ответить

  13. DOBRIY DEN . PROTEUSE RABOTAET ,POPROBUYTE DOBAVIT V PRERIVANII OT CCP ; RB3 = !RB3; V KAJDOM PEREPOLNENIE CCP IZMENYAETSA SOSTOYANIYA PORTA RB3.

    Ответить

    sarge Ответил:

    А почему же не работает RD0 = !RD0?

    Ответить

  14. A U VAS TAK NAPISANO;

    if (CCP1IF)
    {

    RD0 = 0;
    TMR1H = 0x00; TMR1L = 0x00;
    CCP1IF = 0;

    }

    Ответить

    sarge Ответил:

    да, а до этого в инициализации RD0 = 1;
    ну и можете попробовать RD0 = !RD0; у меня изначально так было и он молчал.

    Ответить

  15. RABOTAET I NA ; RD0 = !RD0;

    Ответить

    sarge Ответил:

    Проверил еще раз. Глухо. Какая версия протеуса у вас и дайте мне хекс файл, скомпиленный вами.

    Ответить

  16. Proteus.pro.7.6.sp4-patch_v1
    :060000000A128A110E280D
    :10000800FE00030E83120313B4000A08B5000A1297
    :100018008A1123280A128A111128A001A101A2011C
    :10002800A301A401A501A601A701A801A901AA018C
    :10003800AB01AC01AD0183010A128A110A2A0C1C1A
    :1000480029280C10A80A0319A90A0C1D5B292808DD
    :10005800013EAE0029080318013EAF002E08B0008B
    :100068002F08B100B201B301B3003008B200B101EA
    :10007800B0013308AD003208AC003108AB003008DD
    :10008800AA001508AE001608AF000030AF1BFF30FD
    :10009800B000B1002E08AA072F0803110318013E6B
    :1000A800031DAB07300803110318013E031DAC07FD
    :1000B800310803110318013E031DAD072D08F30095
    :1000C8002C08F2002B08F1002A08F0000F30F70185
    :1000D800F6004230F5004030F40062210A128A111D
    :1000E8007308A3007208A2007108A1007008A0009C
    :1000F8002308F3002208F2002108F1002008F0008C
    :100108001E30F400F501F601F701D7210A128A1111
    :100118007308A7007208A6007108A5007008A4005B
    :1001280000302702031DA22800302602031DA22842
    :1001380001302502031DA228F5302402031CA6283D
    :100148000514A728051000302702031DB528003024
    :100158002602031DB52803302502031DB528E93002
    :100168002402031CB9288514BA28851000302702F8
    :10017800031DC82800302602031DC82805302502A3
    :10018800031DC828DD302402031CCC280515CD2802
    :10019800051100302702031DDB2800302602031D4D
    :1001A800DB2807302502031DDB28D1302402031C7D
    :1001B800DF288515E028851100302702031DEE2869
    :1001C80000302602031DEE2809302502031DEE2803
    :1001D800C5302402031CF2280516F3280512003046
    :1001E8002702031D012900302602031D01290B30B7
    :1001F8002502031D0129B9302402031C052985168F
    :100208000629851200302702031D14290030260212
    :10021800031D14290D302502031D1429AD302402B5
    :10022800031C182905171929051300302702031D77
    :10023800272900302602031D27290F302502031D18
    :100248002729A1302402031C2B2985172C29851363
    :1002580000302702031D3A2900302602031D3A29DF
    :1002680011302502031D3A2995302402031C3E292A
    :1002780006143F29061000302702031D4D290030BF
    :100288002602031D4D2913302502031D4D298930EF
    :100298002402031C5129861452298610013088062D
    :1002A800083086068F018E010C11A801A9013508B6
    :1002B8008A00340E8300FE0E7E0E0900F901F31F3A
    :1002C8007229F009F109F209F309F00A0319F10A90
    :1002D8000319F20A0319F30AF901F90AF71F812928
    :1002E800F409F509F609F709F40A0319F50A0319D7
    :1002F800F60A0319F70A0130F906FA01FB01FC01B5
    :10030800FD0173087204710470040319C029F8010F
    :10031800F80AF31B95290310F00DF10DF20DF30DFA
    :100328008C290310FA0DFB0DFC0DFD0D73087702E7
    :10033800031DA82972087602031DA82971087502F1
    :10034800031DA82970087402031CBA297008F40256
    :100358007108031C710FF5027208031C720FF60274
    :100368007308031C730FF7027A140310F30CF20CD2
    :10037800F10CF00CF80B952979080319CE29FA0924
    :10038800FB09FC09FD09FA0A0319FB0A0319FC0A0F
    :100398000319FD0A7D08F3007C08F2007B08F100D0
    :1003A8007A08F0000800F801F901FA01FB01701C55
    :1003B800F1297408F807750803110318013E031D95
    :1003C800F907760803110318013E031DFA07770899
    :1003D80003110318013E031DFB070310F40DF50D6F
    :1003E800F60DF70D0310F30CF20CF10CF00C73087A
    :1003F800720471047004031DDB297B08F3007A087A
    :10040800F2007908F1007808F000080085018601FB
    :10041800870188018901063083169F0083129F0196
    :1004280083168501860104308700880189018B01C4
    :100438000730810003178801890183128713881305
    :100448000530031397001130900083160C150C1417
    :0C0458008B170B1783120C110C10312AAB
    :04400E0094ECFFFF30
    :00000001FF

    Ответить

    sarge Ответил:

    Ваш хекс вообще ничего не дергает у меня, даже RD0 в 1 не ставит.
    Позже постараюсь вернуться к вашему вопросу, и установить протеус посвежее может в этом глюк, сейчас пора бежать.

    Ответить

  17. TOCHNO PEREUSTANOVITE PROTEUS DOLJNO SRABOTAT .U MENYA TOJE INOGDA TAK BIVAET

    Ответить

    sarge Ответил:

    Да, поставил сейчас 8 протеус и все начало работать. Теперь можно и поковыряться.
    Вопрос – какую максимальную частоту вы хотите ловить?
    Если это тахометр так по идее вам же не нужно особо больше 200 Гц, правильно?

    Ответить

  18. izmenil formulu ; N = ((N_overflows+0)*65536 + (256*CCPR1H+CCPR1L))*2;
    N=N/16;
    CCP1CON=0b00000111;//0111 = захват по каждому 16-му переднему фронту сигнала
    T1CON=0b00100001;
    //10 = 1:4 частота таймера 500kГц и 1 тик таймера будет равен 1/500000 Гц = 2 мкс.,
    vse zarabotalo ,no odna problema mejdu chastotami 130-230 Hz ne opredelyaet chastotu . 0-120 i ot 240 do 400 vse normalno

    Ответить

  19. shkala do 8000 oborotov v minutu 8000/30=266,6 Hz ,stranno pochemu v predelah 130-230 hz N privishaet 65000 i f=0 ;

    Ответить

    sarge Ответил:

    Как вы проверяете точное значение частоты? Пользуетесь режимом отладки?

    Ответить

  20. da polzuyus otladkoy , v rejime zahvat po 16 frontu bole tochnee vichislaet chastotu

    Ответить

    sarge Ответил:

    Тестирую код, пока считаю только период:

    #include &lt;xc.h&gt;
    #define _XTAL_FREQ         8000000 // ??????? ?????????? ? ??
    #pragma config FOSC= HS //INTOSC        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
    #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = OFF       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
    #pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
    #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
    #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
    #pragma config CP = ON         // Flash Program Memory Code Protection bit (Code protection off)
    #pragma config WRT = OFF
    
    unsigned long T;
    
    //  int   bt=0;
    volatile unsigned char N_overflows = 0;
    volatile unsigned char timerFlag = 0;
    volatile unsigned char test = 0;
    volatile unsigned int Ttemp = 0;
    unsigned long int N_start, N_end;
    long int N;
    
    #define _XTAL_FREQ         8000000 // частота генератора в Гц
    
    
    
    
    
    
    
    void main(void)
    {
      PORTA=0;
      PORTB=0; 
      PORTC=0;// .
      PORTD=0;
      PORTE=0;
    
      ADCON1=0b00000110; // vivodi nastroeni kak sifrovoy 
      ADCON0=0b00000000;//modul ADC vikluchen
      TRISA= 0b00000000;
      TRISB= 0b00000000;
      TRISC= 0b00000100; //RC2 VHOD 
      TRISD= 0b00000000;
      TRISE= 0b00000000;
    
      INTCON=0b00000000;
      OPTION_REG=0b0000011; //бит 3:0 = предделитель включен перед TMR0.
        //коэффициента деления предделителя = 111- 1:256 
       OSCCON=0b01111101;//8MHZ
      ANSEL=0;
      ANSELH=0;
      RD0 = 1;
      C1ON=0;//komparator vikluchen
      C2ON=0;//komparator vikluchen
      CCP1CON=0b00000101; //0101 = захват по каждому переднему фронту сигнала
    
      T1CON=0b00010001; 
      CCP1IE = 1;  
      GIE=1; 
      PEIE = 1;
      TMR1IE = 1;
      CCP1IF=0; 
      TMR1IF=0;  
        
    //*******************************************************************************************************************/
    
      while(1)
       { 
    
    
       }   
    }
    
    void interrupt isr() {
     if(TMR1IF)  //
      {
          N_overflows++;
          TMR1H = 0x00; TMR1L = 0x00;
          timerFlag = 1;
          TMR1IF=0;  
      }
    
    
    if (CCP1IF) 
    {
       Ttemp = 0;
       Ttemp = (CCPR1H&lt;&lt;8) | CCPR1L;
       T = N_overflows*65536 + Ttemp;
       test++;
       N_overflows = 0;
       TMR1H = 0x00; TMR1L = 0x00;
       CCP1IF = 0;
    }
    
    }
    

    Работаю как и прежде по каждому фронту, таймер настроен на 1 мкс.
    Вот результат:
    https://www.dropbox.com/s/s8xsjd5b91vik4w/Taho_piuc.JPG?dl=0
    К 270 Гц ошибка расчетной частоты уже составляет 3%, не знаю приемлемо это для вас или нет, но в целом я не наблюдаю пока никаких прострелов в расчете периода.

    Ответить

    sarge Ответил:

    Добавил частоту

    #include &lt;xc.h&gt;
    #define _XTAL_FREQ         8000000 // ??????? ?????????? ? ??
    #pragma config FOSC= HS //INTOSC        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
    #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = OFF       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
    #pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
    #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
    #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
    #pragma config CP = ON         // Flash Program Memory Code Protection bit (Code protection off)
    #pragma config WRT = OFF
    
    volatile unsigned long T;
    volatile unsigned long F=0;
    
    //  int   bt=0;
    volatile unsigned char N_overflows = 0;
    volatile unsigned char timerFlag = 0;
    volatile unsigned char test = 0;
    volatile unsigned int Ttemp = 0;
    unsigned long int N_start, N_end;
    long int N;
    
    #define _XTAL_FREQ         8000000 // частота генератора в Гц
    
    
    
    
    
    
    
    void main(void)
    {
      PORTA=0;
      PORTB=0; 
      PORTC=0;// .
      PORTD=0;
      PORTE=0;
    
      ADCON1=0b00000110; // vivodi nastroeni kak sifrovoy 
      ADCON0=0b00000000;//modul ADC vikluchen
      TRISA= 0b00000000;
      TRISB= 0b00000000;
      TRISC= 0b00000100; //RC2 VHOD 
      TRISD= 0b00000000;
      TRISE= 0b00000000;
    
      INTCON=0b00000000;
      OPTION_REG=0b0000011; //бит 3:0 = предделитель включен перед TMR0.
        //коэффициента деления предделителя = 111- 1:256 
       OSCCON=0b01111101;//8MHZ
      ANSEL=0;
      ANSELH=0;
      RD0 = 1;
      C1ON=0;//komparator vikluchen
      C2ON=0;//komparator vikluchen
      CCP1CON=0b00000101; //0101 = захват по каждому переднему фронту сигнала
    
      T1CON=0b00010001; 
      CCP1IE = 1;  
      GIE=1; 
      PEIE = 1;
      TMR1IE = 1;
      CCP1IF=0; 
      TMR1IF=0;  
        
    //*******************************************************************************************************************/
    
      while(1)
       { 
    
    
       }   
    }
    
    void interrupt isr() {
     if(TMR1IF)  //
      {
          N_overflows++;
          TMR1H = 0x00; TMR1L = 0x00;
          timerFlag = 1;
          TMR1IF=0;  
      }
    
    
    if (CCP1IF) 
    {
       Ttemp = 0;
       Ttemp = (CCPR1H&lt;&lt;8) | CCPR1L;
       T = N_overflows*65536 + Ttemp;
       F = 1000000/T;
       test++;
       N_overflows = 0;
       TMR1H = 0x00; TMR1L = 0x00;
       CCP1IF = 0;
    }
    
    }
    

    Просвипал по быстрому по частотам все есть, провалов не видно, НО:
    Ошибка расчетов частоты в коде составляет уже приличные 20 процентов на 250 Гц, причина добавление математических вычислений в обработчик прерываний – чем больше мы сюда грузим, тем больше ошибка

    Я бы кстати вообще частоту не считал, если вы собираетесь светодиодами рулить, можно на основе временных промежутков выбирать сколько светодиодов зажигать.
    Ну или повышать частоту тактирования вашего мк.

    Ответить

  21. dly naglyadnosti perevel programmu na 16f628 . chastotomer , pabotaet na vseh chasstotah pri zahvate po kajdomu frontu . pri perevode ccp na zahvat po kajdomu 4 ili 16 frontu rabotaet no ne na fseh chastotah , v kakoyto pereud chastot v eredine ne rabotaet , proekt postavil na yandex disk , mojet proverite kogda vremya budet

    Ответить

    sarge Ответил:

    Вы мой код пробовали?
    Считает по всем частотам на pic16f877a, читайте в общем мои два сообщения сверху.

    Ответить

  22. if (CCP1IF)
    {
    Ttemp = 0;
    Ttemp = (CCPR1H<<8) | CCPR1L;
    T = N_overflows*65536 + Ttemp;
    test++;
    N_overflows = 0;
    TMR1H = 0x00; TMR1L = 0x00;
    CCP1IF = 0;
    }

    Ответить

    sarge Ответил:

    Покажите ошибку, все тут правильно и ошибки быть не должно.
    Я вам не вручную набирал а скопировал код, который откомпилился и работает.

    Ответить

  23. da zdes net oshibki . na vashem soobshenii pochemuta etu stroku pokazivaet tak; Ttemp=(CCPR1H&;lt;8)|CCPR1L;
    POSMOTRITE NA VERHU VASHU SOOBSHENII ,ILI U MENYA V KOMPUTERE TAK POKAZIVAET

    Ответить

    sarge Ответил:

    это глюк отображалки кода, но вы же правильно написали << и |, вместо этих хтмл служебных символов.

    Ответить

  24. PROGRAMMA RABOTAET OTLICHNA ,SDELAL ZAHVAT PO KAJDOMU 16 FRONTU ,TOCHNOST NAMNOGO LUCHSHE ,V CHEM BILA PROBLEMA ? I KAKOY ROL IGRAYUT SDES ETI DVE PEREMENNIE ?
    timerFlag = 1;
    test++;

    Ответить

    sarge Ответил:

    Эти переменные для меня, забыл почистить, тестил отладку на протеусе.

    Ответить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.