其他分享
首页 > 其他分享> > 身价过亿的温柔萝莉对小码农说ADC会采集吗

身价过亿的温柔萝莉对小码农说ADC会采集吗

作者:互联网

文章目录


在这里插入图片描述

小码农电压使者怎么敢说不会采集

模拟量—>数字量(ADC模块)

模拟量与单片机的数字量之间的关系

5V 单片机 CPU 电路是二进制的,运算过程中,电压只有2种:高电平 5V 和低电平 0V 。对于电压或者电流连续变化的信号,就需要通过模数转换电路,变成单片机可以识别的数字电平信号。 MP3 就是用 ADC 采样保存的失真文件。

模拟量转换成数字的方式

模拟量变成数字量,通常都是用比较器来负责转换。目前来说,常见的有两种方式,一种是并行比较,一种是逐次比较

**并行比较器:**速度比较快,但是采用的元件非常非常多。成本会非常高。所以,实用性不是很广泛

**逐次比较器:**通过反馈控制,多次运算后,转换出结果。具有成本低、元件简单等优势,而且容易做出高精度的转换器,所以被广泛使用。

逐次比较器ADC的概念

一个超级好的例子分享给你们

先来玩个游戏 :狗蛋拿了些花生米,跟你说,想吃就要先猜对有多少个。告诉你最多是 255 颗,你猜的时候,可以告诉你多了或者少了。那么,怎么猜才能最快猜出花生米的数量?
猜的时候,为了方便计算, 我们多加 0.5 颗花生米。
==第一步:==猜 255 ÷ 2 +0.5=128. 狗蛋告诉你,多了 (0) 。
第二步:猜 128 ÷ 2=64. 狗蛋告诉你,少了 (1)。
第三步:猜 (128 + 64) ÷ 2=96. 狗蛋 告诉 你,多了 (0) 。
第四步:猜 (96 + 64) ÷ 2=80. 狗蛋 告诉 你,少了 (1) 。
第五步:猜 (96 + 80) ÷ 2=88. 狗蛋 告诉 你,少了(1)。
第六步:猜 (96 + 88) ÷ 2=92. 狗蛋 告诉 你,多了(0)。
第七步:猜 (92+ 88) ÷ 2=90. 狗蛋 告诉 你,多了(0) 。
第八步:猜 (90+ 88) ÷ 2=89. 狗蛋 告诉 你,猜对 (?) 。
得出结果: 如果不加 0.5 ,实际计算公式得结果是 88.65234375 。实际上88.65比89小所以是 1
四舍五入, 89>88.65, 取 ?= 1 ;得出结果就是 0 1 0 1 1 0 0 1 =89=0x59;

image-20211120094547097

STC内部ADC模块的寄存器

image-20211120110912878

1.ADC口配置成ADC输入模式或者高阻模式

2.ADC控制寄存器:ADC_CONTR.控制电源,转换速度,标志位,启动位,通道选择[2:0]

3.ADC采样结果输出寄存器ADC_RES,ADC_RESL。可以是[1:0]+[7:0],也可以是[7:0]+[1:0].

4.ADC转换,跟中断有关的寄存器IE

5.辅助寄存器AUXR1,主要是控制结果寄存器的存储格式

这里我们需要采集电池电压(我们用P1.0采集)

我是准备用ADC0来检测电池电压的,具体看老师需求,然后把示数显示到数码管上面,因为之前我出过数码管博客,大家可能还有点印象,不知道的看真正的数码管

P1M1 |= 0x01;P1M0 &= ~0x01;//P1.0脚ADC0

image-20211004005045030

P1ASF |= 0x01;

image-20211004075742165

CLK_DIV |= 0x20;

image-20211004054800063

ADC_RES = 0;ADC_RESL = 0;

image-20211004055220496

ADC初始化

image-20211120142240125

//ADC初始化
void ADC_Init()
{
	P1M1 |= 0x0f;
	P1M0 &= ~0x0f;//P1.0脚ADC0
	P1ASF |= 0x0f;
//	P1M1 |= 0x02;
// 	P1M0 &= ~0x02;//P1.1脚ADC1
//	P1ASF |= 0x02;
	CLK_DIV |= 0x20;
	ADC_RES = 0;
	ADC_RESL = 0;
}

ADC_CONTR = 0x88;

image-20211004092121135

ADC读数据底层驱动

image-20211120154544982

