OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4130|回复: 1

请教输入捕获实验测脉宽,自动切换量程不成功

[复制链接]

2

主题

12

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2016-9-24
在线时间
14 小时
发表于 2017-7-11 12:06:59 | 显示全部楼层 |阅读模式
20金钱
本帖最后由 windwood 于 2017-7-11 12:06 编辑

    各位好,小弟新手入门,有个问题困扰好几天了。使用的是F407开发平台,是在原子哥输入捕获实验代码修改的。实现功能:根据555单稳态触发的原理,可以得到脉冲宽度Tw=1.1RC ,R已知,进而测量电容大小。
档位设置:R有1K,10K,100K,2M四个阻值,设置四个档位,电容C的测量范围100pF-1000uF
  
档位
  
电阻
电容范围
时间范围Tw=1.1RC
PA11
PA10
第一档
1K
100uF-1000uF
110,000us-1100,000us
0
0
第二档
10K
1uF-100uF
11,000us-1100,000us
0
1
第三档
100K
10nF-1uF
1100us-110,000us
1
0
第四档
2M
100pF-10nF
220us-2200us
1
1
硬件原理
原理.png
按照本表格接线。PB11为定时器2通道5。
  
网络标号
  
Cap_tri
Cap_out
Cap_sel_L
Cap_sel_H
功能
触发信号
输出信号
档位选择控制低位
档位选择控制高位
接入芯片引脚
PA8
PB11
PA10
PA11
程序代码
主程序main.c如下
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"

extern u8  TIM2CH4_CAPTURE_STA;                //êäèë2¶»ñ×′쬠                                                  
extern u32        TIM2CH4_CAPTURE_VAL;        //êäèë2¶»ñÖμ

int main(void)
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//éèÖÃÏμí3ÖD¶ÏóÅÏ輶·Ö×é2
        delay_init(168);  //3õê¼»ˉÑóê±oˉêy
        uart_init(115200);//3õê¼»ˉ′®¿ú2¨ìØÂêÎa115200
        CapShift();       
}

timer.c如下:
#include "timer.h"
#include "led.h"
#include "usart.h"
#include "delay.h"

unsigned int CapShiftNum; //档位标识,CapShiftNum 从1,2,3,4取值
unsigned long Cv;        //电容值
long long Tw;             //脉宽


TIM_ICInitTypeDef  TIM2_ICInitStructure;

//定时器2通道4
//arr自动重装载值
//psc时钟预分频数
void TIM2_CH4_Cap_Init(u32 arr,u16 psc)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);         
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);        
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //GPIOA8
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;       
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
        GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化ˉPA8,PA8是Ctri 触发信号,低电平触发555.
       
       
        //初始化PA10,PA11,CSH=PA11,CSL=PA10
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; //GPIOA10,11
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;       
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //GPIOB11
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_Init(GPIOB,&GPIO_InitStructure);

        GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_TIM2); //PA0复用为定时器2

          
        TIM_TimeBaseStructure.TIM_Prescaler=psc;
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
        TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
       

        //初始化TM2输入捕获参数
        TIM2_ICInitStructure.TIM_Channel = TIM_Channel_4;
  TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;        //上升沿捕获
  TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM2_ICInitStructure.TIM_ICFilter = 0x00;//不滤波
  TIM_ICInit(TIM2, &TIM2_ICInitStructure);
               
  TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许中断
       
  TIM_Cmd(TIM2,ENABLE );         //使能定时器


        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//ÇàÕ¼óÅÏ輶3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;                //×óóÅÏ輶3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                       
        NVIC_Init(&NVIC_InitStructure);       
       
       
}

u8  TIM2CH4_CAPTURE_STA=0;        //输入捕获状态                                           
u32        TIM2CH4_CAPTURE_VAL;        //输入捕获值(TIM2,32位)

void TIM2_IRQHandler(void)
{                     

        if((TIM2CH4_CAPTURE_STA&0X80)==0)//还未捕获成功
        {
                if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)//溢出
                {             
                        if(TIM2CH4_CAPTURE_STA&0X40)//已经捕获到了高电平了
                        {
                                if((TIM2CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长
                                {
                                        TIM2CH4_CAPTURE_STA|=0X80;                //标记成功捕获了一次
                                        TIM2CH4_CAPTURE_VAL=0XFFFFFFFF;
                                }else TIM2CH4_CAPTURE_STA++;
                        }         
                }
                if(TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)//捕获1发生捕获事件
                {       
                        if(TIM2CH4_CAPTURE_STA&0X40)                //捕获到下降沿       
                        {                                 
                                TIM2CH4_CAPTURE_STA|=0X80;                //标记成功捕获到一次高电平脉宽
                          TIM2CH4_CAPTURE_VAL=TIM_GetCapture4(TIM2);//获取当前的捕获值
                                 TIM_OC4PolarityConfig(TIM2,TIM_ICPolarity_Rising); //设置上升沿捕获
                        }else                                                                  // 还未开始,第一次捕获上升沿
                        {
                                TIM2CH4_CAPTURE_STA=0;                        //清空
                                TIM2CH4_CAPTURE_VAL=0;
                                TIM2CH4_CAPTURE_STA|=0X40;                //标记捕获到了上升沿
                                TIM_Cmd(TIM2,DISABLE );         //关闭TIM2
                                 TIM_SetCounter(TIM2,0);
                                 TIM_OC4PolarityConfig(TIM2,TIM_ICPolarity_Falling);                //设置下降沿捕获
                                TIM_Cmd(TIM2,ENABLE );         //ê1Äü¶¨ê±Æ÷2
                        }                    
                }                                                                                   
        }
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC4|TIM_IT_Update); //清楚中断标志位
}

