当前位置: 代码网 > 科技>人工智能 > 基于STM32的电阻、电容测量(NE555芯片RC振荡法)

基于STM32的电阻、电容测量(NE555芯片RC振荡法)

2024年08月02日 人工智能 我要评论
做的一个关于电阻和电容的测量电路,都是比较通用的。经过实际测试,电容测量电路还是可以的,电阻测量电路有一个缺点就是,随着测量时长的推移,在小电阻的测量时,比如0-100欧姆测量时,检测到的RC震荡频率会增加, 所以小电阻需要校正一下,否则小电阻容易出现较大的偏差。大电阻的话测量精度还是可以的。码字不易,希望大家三连支持一下!!你们的支持就是我分享的动力!


前言

做的一个关于电阻和电容的测量电路,都是比较通用的。经过实际测试,电容测量电路还是可以的,电阻测量电路有一个缺点就是,随着测量时长的推移,在小电阻的测量时,比如0-100欧姆测量时,检测到的rc震荡频率会增加, 所以小电阻需要校正一下,否则小电阻容易出现较大的偏差。大电阻的话测量精度还是可以的。


一、电路图

在这里插入图片描述
具体的电阻电容选值已经标好了,这个电阻电容的选值对应的测量范围为电阻10-1m欧姆,电容1-220nf左右。输出f口的作用主要在于通过两个自锁开关切换电阻或者电容的测量,只用占用单片机的一个io口,这个io口进行外部中断。

1.电阻测量公式

在这里插入图片描述
fr为我们测量到的频率
在实际电路中,r12和r13均被设置为1.5k。由于单片机内部被设定为每隔一秒钟检测一次脉冲的个数,故在极限状况下可以测的大范围的电阻。若需要改进优化范围,可以改变r13和r12电阻的大小,使其产生不同的谐振状态,从而实现不同范围的需求。

2.电容测量公式

在这里插入图片描述
同样fc为测的电容频率

二、代码实现

1.外部中断代码

#include "exti.h"
#include "key.h"
#include "delay.h"
#include "stm32f10x_exti.h" 
long pulsenum;	//脉冲个数 
void extix_init(void)//外部中断初始化函数
{
  exti_inittypedef exti_initstructure;
  nvic_inittypedef nvic_initstructure;
  rcc_apb2periphclockcmd(rcc_apb2periph_afio,enable);//外部中断,需要使能afio时钟
  gpio_extilineconfig(gpio_portsourcegpioa,gpio_pinsource15);
  exti_initstructure.exti_line=exti_line15;
  exti_initstructure.exti_mode = exti_mode_interrupt;	
  exti_initstructure.exti_trigger = exti_trigger_falling;
  exti_initstructure.exti_linecmd = enable;
  exti_init(&exti_initstructure);	  	//根据exti_initstruct中指定的参数初始化外设exti寄存器
  nvic_initstructure.nvic_irqchannel = exti15_10_irqn;			//使能按键所在的外部中断通道
  nvic_initstructure.nvic_irqchannelpreemptionpriority = 0x00;	//抢占优先级2, 
  nvic_initstructure.nvic_irqchannelsubpriority = 0x01;					//子优先级1
  nvic_initstructure.nvic_irqchannelcmd = enable;								//使能外部中断通道
  nvic_init(&nvic_initstructure); 
}
void exti15_10_irqhandler(void)
{
  pulsenum++;
  exti_clearitpendingbit(exti_line15); 
}

外部中断主要是为了采集电阻电容端口对应的频率,此处的话是用pa15作为中断触发口。

2.定时器中断处理数据

代码如下(示例):

