嵌入式学习-STC-ADC(模数转换器)

本文详细介绍了ADC(模数转换器)的工作原理,包括采样和量化过程,并展示了在医疗设备、音频信号处理和电力系统中的应用场景。特别关注了4096作为基准电压的含义以及如何通过ADC读取并转换模拟信号,以NTC热敏电阻为例,演示了整个数据获取和温度计算的过程。
摘要由CSDN通过智能技术生成

记录每次学习的过程,总结学习的内容,希望能给到自己和别人帮助。

嵌入式学习-STC-ADC(模数转换器)

ADC

(Analog to Digital Converter 模数转换器)是一种将模拟信号转换为数字信号的电路。在电子系统中,模拟信号常常需要转换为数字信号进行处理和存储。模数转换的基本原理是将模拟信号进行采样,并将采样值量化为数字表示。
采样:是指在一定时间间隔内对模拟信号进行测量,并将测量值存储在数字形式的数据中
量化:是将这些连续的模拟信号值离散化为一系列数字值,通常使用二进制表示。
简单理解,ADC是把模拟信号转换为数字信号的工具,我们可以认为,一个信号有强弱之分,强弱的体现为电压的高低。在数字电路中,只有0和1之分,也就是高电平或低电平。那么体现不了这个强弱。ADC的作用就是体现强弱,精确化的拿到具体的值。
在这里插入图片描述
● 模拟信号:信号有强弱之分,强弱的体现为电压的高低
● 数字电路:只有0和1之分,也就是高电平或低电平
应用场景:

  1. 医疗设备:如心电图、血压计之类。
  2. 音频信号处理:在数字音频处理中,ADC将模拟音频信号转换为数字信号,然后可以进行数字信号处理和存储。
  3. 电力系统:测量电压。
    总之,需要知道信号强弱的,需要将模拟信号转为数字信号的都会用到ADC。
    主要功能:采集和量化
    io设置模式:为了能准确采集,初始化为高阻输入

用4096表示基准电压

2.5 1.25


4096 2048

ADC为12位精度的,意思是最大值是2的12次方,值为4096.
ADC的这个最大值,表示的是最大测量范围:

  1. 数值最大为4096
  2. 测量的电压值不能超过基准电压
  3. 基准电压对应的值为4096
    记住:我们用4096表示基准电压。
    例如采集到4096的时候,证明是最大电压,这时候会是2.5伏。例如采集到2048的时候,证明当时的电压是1.25伏。

以上原理图中,基准电压由 VREF电压决定。这个电路中用到了一个芯片CJ431/CD431,这是一款电压基准芯片,会恒定的输出2.5V电压。
在我们的设计方案中,理论上可以不使用这个电压基准芯片的,直接连接3V3,但是LDO的输出稳定性不够,因此使用电压基准芯片会更为准确。

由以上我们可以得出:

  1. 基准电压为:2.5V
  2. 基准电压对应的数值是4096
  3. 测量的值为ADC引脚
  4. 电压值的计算:
    在这里插入图片描述

反向得到电源输入电压

  1. 将ADC_Vref+引脚接到VCC管脚
  2. MCU_Vcc = 4096 * 1.19V / 12位ADC转换结果(CH15)

计算公式:
在这里插入图片描述

ADC功能引脚

STC8H芯片有15个通道的ADC功能引脚:
在这里插入图片描述

代码流程:

配置IO工作模式
配置ADC ADC_Config();
用 函数来读取采样值

IO初始化为高阻输入

void GPIO_config(void) {
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    GPIO_InitStructure.Pin  = GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_HighZ;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P0, &GPIO_InitStructure);//初始化
}

ADC配置逻辑

一般内容不用修改