void CapMessure( void )
{
        TIM2_CH4_Cap_Init(0XFFFFFFFF,84-1); //òÔ1MhzμÄÆμÂê¼Æêy
       
Cap_tri=1;
         delay_us(10);
Cap_tri=0;//触发信号低电平,触发555
         delay_us(10);
Cap_tri=1;
       
          delay_ms(2000);
                if(TIM2CH4_CAPTURE_STA&0X80)        //成功捕获到了一次高电平
                {
                        Tw=TIM2CH4_CAPTURE_STA&0X3F;
                        Tw*=0XFFFFFFFF;                                          //溢出时间总和
                        Tw+=TIM2CH4_CAPTURE_VAL;                   //得到总的高电平时间Tw
                        printf("HIGH:%lld us\r\n",Tw);
                        TIM2CH4_CAPTURE_STA=0;                             //开启下一次捕获
                }
}


/****************************************************
档位     电阻       电容范围        时间范围Tw=1.1RC
*第一档    1k       100uf——1000uf     110,000us¡a¡a1100,000us
*第二档    10k      1uf——100uf        11,000us¡a¡a1100,000us
*第三档    100k     10nf——1uf         1100us¡a¡a110,000us
*第四档    2000k    100pf——10nf       220us¡a¡a2200us
****************************************************/



void CapShift( void )
{
   //档位确定
   //----------------
   CapShiftNum=2;     //11ms<Tw<1.1s为第二档
   Cap_sel_H=0;        //初始化为第二档
   Cap_sel_L=1;
   CapMessure();       //获得时间Tw,此时电阻为10K
   printf("test1\n");
   if(Tw>1000000)      //Tw>1.3s 档位为1档; 100uf为1330000
         { CapShiftNum=1;   //档位标识第一档
           printf("test2\n");
         }
   if(Tw<13000)                   //Tw<13ms 档位可能为三四档 1uf为13103
   {
      CapShiftNum=3;   //Tw<11ms 为第三档
      Cap_sel_H=1;     //处于第三档
      Cap_sel_L=0;
      CapMessure();    //重新测量时间Tw,此时电阻为100K(用于判断是第三档还是第四档)
      if(Tw<1100)
                        { CapShiftNum=4;  //Tw<11ms 为第四档
                        printf("test3");}
    }
    //----------------
   //档位确定结束
   //----------------
   switch(CapShiftNum)
    {
      case 1:Cap_sel_H=0;     //处于第一档
             Cap_sel_L=0;
        break;
      case 2:Cap_sel_H=0;     //处于第二档
             Cap_sel_L=1;
        break;
      case 3:Cap_sel_H=1;     //处于第三档
             Cap_sel_L=0;
        break;
      case 4:Cap_sel_H=1;     //处于第四档
             Cap_sel_L=1;
        break;
    }
        delay_ms(100);
  CapMessure();             //确定完档位后,再次测量Tw


        switch(CapShiftNum)
    {
      case 1:
                        if(Tw>700000)
                        {Cv=Tw/0.9;
                        printf("Capacity1:%ld nf\r\n",Cv);
                        }
                        else
                        {
                                Cv=Tw/1.2;
                                printf("Capacity1:%ld nf\r\n",Cv);
                        }
        break;
     case 2:
                        if(Tw<100000)
                        {Cv=Tw/12;
                                printf("Capacity2:%ld nf\r\n",Cv);
                        }
                        else
                        {
                        Cv=Tw/12;
                        printf("Capacity2:%ld nf\r\n",Cv);
                        }
                   break;
         case 3:
                               
                        if(Tw>20000)
                        {Cv=Tw/0.11;
                                printf("Capacity3:%ld pf\r\n",Cv);
                        }
                        else
                                {Cv=Tw/0.113;
                                printf("Capacity3:%ld pf\r\n",Cv);
                                }
                break;
         case 4:
                         if(Tw>10000)        Cv=Tw/2.2;
                        if(Tw<10000&&Tw>1200) Cv=Tw/2.1;
                        if(Tw<1200) Cv=(Tw-53)/2.2;
            printf("Capacity4:%ld pf\r\n",Cv);
                break;
    }
}

运行结果:
接入33uF电容测量,串口调试助手截图如下:

O438DW63G73ZRWZ]6{1I`OR.png
如果把delay_ms(2000);改为delay_ms(5000);运行结果如下:
5s.png
测量结果为34uF左右,和电解电容的33uF差别不大,误差3%以内。
请教一下几个问题:
1)程序执行过程中为什么是先打印了test1,而在CapMessure( void )中,并没有打印脉宽Tw,这个执行的逻辑顺序没有搞明白,没想通,请大神指点。
2)如结果中的第一个图,延迟时间改为2s,测量的Tw也是2s,大概就是2s内,充电还没完成,下降沿还没到来。数据溢出了,那么既然这样,我档位选择开关应该调到1档位,再测试,再打印,为什么没有自动换挡,程序哪儿出问题了。

希望各位前辈多多指教!小弟感激不尽!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165359
金钱
165359
注册时间
2010-12-1
在线时间
2110 小时
发表于 2017-7-12 01:14:37 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-12-18 16:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表