[讨论] PCA捕获

dj狂人   2014-5-10 20:54 楼主
void PCA_Init(void)
{
        CCON = 0x00;             //初始化PCA控制寄存器                              
                                                                                                         
        CL = 0;                        
        CH = 0;
        CCAP0L = 0x00;
        CCAP0H = 0x00;
       
        CMOD = 0x09;              //设置PCA时钟源为系统时钟,且使能PCA计时溢出中断

       CCAPM0 = 0x31;           //PCA模块0为16位捕获模式(上升沿/下降沿捕获,可测高电平或者低电平宽度),且产生捕获中断   

       CR = 1;             //PCA计时器开始运行
       EA = 1;             //开总中断         
}

void PCA_isr() interrupt 7 {    if (CF)    {        CF = 0;        cnt++;                      //PCA计时溢出次数+1    }    if (CCF0)    {        CCF0 = 0;        Hcycle = CCAP0H;    //保存本次的捕获值    高位        Lcycle = CCAP0L;    //保存本次的捕获值    低位        //CL = 0;                                     //CH = 0;    }}
           PCA捕获折腾两天了,原想用来测脉冲波脉宽的,求占空比、周期什么的。           上面两个程序原来是想脉冲来的时候,通过取得CCAP0H、CCAP0L的数据求周期和占空比来着,Hcycle、Lcycle 是全局变量,退出中断后把Hcycle、Lcycle整合成16数据用串口显示。
void main(void){                                                                         UART_Init();
        while(1)        {                cycle = Hcycle;      //Hcycle、Lcycle初始值为零                cycle = cycle << 8;                cycle = cycle | Lcycle;                                if(cycle)  //不为零时输出                {                                 UART_Send_St (cycle); //串口显示                         Hcycle = 0;                         Lcycle = 0;                         cyde = 0;                }                                }}
         按我的的想法应该是脉冲接入后在串口是可以不停的显示cyde 的,可实际接入脉冲后它没反应,只有断开脉冲输入后才出一个数据,我看着数据手册改过PCA初始化部分,可还是一点效果没有,是我哪里设置错了吗?????都快崩溃了

回复评论 (27)

void PCA_Init(void)
{
        CCON = 0x00;             //初始化PCA控制寄存器                              
                                                                                                         
        CL = 0;                        
        CH = 0;
        CCAP0L = 0x00;
        CCAP0H = 0x00;
        
        CMOD = 0x09;              //设置PCA时钟源为系统时钟,且使能PCA计时溢出中断

       CCAPM0 = 0x31;           //PCA模块0为16位捕获模式(上升沿/下降沿捕获,可测高电平或者低电平宽度),且产生捕获中断   

       CR = 1;             //PCA计时器开始运行
       EA = 1;             //开总中断         
}

void PCA_isr() interrupt 7 {   
      if (CF)   
      {  
            CF = 0;
             cnt++;                      //PCA计时溢出次数+1   
      }   
      if (CCF0)
      {  
           CCF0 = 0;  
           Hcycle = CCAP0H;    //保存本次的捕获值    高位   
           Lcycle = CCAP0L;    //保存本次的捕获值    低位   
           //CL = 0;                              
           //CH = 0;  
       }
}
         
void main(void)
{                                                                    
       UART_Init();
       while(1)  
      {            
              cycle = Hcycle;      //Hcycle、Lcycle初始值为零         
              cycle = cycle << 8;         
              cycle = cycle | Lcycle;                        
              if(cycle)  //不为零时输出     
             {                        
                     UART_Send_St (cycle); //串口显示               
                     Hcycle = 0;      
                     Lcycle = 0;              
                     cyde = 0;      
              }                        
       }
}
  无语,编辑的时候好好的,一发帖就乱了
点赞  2014-5-10 20:59
找出原因了,居然是幅值不够,幅值太低单片机检测不出高电平,我居然折腾了那么久!!!无语...............................
点赞  2014-5-11 14:10
呵呵,楼主的经历再次说明"有时候别人很难帮忙的"
点赞  2014-5-12 09:46
引用: huo_hu 发表于 2014-5-12 09:46
呵呵,楼主的经历再次说明"有时候别人很难帮忙的"

又卡住了,我用的是STC12C5A60S2,12T 模式,晶振12M的,按道理一个机器周期计一次数,那么读出计时器相应的计数值以及它的溢出次数,就能得到
相应的时间。然后我用PCA选择跳变沿方式检测频率为 1 Hz的脉冲波,可是得到的数据求出的周期却远大于 1 s
点赞  2014-5-12 12:21
       while(1)  
       {            
               cycle = Hcycle;      //Hcycle、Lcycle初始值为零         
               cycle = cycle << 8;         
               cycle = cycle | Lcycle;                        
               if(cycle)  //不为零时输出  
这段啥意思
点赞  2014-5-12 13:29
引用: huo_hu 发表于 2014-5-12 13:29
while(1)  
       {            
               cycle = Hcycle;      //Hcycle、Lcycle初始值 ...

计数值
点赞  2014-5-12 16:45
我知道错哪了,队友一语惊醒梦中人。以前用51的定时/计数器的时候,忘了它有12分频的这茬,12M的晶振12分频之后才是一个脉冲计数一次,也就是一微妙计数一次。而我用PCA模式直接是用系内部时钟作计时脉冲,没考虑还有12分频这部分,导致数据处理错误
点赞  2014-5-12 16:53
PCA捕获在跳变沿模式时,触发时怎么知道它是上升沿触发还是下降沿触发。我试过判断相应引脚电平的高低来求占空比,可是这样得到数据是错误的
点赞  2014-5-15 21:55
引用: dj狂人 发表于 2014-5-15 21:55
PCA捕获在跳变沿模式时,触发时怎么知道它是上升沿触发还是下降沿触发。我试过判断相应引脚电平的高低来求 ...

是不是太快了,读取的状态不定.
点赞  2014-5-16 10:58
引用: huo_hu 发表于 2014-5-16 10:58
是不是太快了,读取的状态不定.

应该是,如果这样不行的话。有什么办法知道当前触发是上升沿触发还是下降沿触发吗
点赞  2014-5-16 12:11
引用: dj狂人 发表于 2014-5-16 12:11
应该是,如果这样不行的话。有什么办法知道当前触发是上升沿触发还是下降沿触发吗

这个51好像无解了
点赞  2014-5-16 13:45
引用: huo_hu 发表于 2014-5-16 13:45
这个51好像无解了

得了,开外部中断下降沿触发和跳变沿触发或开两路PCA捕获模块,一路上升沿触发、一路跳变沿触发 ,就可以知道那个是高电平的时间了  
点赞  2014-5-19 11:04
引用: dj狂人 发表于 2014-5-19 11:04
得了,开外部中断下降沿触发和跳变沿触发或开两路PCA捕获模块,一路上升沿触发、一路跳变沿触发 ,就可以 ...

也行,一路应该也可以的,是不是IO的状态不对呢?
点赞  2014-5-19 11:20
引用: huo_hu 发表于 2014-5-19 11:20
也行,一路应该也可以的,是不是IO的状态不对呢?

不懂,靠检测I/O状态的方法试过了,不行。请问下STC12C5A60S2 用24M的晶振,然后PCA模式选择2分频计数,按道理应该能测到500KHz的频率吧,可为什么我的只要一上到25KHz测的周期就开始出错了呢
点赞  2014-5-19 11:26
引用: huo_hu 发表于 2014-5-19 11:20
也行,一路应该也可以的,是不是IO的状态不对呢?

不知道是不是我的程序问题,有空能帮看下吗
点赞  2014-5-19 11:27
引用: dj狂人 发表于 2014-5-19 11:27
不知道是不是我的程序问题,有空能帮看下吗


怀疑你的显示部分开销太大了,你这样,在 if (CCF0)里输出一个io翻转,用示波器比较这个信号和输入,看看,如果一致那就是开销的问题.
点赞  2014-5-19 12:28
引用: huo_hu 发表于 2014-5-19 12:28
怀疑你的显示部分开销太大了,你这样,在 if (CCF0)里输出一个io翻转,用示波器比较这个信号和输入,看看, ...

QQ图片20140519145429.jpg QQ图片20140519145436.jpg
34KHz以下的话,还一致,上了34K就不行了
点赞  2014-5-19 14:58
测脉宽、频率什么的还是定时、计数 好,12M的晶振能测到6M。测量精度是够的,数据会有一点点跳,效果还是不错的。
点赞  2014-7-6 09:11
至于PCA捕获的话,不管系统晶振用到多大,只要测量频率上到40KHz就不行了,个人感觉是它内部时间花销太大造成的。不过可以用它测频率较低的脉宽,1Hz-20KHz,这样就可以补上定时、计数 测脉冲信号时,频率太低造成费时这个缺陷
点赞  2014-7-6 09:16
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复