/******************* AD配置函数 *******************/
void	ADC_config(void)
{
	ADC_InitTypeDef		ADC_InitStructure;		//结构定义

	ADC_InitStructure.ADC_SMPduty   = 31;		//ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)
	ADC_InitStructure.ADC_CsSetup   = 0;		//ADC 通道选择时间控制 0(默认),1
	ADC_InitStructure.ADC_CsHold    = 1;		//ADC 通道选择保持时间控制 0,1(默认),2,3
	ADC_InitStructure.ADC_Speed     = ADC_SPEED_2X1T;		//设置 ADC 工作时钟频率	ADC_SPEED_2X1T~ADC_SPEED_2X16T
	ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED;	//ADC结果调整,	ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
	ADC_Inilize(&ADC_InitStructure);		//初始化
	ADC_PowerControl(ENABLE);				//ADC电源开关, ENABLE或DISABLE
	NVIC_ADC_Init(DISABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}

数据读取与转换

result = Get_ADCResult(ADC_CH13);
v = result * 2.5 / 4096;

功能举例:

获取热敏电阻NTC数值

热敏电阻的特性:温度上升,电阻减少
NTC(Negative Temperature Coefficient)是指随温度上升电阻减小、具有负温度系数的热敏电阻现象和材料。
得到电阻,反推温度。
想得到电阻,要得到电压。

在这里插入图片描述

阻温特性表

表值过多,有兴趣的可以去浏览 相关所购买的热敏电阻的数据手册,我这里只截取部分作为例子
在这里插入图片描述
在这里插入图片描述

代码封装(转换成温度输出)

NTC.h

创建NTC.h,写入如下内容

#ifndef __NTC_H__
#define __NTC_H__

// 初始化NTC
void NTC_Initialize();

// 获取温度值
int NTC_get_temperature();

#endif

NTC.c

创建一个NTC.c文件,写入如下内容,请自行将temp_table拷贝进来(因为temp_table较长,我会放在最后面,有需要的话再复制进来这个.c文件中)

#include "NTC.h"
#include "GPIO.h"
#include "ADC.h"
#include "NVIC.h"
#include <stdio.h>

//1.初始化数组------------------------------------------------------------------
// static标志此函数,只能在本文件使用,避免冲突
// code 关键字作用 定义的数据要放在ROM(程序代码存储区)里面,写入后不能再更改
static u16 code temp_table[] = {
	58354, // -55
    55464, // -54
    .....//剩余的不复制,需要复制就到数组定义中复制
}




//2.初始化配置------------------------------------------------------------------

//GPIO配置
static void GPIO_config(void) {
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义

    // P04 高阻输入 为保证数据精确   热敏电阻用的是P04引脚
    GPIO_InitStructure.Pin  = GPIO_Pin_4;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_HighZ;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P0, &GPIO_InitStructure);//初始化
}

