新手上路
- 积分
- 45
- 金钱
- 45
- 注册时间
- 2016-9-24
- 在线时间
- 14 小时
|
20金钱
本帖最后由 windwood 于 2017-7-11 12:06 编辑
各位好,小弟新手入门,有个问题困扰好几天了。使用的是F407开发平台,是在原子哥输入捕获实验代码修改的。实现功能:根据555单稳态触发的原理,可以得到脉冲宽度Tw=1.1RC ,R已知,进而测量电容大小。
档位设置:R有1K,10K,100K,2M四个阻值,设置四个档位,电容C的测量范围100pF-1000uF
硬件原理:
按照本表格接线。PB11为定时器2通道5。 程序代码:
主程序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电容测量,串口调试助手截图如下:
如果把delay_ms(2000);改为delay_ms(5000);运行结果如下:
测量结果为34uF左右,和电解电容的33uF差别不大,误差3%以内。
请教一下几个问题:
1)程序执行过程中为什么是先打印了test1,而在CapMessure( void )中,并没有打印脉宽Tw,这个执行的逻辑顺序没有搞明白,没想通,请大神指点。
2)如结果中的第一个图,延迟时间改为2s,测量的Tw也是2s,大概就是2s内,充电还没完成,下降沿还没到来。数据溢出了,那么既然这样,我档位选择开关应该调到1档位,再测试,再打印,为什么没有自动换挡,程序哪儿出问题了。
希望各位前辈多多指教!小弟感激不尽!
|
|