一.了解ADC
1.概念
ADC(Analog-to-Digital Converter)是指集成在微控制器、微处理器或其他数字系统芯片中的模数转换器。ADC用于将模拟信号(如温度、电压、光强等)转换为数字信号,以便数字系统可以对其进行处理,分析,采样等。嵌入式ADC的好处是可以节省空间、降低成本,并且简化系统设计和布局。通常,嵌入式ADC提供不同的输入通道,分辨率和采样速率,并可以通过软件配置来满足具体应用的需求.
模数转换的基本原理是将模拟信号进行采样,并将采样值量化为数字表示。
- 采样:是指在一定时间间隔内对模拟信号进行测量,并将测量值存储在数字形式的数据中
- 量化:是将这些连续的模拟信号值离散化为一系列数字值,通常使用二进制表示。
简单理解,ADC是把模拟信号转换为数字信号的工具,我们可以认为,一个信号有强弱之分,强弱的体现为电压的高低。在数字电路中,只有0和1之分,也就是高电平或低电平。那么体现不了这个强弱。ADC的作用就是体现强弱,精确化的拿到具体的值。
2.应用场景:
-
疗设备:ADC被用于医疗设备中,如心电图仪器、血压计、体温计等,将生理信号(如心电信号、血压信号)转换为数字信号,以便医生进行准确的诊断和监测。
-
音频处理:在音频系统中,ADC用于将模拟音频信号转换为数字形式,如录音设备、数字音频处理器等,以便进行音频处理、存储和传输。
-
仪器仪表:ADC在各种仪器仪表中广泛应用,用于测量和监测各种物理量,如温度、压力、光强等,并将其转换为数字信号进行处理。
-
通信系统:ADC在通信系统中扮演重要角色,将模拟信号(如语音信号、视频信号)转换为数字信号进行传输、编解码和处理,如手机、无线网络、卫星通信等。
-
电力系统:ADC用于测量电压、电流等电力参数,实现对电力系统的监测、保护和控制,保障电力设备的稳定运行。
二.STC8 ADC
1.引脚
STC8H芯片有15个通道的ADC功能引脚
ADC功能 | 引脚 |
ADC0 | P1.0 |
ADC1 | P1.1 |
ADC2 | P5.4 |
ADC3 | P1.3 |
ADC4 | P1.4 |
ADC5 | P1.5 |
ADC6 | P1.6 |
ADC7 | P1.7 |
ADC8 | P0.0 |
ADC9 | P0.1 |
ADC10 | P0.2 |
ADC11 | P0.3 |
ADC12 | P0.4 |
ADC13 | P0.5 |
ADC14 | P0.6 |
2.基准电压
芯片基准电压,参考ADC_VRef+
引脚,此引脚设计如下:
ADC为12位精度的,意思是最大值是2的12次方,值为4096. 表示的是最大测量范围:
- 数值最大为4096
- 测量的电压值不能超过基准电压
- 基准电压对应的值为4096
记住:我们用4096表示基准电压。
3.结论
以上原理图中,基准电压由
VREF
电压决定。这个电路中用到了一个芯片CJ431/CD431
,这是一款电压基准芯片,会恒定的输出2.5V
电压。在我们的设计方案中,理论上可以不使用这个电压基准芯片的,直接连接3V3,但是LDO的输出稳定性不够,因此使用电压基准芯片会更为准确。
由以上我们可以得出:
- 基准电压为:2.5V
- 基准电压对应的数值是4096
- 测量的值为ADC引脚
- 电压值的计算: 电压值 =(测量值*基准电压)/4096
三.代码实现
1.初始化 GPIO UART ADC
GPIO: 控制引脚
ADC:电数模分析
UART:串口输入输出(具体可以看👇篇)
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);//初始化
}
void UART_config(void) {
// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
COMx_InitDefine COMx_InitStructure; //结构定义
COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
COMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200
COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLE
COMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLE
UART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4
NVIC_UART1_Init(ENABLE,Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
UART1_SW(UART1_SW_P30_P31); // 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}
void ADC_config() {
ADC_InitTypeDef init;
init.ADC_SMPduty = 31; //ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)
init.ADC_Speed = ADC_SPEED_2X1T; //设置 ADC 工作时钟频率 ADC_SPEED_2X1T~ADC_SPEED_2X16T
init.ADC_AdjResult = ADC_RIGHT_JUSTIFIED; //ADC结果调整, ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
init.ADC_CsSetup = 0; //ADC 通道选择时间控制 0(默认),1
init.ADC_CsHold = 1; //ADC 通道选择保持时间控制 0,1(默认),2,3
ADC_Inilize(&init);
ADC_PowerControl(ENABLE);
NVIC_ADC_Init(DISABLE, Priority_0);
}
2.数据读取与转换
result = Get_ADCResult(ADC_CH13);
v = result * 2.5 / 4096;
3.主函数
int main() {
u16 adc;
float v;
EA = 1;
// 初始化IO的工作模式
GPIO_config();
UART_config();
// 初始化ADC的工作的参数
ADC_config();
// 开始测量
while(1) {
adc = Get_ADCResult(ADC_CH13);
v = adc * 2.5f / 4095;
printf("adc: %d, v: %.2f\n", adc, v);
delay_ms(250);
delay_ms(250);
delay_ms(250);
delay_ms(250);
}
}