/******************* AD配置函数 *******************/
static void	ADC_config(void)
{
    ADC_InitTypeDef		ADC_InitStructure;		//结构定义

    ADC_InitStructure.ADC_SMPduty   = 31;		//ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)
    ADC_InitStructure.ADC_CsSetup   = 0;		//ADC 通道选择时间控制 0(默认),1
    ADC_InitStructure.ADC_CsHold    = 1;		//ADC 通道选择保持时间控制 0,1(默认),2,3
    ADC_InitStructure.ADC_Speed     = ADC_SPEED_2X1T;		//设置 ADC 工作时钟频率	ADC_SPEED_2X1T~ADC_SPEED_2X16T
    ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED;	//ADC结果调整,	ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
    ADC_Inilize(&ADC_InitStructure);		//初始化
    ADC_PowerControl(ENABLE);				//ADC电源开关, ENABLE或DISABLE
    NVIC_ADC_Init(DISABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}

//内部方法------------------------------------------------------------------
//3.找下标,最接近的值
static int get_pos(float re) {
		//定义入参和第一个电阻值的差值为diff 
    float diff = abs(re - temp_table[0]);
    float temp;
	//获取数组长度
    int n = sizeof(temp_table)/sizeof(temp_table[0]);
    int i, min_idx = 0;
//因为已经将第0个电阻值拿出来比较了,所以从1开始
    for(i = 1; i < n; i++) {
        temp = abs(re - temp_table[i]);
        if (diff > temp) {
            diff = temp;
					//如果有更小的差值,在获取了值之后,还要将这个值的下标记住
            min_idx = i;
        }
    }
    return min_idx;
}




//提供给外部的方法------------------------------------------------------------------


// 初始化
void NTC_Initialize() {
    GPIO_config();
    ADC_config();
}

// 获取温度值
int NTC_get_temperature() {
    u16		adc_value;
    float vol,re;
    int temperature;

// ADC_CH12 ===> P04 根据15个通道的ADC功能引脚查询 我们使用的是P04脚 所以用的是ADC12
    adc_value = Get_ADCResult(ADC_CH12);
    //拿到采样值之后,代入公式即可算出电压值
    vol = adc_value * 2.5 / 4096;
    //拿到电压之后,代入公式即可算出电阻值
    re =  vol * 10 / (3.3 - vol);
    //拿到电阻之后,调用函数即可算出温度  因为温度的下标与实际温度之间相差55,所以需要减去55
    temperature = get_pos(re*100)-55;

    return temperature;
}

main函数使用


int temperature;
NTC_Initialize(); //调用自写的初始化方法

temperature=NTC_get_temperature();  //调用自写的温度函数
printf("温度temperature:%d \n", (int)temperature);

数组定义

采用表的方式来记录 电阻值和温度的关系。
其中,表中记录的是阻值,下标记录的是温度。可以通过阻值比对,查询出下标,下标就是对应的温度。
● 元素是阻值,注释是温度
● code 关键字作用
○ 定义的数据要放在ROM(程序代码存储区)里面,写入后不能再更改
● code关键字: 放到一个代码存储区 ,换一个地方存放的意思
这个就是 NTC.c里面的temp_table,需要用到时候将这一段复制到 NTC.c中去

u16 code temp_table[]= {
	58354, // -55
	55464, // -54
	52698, // -53
	50048, // -52
	47515, // -51
	45097, // -50
	42789, // -49
	40589, // -48
	38492, // -47
	36496, // -46
	34597, // -45
	32791, // -44
	31075, // -43
	29444, // -42
	27896, // -41
	26427, // -40
	25034, // -39
	23713, // -38
	22460, // -37
	21273, // -36
	20148, // -35
	19083, // -34
	18075, // -33
	17120, // -32
	16216, // -31
	15361, // -30
	14551, // -29
	13785, // -28
	13061, // -27
	12376, // -26
	11728, // -25
	11114, // -24
	10535, // -23
	9986,  // -22
	9468,  // -21
	8977,  // -20
	8513,  // -19
	8075,  // -18
	7660,  // -17
	7267,  // -16
	6896,  // -15
	6545,  // -14
	6212,  // -13
	5898,  // -12
	5601,  // -11
	5319,  // -10
	5053,  // -9
	4801,  // -8
	4562,  // -7
	4336,  // -6
	4122,  // -5
	3920,  // -4
	3728,  // -3
	3546,  // -2
	3374,  // -1
	3211,  // 0
	3057,  // 1
	2910,  // 2
	2771,  // 3
	2639,  // 4
	2515,  // 5
	2396,  // 6
	2284,  // 7
	2177,  // 8
	2076,  // 9
	1978,  // 10
	1889,  // 11
	1802,  // 12
	1720,  // 13
	1642,  // 14
	1568,  // 15
	1497,  // 16
	1430,  // 17
	1366,  // 18
	1306,  // 19
	1248,  // 20
	1193,  // 21
	1141,  // 22
	1092,  // 23
	1044,  // 24
	1000,  // 25
	957,   // 26
	916,   // 27
	877,   // 28
	840,   // 29
	805,   // 30
	771,   // 31
	739,   // 32
	709,   // 33
	679,   // 34
	652,   // 35
	625,   // 36
	600,   // 37
	576,   // 38
	552,   // 39
	530,   // 40
	509,   // 41
	489,   // 42
	470,   // 43
	452,   // 44
	434,   // 45
	417,   // 46
	401,   // 47
	386,   // 48
	371,   // 49
	358,   // 50
	344,   // 51
	331,   // 52
	318,   // 53
	306,   // 54
	295,   // 55
	284,   // 56
	274,   // 57
	264,   // 58
	254,   // 59
	245,   // 60
	236,   // 61
	228,   // 62
	220,   // 63
	212,   // 64
	205,   // 65
	198,   // 66
	191,   // 67
	184,   // 68
	178,   // 69
	172,   // 70
	166,   // 71
	160,   // 72
	155,   // 73
	150,   // 74
	145,   // 75
	140,   // 76
	135,   // 77
	131,   // 78
	126,   // 79
	122,   // 80
	118,   // 81
	115,   // 82
	111,   // 83
	107,   // 84
	104,   // 85
	101,   // 86
	97,    // 87
	94,    // 88
	91,    // 89
	89,    // 90
	86,    // 91
	83,    // 92
	81,    // 93
	78,    // 94
	76,    // 95
	74,    // 96
	71,    // 97
	69,    // 98
	67,    // 99
	65,    // 100
	63,    // 101
	61,    // 102
	60,    // 103
	58,    // 104
	56,    // 105
	55,    // 106
	53,    // 107
	52,    // 108
	50,    // 109
	49,    // 110
	47,    // 111
	46,    // 112
	45,    // 113
	43,    // 114
	42,    // 115
	41,    // 116
	40,    // 117
	39,    // 118
	38,    // 119
	37,    // 120
	36,    // 121
	35,    // 122
	34,    // 123
	33,    // 124
	32,    // 125
};
  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值