#include "timer.h"
#include "led.h"
#include "usart.h"
#include "adc.h"
#include "exti.h"
#include "main.h"
//电阻--------------------------------
unsigned long  z1=14026950.00;
float rz=0;
unsigned long   rx=0;
unsigned long   rx2=0;
unsigned long   rx3=0;
unsigned long   rx4=0;
unsigned long   rx5=0;
unsigned long   rx6=0;
unsigned long   rx7=0;
unsigned long   rx8=0;
unsigned long   rx9=0;
unsigned long   r=0;
//电容--------------------------------
float cz=0;
float cx=0;
unsigned long   x;
void tim3_int_init(u16 arr,u16 psc)
{
  tim_timebaseinittypedef  tim_timebasestructure;
	nvic_inittypedef nvic_initstructure;
	rcc_apb1periphclockcmd(rcc_apb1periph_tim3, enable);
	tim_timebasestructure.tim_period = arr;
	tim_timebasestructure.tim_prescaler =psc;  
	tim_timebasestructure.tim_clockdivision = 0;
	tim_timebasestructure.tim_countermode = tim_countermode_up;  
	tim_timebaseinit(tim3, &tim_timebasestructure);  
	tim_itconfig(tim3, tim_it_update|tim_it_trigger,enable);
	nvic_initstructure.nvic_irqchannel = tim3_irqn;  
	nvic_initstructure.nvic_irqchannelpreemptionpriority = 0;  
	nvic_initstructure.nvic_irqchannelsubpriority = 3;  
	nvic_initstructure.nvic_irqchannelcmd = enable; 
	nvic_init(&nvic_initstructure);  
	tim_cmd(tim3, enable);  							 
}
void tim3_irqhandler(void)   //tim3中断
{
	static u16 count;
	if (tim_getitstatus(tim3, tim_it_update) != reset) //检查指定的tim中断发生与否:tim 中断源 
	{
		/*电阻采集*/
		count++;
    if(count >= 1000)
	  {
			count = 0;
			x = pulsenum;                                                  //测得的脉冲值数量,也就是fr
			if(mode==3)
			{
				if(x<=8)z1=14006950.00;
				else if(x>8&&x<30)z1=14726950.00;
				else if(x>30&&x<300)z1=14526950.00;
				else if(x>300&&x<1000)z1=14867950.00;
				else if(x>1000&&x<5000)z1=14467950.00;
			  rz=(z1/x);                                                     //测量100到1000
			  rx=rz-1500;
			  rx=rx>>1;                                                      //对应的除以2
        if(rx>=1490)
        {
          rx=rx-1490;
        }else
        {
			    rx=0;
        }
			  if(x==0){rx=0;rx2=0;rx3=0;rx4=0;rx5=0;rx6=0;rx7=0;rx8=0;rx9=0;}//如果测得的频率为0,则此次测得的结果都为0
        if(rx>2000000){rx=2000000;}                                    //如果电阻测得的结果大于1m欧姆,则结果就等于1m欧姆
			  rx2=(rx+rx3+rx4+rx5+rx6+rx7+rx8+rx9)>>3;                //求平均提高精度
			  rx9=rx8;rx8=rx7;rx7=rx6;rx6=rx5;rx5=rx4;rx4=rx3;rx3=rx; //依次赋值
				pulsenum = 0;
			}
			/*电容采集*/
			else if(mode==4)
			{
				cz=708317/x-7;
				if(cz>9999999)cz=9999999;  //限制最高值
				pulsenum = 0;
			}
		}
		tim_clearitpendingbit(tim3, tim_it_update  );  //清除timx的中断待处理位:tim 中断源 
	}
}

从上往下看,在电阻参数设置一栏里面,定义了rx-rx9还有r,这个主要是为了提高电阻测量的精度。在实际的测试过程中电阻需要测量八次才能得到一个稳定的电阻值,也就是8s左右得到稳定的电阻值。z1是我们设置好的一个参数。通过调节这个参数可以改变我们的精度。电容参数设置也是一样,x是我们每秒检测到的一个频率值。通过外部中断里面的pulse赋值。

在定时器三中断里面有一个count计数,此处定时器设置的频率为1khz,因此count计数到1000的时候自动归零,也代表过了一秒钟,所以进行一次脉冲数的赋值给x。mode是我们设置的检测模式,此处当模式为3的时候进行电阻的测量,模式为4的时候进行电容的测量。

x的值越小,代表测量的电阻阻值越大。一般我调试的时候会进行划分区间段的调试,这样能够尽可能地提升测量的精度。通过keil的软件仿真观测不同阻值对应不同x值,从而改变z1的大小,z1越大,阻值就越大。z1越小,阻值就越小。通过改变z1的大小,从而获得某个区间段更优的数据。在if(rx>=1490)里面,这个1490的值是不确定的,是要根据你测量小电阻的时候来。假设如果10欧姆的电阻测量起来以后显示20欧姆的话,请把多余的这部分带入到上面的公式里面,修改1490的大小,如果大于真实电阻值的话,就把这个1490略微增大点,如果小于真实电阻值的话,就把1490稍微减小一点。

电容采集这边的话就是改变708317这个值,你可以用小电容定标,也可以用大电容定标,这都是没问题的,通过改变这个值获得更高精度的电容测量值。前提是测量的电容都是无极性电容


在主函数中,只需要调用着两个数值即可,即可获得想要的电阻电容值。


总结

码字不易,希望大家三连支持一下!!你们的支持就是我分享的动力!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com