问题描述
我想在捕获模式下使用 pic 18f4550 CCP 测量脉冲宽度。 这个想法是: 当CCP模型接收到上升沿时,定时器1启动,每次定时器1中断后,初始值为0的常数x加1,当CCP模型接收到下降沿时,定时器1停止并增加的 x 也必须停止,以便其值可用于计算脉冲。 我发现的问题是 x 的增加不会停止并且代码像计数器一样工作 由于我是 pic 编程的新手,我找不到错误。 如果有人可以提供帮助,我将不胜感激。 我正在使用的代码如下。 谢谢!
#include <stdio.h>
#include <stdlib.h>
#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>
int x=0;
void main()
{
unsigned long comtage;
unsigned long DEPHASAGE[20];
float Deph_tempo;
TRISCbits.TRISC2=1;
IRCF0=1;
IRCF1=1;
IRCF2=1;
LCD_Init();
LCD_String_xy(0,"pulse");
PIE1bits.CCP1IE=1;
PIR1bits.CCP1IF=0;
CCP1CON=0b00000101;
CCPR1=0;
T1CONbits.RD16=0;
T1CKPS0=0;
T1CKPS1=0;
TMR1CS=0;
while(1)
{
CCP1CON = 0b00000101;
PIR1bits.CCP1IF = 0;
TMR1ON = 0;
TMR1 = 0;
while (!PIR1bits.CCP1IF)
;
TMR1ON = 1;
CCP1CON = 0b00000100;
PIR1bits.CCP1IF = 0;
if (TMR1IF==1)
{
x++;
TMR1IF=0;
}
while (!PIR1bits.CCP1IF)
;
comtage = x;
Deph_tempo = ((float)comtage /7843.13 );
sprintf(DEPHASAGE,"%.5f ",Deph_tempo);
LCD_String_xy(2,DEPHASAGE);
}
x = 0;
}
``
解决方法
有一种方法可以实现您想要做的事情...这有点棘手,因为您需要一个超过 16 位宽的计时器。可以同时使用 TMR1 和 TMR3 与 CCPCON 一起工作,并获得一个 19 位宽的定时器,在 Fosc = 8MHz 时,定时器的时钟输入为 2MHz,这意味着这个 19 位定时器将在 2^19 后翻转 * .5 us = 264 us 秒左右...我们可以使用 TMR3IF 来检测翻转并将其设为 20 位,但这仍然有点短。
也可以使用具有 1:256 预分频器的 TMR0,但您需要为 TMR0 提供外部时钟。您可以使用 TMR3 和 PWM 发生器在 CCP2/RC1 上生成 500kHz 时钟信号,并将其路由到 TK0CKI/RA4。这将有效地创建一个 26 位计数器,分辨率为 4/Fosc = .5 us,范围为 33.55 秒。您可以通过使用 PLL 来增加振荡器频率来提高分辨率。这也有一个优点,它会非常精确。可重复性取决于循环。使用 ISR 来捕获中断会大大提高可重复性。
#include <stdio.h>
#include <stdlib.h>
#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>
void main()
{
unsigned long count = 0;
// Setting up TMR0 for extarnal clock on T0CKI/RA4
LATAbits.LATA4 = 0;
TRISAbits.TRISA0 = 1; // RC0 as input
T0CON = 0x27 // Prescaler 1:256,0->1 transition,T0CKI input
TMR0IE = 0; // mask interrupts.
// Setting up TMR1/CCP1CON for capture on RC2/CCP1
TRISCbits.TRISC2 = 1; // CCP2/RC2 as input
LATCbits.LATC2 = 0;
T1CON = 0x80 // internal clock oscillator off,1:1 pre,16 bits reads
TMR1 = 0;
CCP1CON = 0x05 // set capture mode on rising edge
CCP2IE = 0; // mask interrupts
TMR1IE = 0;
// Setting up TMR2/CCP2CON for generating the clock on CCP2/RC1
LATCbits.LATC1 = 0; // clear RC1 latch
TRISCbits.TRICSC1 = 0; // RC1 as output
T2CON = 0; // timer2 off,prescaler 1:1,post scaler 1:1
PR2 = 3; // PWM frequency = (Fosc / 4) / 4
TMR2 = 0;
CCPR2 = 0;
CCP2CON = 0x1C; // CCP2M = PWM mode,DCB2<0> = 1 (LSB for duty cycle compare)
CCP2IE = 0; // mask interrupts
TMR2IE = 0;
while (1)
{
// get ready to capture.
TMR2ON = 0; // stop our timing clock.
TMR0ON = 0; // this reset TMR0 prescaler
TMR0 = 0; // clear timers.
TMR1 = 0;
TMR2 = 0;
TMR0ON = 1; // Timer 0 is ready to count.
CCP1CON = 0x05; // set capture mode on rising edge
PIR1bits.CCP1IF = 0;
while (!PIR1bits.CCP1IF) // wait for event
;
PIR1bits.CCP1IF = 0;
CCP1CON = 0x04; // set capture mode on falling edge
TMR1ON = 1;
TMR2ON = 1;
while (!PIR1bits.CCP1IF) // wait for event
;
// here we have to make sure to keep the same latency as after
// rising edge,so we are precise.
PIR1bits.CCP1IF = 0;
CCP1CON = 0x04; // set capture mode on rising edge
TMR1ON = 0;
TMR2ON = 0; // also stops TMR0
// TMR0's clock is is divided by 2²2 * 2^8 = 2^10
// its lower 6 bits should be equal to the upper 6 bits
// of TMR1.
count = ((TMR0 & 0xFFC0 << 10) + TMR1;
// convert to us
count >>= 1;
// display...
}
}
在我面前没有实际设备和示波器的情况下,这是我所能做到的。如果您有任何疑问或遇到任何问题,请告诉我。