//ADC读数据底层驱动
void ADC_Read_Data_Drive()
{
	//转换之前先把转换结果寄存器清零
	ADC_RES = 0;
	ADC_RESL = 0;
	//启动转换
	ADC_CONTR = 0x88;//转换速度我用最慢的
	//等到ADC_FLAG为1
	while(!(ADC_CONTR&0x10));
	//然后把数据传到缓存变量里面去
	ADC_Read_Data = ADC_RES<<8;
	ADC_Read_Data = ADC_Read_Data+ADC_RESL;	
}

演示视频

采集电压

<iframe allowfullscreen="true" data-mediaembed="bilibili" id="57H7gO6M-1637394841799" src="https://player.bilibili.com/player.html?aid=336797960"></iframe>

采集电压

ADC代码

ADC_Drive.c(还有一个我自己写的滤波函数,使得数据稳定)基本这个水平可以拿省二了

#include "all.h"


//有数据那我们就得存
u16 xdata ADC_Read_Data = 0;
u16 xdata ADC_Filter_Data = 0;

//ADC初始化
void ADC_Init()
{
	P1M1 |= 0x0f;
	P1M0 &= ~0x0f;//P1.0脚ADC0
	P1ASF |= 0x0f;
//	P1M1 |= 0x02;
// 	P1M0 &= ~0x02;//P1.1脚ADC1
//	P1ASF |= 0x02;
	CLK_DIV |= 0x20;
	ADC_RES = 0;
	ADC_RESL = 0;
}

//ADC读数据底层驱动
void ADC_Read_Data_Drive()
{
	//转换之前先把转换结果寄存器清零
	ADC_RES = 0;
	ADC_RESL = 0;
	//启动转换
	ADC_CONTR = 0x88;//转换速度我用最慢的
	//等到ADC_FLAG为1
	while(!(ADC_CONTR&0x10));
	//然后把数据传到缓存变量里面去
	ADC_Read_Data = ADC_RES<<8;
	ADC_Read_Data = ADC_Read_Data+ADC_RESL;	
}

//全局的ADC滤波数据结构体指针
ADC_Data* adc_filter;

//ADC滤波数据底层驱动
void ADC_Filter_Data_Drive()
{	
	
	/*u16  ADC_Min = 0;
	u16  ADC_Max = 0;
	u16  ADC_Tmp = 0;
	u16  ADC_Result = 0;*/
	
	//设置两个循环变量
	u8 i = 0;
	u8 j = 0;
	ADC_Filter_Data = 0;
	ADC_Read_Data_Drive();
	for(i = 0;i<4;i++)//外层8次循环
	{
		adc_filter->ADC_Result = 0;
		adc_filter->ADC_Min = 
		adc_filter->ADC_Max = 
		ADC_Read_Data;
		for(j = 0;j<4;i++)//内层8次循环
		{
			adc_filter->ADC_Tmp = ADC_Read_Data;
			if (adc_filter->ADC_Tmp < adc_filter->ADC_Min) 
			{
				adc_filter->ADC_Result += adc_filter->ADC_Tmp;
				adc_filter->ADC_Min = adc_filter->ADC_Tmp;
			}
			else if (adc_filter->ADC_Tmp > adc_filter->ADC_Max) 
			{
				adc_filter->ADC_Result += adc_filter->ADC_Tmp;
				adc_filter->ADC_Max = adc_filter->ADC_Tmp;
			}
			else 
			{
				adc_filter->ADC_Result += adc_filter->ADC_Tmp;
			}				
		}
		adc_filter->ADC_Result /= 4;
		ADC_Filter_Data += adc_filter->ADC_Result;
	}
	  ADC_Filter_Data /= 4;
}

ADC_Drive.h

#ifndef ADC_Drive
#define ADC_Drive

typedef struct ADC_Filter_Data
{
	u16  ADC_Min;      //ADC最小值
	u16  ADC_Max;      //ADC最大值
	u16  ADC_Tmp;      //ADC临时值
	u16  ADC_Result;   //ADC结果
} ADC_Data;

//外部声明
extern void ADC_Init();
extern void ADC_Read_Data_Drive();
extern void ADC_Filter_Data_Drive();
extern u16 xdata ADC_Read_Data;
extern u16 xdata ADC_Filter_Data;
#endif

标签:农说,Drive,小码,filter,ADC,u16,Data,adc
来源: https://blog.csdn.net/qq_42832862/article/details/121440695