ADC工作原理:
深化量化误差分析:引入公式Equant=Vref2n+1 E_{\text{quant}} = \frac{V_{\text{ref}}}{2^{n+1}} Equant=2n+1Vref,其中EquantE_{\text{quant}}Equant为量化误差,nnn为分辨率(12位时误差约0.61 mV)。解释如何通过过采样降低噪声。
STC8 ADC硬件特性:
补充多通道切换时序:建议添加时序图描述(例如,通道切换延迟tswitch≈1μst_{\text{switch}} \approx 1 \mu stswitch≈1μs),并讨论外部参考电压源的选择(如使用TL431稳压器提升精度)。
1. ADC初始化函数
/******************* ADc配置函数 *******************/
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
}
2. 获取值
u16 result = Get_ADCResult(chn); // chn: ADC_CH0, ADC_CH1, ADC_CH2 .... ADC_CH15
3. 计算电压
float v = result * 基准电压 / 采样精度;
4. 案例
#include "GPIO.h"
#include "Delay.h"
#include "UART.h" // 串口配置 UART_Configuration
#include "NVIC.h" // 中断初始化NVIC_UART1_Init
#include "Switch.h" // 引脚切换 UART1_SW_P30_P31
#include "ADC.h"
void GPIO_config() {
GPIO_InitTypeDef info;
// ===== UART1 P30 P31 准双向
info.Mode = GPIO_PullUp; // 准双向
info.Pin = GPIO_Pin_0 | GPIO_Pin_1; // 引脚
GPIO_Inilize(GPIO_P3, &info);
// P05 高阻输入
info.Mode = GPIO_HighZ; // 高阻输入
info.Pin = GPIO_Pin_5; // 引脚
GPIO_Inilize(GPIO_P0, &info);
}
// 串口配置函数的定义
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
}
/******************* 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
}
void main() {
u16 adc;
float vol; // 电压
EA = 1; // 使能中断总开关
GPIO_config(); // GPIO配置
UART_config(); // 串口配置
ADC_config(); // ADC配置
while (1){
// 读取ADC采样值,是采样值,不是电压值,但和电压有关系
// 参数不能乱写,原理图 芯片手册 P05 对应的通道是 13 通道
adc = Get_ADCResult(ADC_CH13);
// 转换为电压
vol = adc * 2.5 / 4095;
// 0~2.5v 是准确的, 2.5v~3.3v 代码读到的数据都是2.5v
// 1.65 ~ 2.5v
printf("adc = %d, vol = %.2f\n", (int)adc, vol);
// 处理的太快
delay_ms(250);
delay_ms(250);
}
}
关键寄存器说明:
寄存器 | 功能描述 |
---|---|
ADC_CONTR |
控制寄存器 (通道选择/启动/速度) |
ADC_RES |
ADC结果高8位 |
ADC_RESL |
ADC结果低2位 |
P1M1/P1M0 |
P1口模式配置寄存器 |
使用注意:
- 首次使用需延时30μs等待ADC稳定
- ADC引脚必须配置为高阻输入模式
- 转换时间约tconv=12×分频系数sysclkt_{conv} = \frac{12 \times 分频系数}{sysclk}tconv=sysclk12×分频系数
- STC8A系列有12位ADC,需调整结果组合方式
建议配合STC-ISP工具生成的寄存器配置文件使用,不同子系列需查看对应数据手册调整细节。