PIC频率捕获程序

2019-03-25 18:44发布

从PIC教材上找的一段程序码,关于PIC16F877A用于频率捕捉的,但是源程序敲进去后数码管无显示;教材附带hex文件显示正常。急,求解!谢谢!

以下为程序码:

//-----------------------------------------------------------------
//  名称: 用工作于捕获方式的CCP1设计的频率计
//-----------------------------------------------------------------
//  说明: 在切换不同的频率输入后按下K1按键,数码管上将显示当前频率值.
//        两次捕获的时间差值即为当前输入频率的周期,倒数可得频率.
//
//-----------------------------------------------------------------
#include <pic.h>
#define INT8U   unsigned char
#define INT16U  unsigned int
#define _XTAL_FREQ 4000000UL               

//按键定义
#define Key_DOWN() (RC5 == 0)

//共阴数码管0~9的数字编码,最后一位为黑屏
const INT8U SEG_CODE[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00 };
//const INT8U SEG_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//分解后的待显示数位
INT8U Display_Buffer[] = {0,0,0,0};

//显示开关控制变量
INT8U Disp_ON = 0;

//连续两次捕获计数变量
volatile INT16U CAPi = 0,CAPj = 0;

//连续三次检测的频率值
volatile INT16U Freq[] = {0,0,0};
//-----------------------------------------------------------------
// 数码管显示频率
//-----------------------------------------------------------------
void Show_FRQ_ON_DSY()
{   
    //INT8U i = 0;
    if (!Disp_ON) return;                                                //如果禁止显示则直接返回
    for (INT8U i = 0; i < 4; i++)
    {
                PORTB=0X00;        //暂时关闭数码管
                PORTD=~(0X10<<i);                                                //先发送扫描码(RD4-RD7依次扫描)
                PORTB=SEG_CODE[Display_Buffer[i]];                //发送数字段码

                if(i==0)       
                        RB7=1;                                                //最高位加小数点

                __delay_ms(2);
    }

}



//------------------------------------------------------------------
// CCP1输入捕获中断子程序(6次捕获,获取3次检测的频率值)
//------------------------------------------------------------------
void interrupt CCP1_Capture_INT()
{
    static INT8U Fi = 0;                           //频率数组索引
        if(CCP1IF)                                //读取第一次捕获值
        {
                if(CAPi==0)       
                        CAPi=((CCPR1H<<8)+CCPR1L);

                else                                //第二次捕获
                {
                        CAPj=((CCPR1H<<8)+CCPR1L);
                        CAPj=1000000UL/(CAPj-CAPi);                //根据相减得到周期计算频率(us)
                        Freq[Fi]=CAPj;                                        //保存第i次检测到的频率并递增索引

                        if(++Fi==3)                                                //达到3次后开始判断检测频率是否相等
                        {
                                Fi=0;
                                if(Freq[0]==Freq[1]&&Freq[0]==Freq[2])                //如果3次检测频率相等,则停止检测,并分解显示数位
                                {
                                        CCP1IE=0;        //禁止CCP1中断
                                        TMR1ON=0;        //禁止TIMER1计数

                                        for(INT8U i=3;i!=0xff;i--)                //分解频率数位并放入显示缓冲
                                        {
                                                Display_Buffer[i]=CAPj%10;
                                                CAPj/=10;                                        //            a/=b等同于a=a/b;
                                        }
                                        Disp_ON=1;                //开显示
                                        return;                        //返回
                                }
                        }
                        TMR1H=TMR1L=CAPi=CAPj=0;                //如未完成连续3次检测(6次捕获)则继续(TMR1和相关变量清零)
                }
                CCP1IF=0;                                //软件清0中断标志位
        }
}
//------------------------------------------------------------------
// 主程序
//------------------------------------------------------------------
void main()
{
        ADCON1=0x06;                //关闭模拟端口
        TRISC5=1;                        //按键输入
        TRISC2=1;                        //CCP1输入
        TRISB=PORTB=0X00;        //数码管显示端口输出
        TRISD=PORTD=0X00;
        CCP1CON=0X05;                //设置CCP1捕捉模式,捕捉上升沿
        CCP1IF=0;                        //清除CCP1中断标志
        TMR1ON=0;                        //TMR1停止

    while(1)
    {
                if(Key_DOWN())                //按键判断
                {
                        __delay_ms(10);        //延时消抖
                        if(Key_DOWN())        //确认按下,开始检测频率
                        {
                                PORTB=0X00;        //关闭共阴极数码管段码(黑屏)
                                Disp_ON=0;        //禁止显示
                                CCP1IE=0;        //使能CCP1捕获中断
                                TMR1ON=1;        //启动TMR1中断计数
                                PEIE=1;                //使能外设中断
                                GIE=1;                //开中断
                    }
                }
                Show_FRQ_ON_DSY();                //数码管刷新显示频率
        }
}

此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
dingzy_2002
1楼-- · 2019-03-26 12:44
hschengyg 发表于 2018-10-8 13:33
版主你好!
我在网上下载了PIC16F72转速表ASM汇编程序,因不懂ASM汇编,编译失败,请教帮忙修改一下。并请 ...

好的,有空我看下.

一周热门 更多>