问题描述
我想在捕获模式下仅使用一个 CCP 模型和 pic 18f4550 来测量脉冲持续时间,因此我尝试在第一时间检测上升沿,当检测到上升沿时,timer1 打开并且捕获模式更改为下降沿,用这种方法我必须测量脉冲宽度,但我使用的代码效果不佳!! 当我使用两个 CCP 模型时很好。 如果有人可以提供帮助,我将不胜感激。
#include <stdio.h>
#include <stdlib.h>
#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>
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,"Deph.tempo");
PIE1bits.CCP1IE=1;
PIR1bits.CCP1IF=0;
CCP1CON=0b00000101;
CCPR1=0;
T1CONbits.RD16=1;
T1CKPS0=0;
T1CKPS1=0;
TMR1CS=0;
TMR1IF=0;
TMR1=0;
while(1)
{
if(PIR1bits.CCP1IF==1){
TMR1ON=1;
PIR1bits.CCP1IF=0;
CCP1CON=0b00000100;
while(!(PIR1bits.CCP1IF==1))
comtage= TMR1;
PIR1bits.CCP1IF=0;
Deph_tempo = (((float)comtage /30.518)/65536 );
sprintf(DEPHASAGE,"%.5f ",Deph_tempo);
LCD_String_xy(2,DEPHASAGE);
}
TMR1=0;
TMR1ON=0;
CCP1CON=0b00000101;
}
}
解决方法
减少等待 CCP1IF 时执行的指令数将提高精度。你试过这个吗?
// ...
while (1)
{
CCP1CON = 0b00000101;
PIR1bits.CCP1IF = 0;
TMR1ON = 0;
TMR1 = 0;
// if your comms with the LCD use interrupts:
//
// disable interrupts here
while (!PIR1bits.CCP1IF)
;
TMR1ON = 1;
CCP1CON = 0b00000100;
PIR1bits.CCP1IF = 0;
while (!PIR1bits.CCP1IF)
;
compte = TMR1;
// if your comms with the LCD use interrupts:
//
// enable interrupts here
// refresh display
// if your comms with the LCD use interrupts:
//
// you may want to add a small delay here,to
// allow for comms to the LCD to end.
// this may not be necessary,depending on the
// signal frequency.
}
// ...
如果这不起作用,您应该检查 LCD 是否没有使用中断。
如果是这样,您应该:
- 在读取样本之前禁用中断
- 在计时时禁用中断
- 在更新显示前启用中断
- 在进行下一个采样之前添加一个延迟,该延迟应该足够长以便 LCD 缓冲区清空。
这是一个不使用中断的解决方案......我认为使用引脚更改中断和自由运行的计时器会获得更好的结果。
编辑:编写此解决方案后,我在您的代码中发现了以下代码行中的错误:
while(!(PIR1bits.CCP1IF==1)) // this is missing a ;
comtage= TMR1; // this line gets executed in the loop
// and adds instructions to the
// loop,this probably more than
// halves the precision of your
// results.
// the imprecision is increased with
// your code that runs after the if block