- 打卡等级:初来乍到
- 打卡总天数:5
- 最近打卡:2024-02-19 12:35:18
新手上路
- 积分
- 35
|
问题现象:
利用15通道测得的基准电压去反推ADC_Vref+管脚的输入电压时是正常的,但是反推其它ADC通道时就不正常了:只要一开ADC15通道转换,其它通道的ADC值都跟ADC15通道一样,不对ADC15通道进行转换时,其它通道是正常的。这是什么原因呢?
硬件连接情况:STC8H1K单片机,ADC_Ref+和VCC接在一起(5V),ADC0用来测量电池电压(3.7V的锂电池电压分压后给到ADC0)。
利用ADC15通道反推ADC_Vref+端口的电压:经计算后为5.056V 【 测得ADC15通道的ADC值为241,读取电压值为1192,从而计算出ADC_Vref+的电压为 5056mV 】
利用ADC15通道测量值,反推ADC0通道电压:测得ADC15通道的ADC值为241,读取电压值为1192,ADC0通道的ADC值在还未运行ADC15转换程序时,是正常的193,一旦经过ADC15转换 ,ADC0就不再正常,变得跟ADC15一样为241。
有一个问题,如果使用ADC15测得的内部基准来反推ADC0通道的输入电压,即便上述测得的ADC0是正常的,那ADC_Vref+管脚的电压有什么作用呢?是不是用不到了?
【在下面代码main程序中可以看到, 第一次正常的ADC0的值为193,而ADC0通道的外部电压Vadc0用万用表实测为952mV,ADC_Vref+的电压是5056mV,Vadc0 = 5056*193/1024 = 943mV,这与952mV接近。】==> 这说明第一次ADC0的值是将ADC_Ref+管脚的5.056V电压作为参考得到的。
代码如下:
//========================================================================
// 函数: 串口1初始化
//========================================================================
void Uart1_Init()
{
P_SW1 = 0x40; // 将串口1配置为P3.6/P3.7端口输出(RXD_2/P3.6, TXD_2/P3.7)
SCON = 0x50; // 将串口1的模式配置为模式1(8位可变波特率),启动串口1接收
TMOD = 0x00; // 配置T1的启动不受外部中断影响、16位自动重装载、作为定时器而非计数器。
TL1 = UART1_BRT;
TH1 = UART1_BRT >> 8;
AUXR = 0x40; // 选择T1作为UART1的波特率发生器(S1ST2置0),给T1的时钟频率选择不分频(即1T模式,设置T1x12为1).
REN = 0; // 关闭串口接收(这里只需要发给PC显示即可,无需接收),这一步也可以在SCON寄存器内设置好。
TR1 = 1; // 启动T1定时器
}
//========================================================================
// 函数: 串口1发送函数
//========================================================================
void Uart1_Send(uchar dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}
//========================================================================
// 函数: GPIO初始化
//========================================================================
void GPIO_INIT()
{
P3M1= 0x00;
P3M0= 0x00;
/*将ADC的IO口配置为高阻模式*/
P1M1|= 0x03; // 将P1.0/P1.1配置为高阻输入模式,P1.0为ADC0,测量电池电压
P1M0&= 0xFC; // 将P1.0/P1.1配置为高阻输入模式,P1.1为ADC1,测量麦克风的输出信号
}
//========================================================================
// 函数: ADC初始化函数
//========================================================================
void ADCInit()
{
P_SW2 |= 0x80; // 使能访问XFR,以便设定相关寄存器
ADCTIM = 0x3F; // 通道选择时间1个时钟,通道保持时间4个时钟,采样时间32个时钟,总共37个时钟
ADCCFG = 0x2F; // 设置ADC转换结果为右对齐,工作频率为:FOSC/2/16,相当于32分频
ADC_RES=0;ADC_RESL=0; // 清除ADC结果寄存器
ADC_CONTR |= ADC_POWER; // 开启ADC电源
delay_ms(20); // 增加延时让ADC稳定.
}
//========================================================================
// 函数: ADC转换函数
//========================================================================
uint ADCRead(uchar ch)
{
uint adc_dat;
ADC_RES = 0;
ADC_RESL = 0; // 将结果寄存器的数据清零
ADC_CONTR |= ADC_START|ch; // 启动ADC转换/设定ADC通道(ch为0时为ADC0--P1.0端口,ch为1时为ADC1--P1.1端口...ch为15时为ADC15,即第15通道)
_nop_();
_nop_();
while (!(ADC_CONTR & ADC_FLAG)); // 查询ADC完成标志
ADC_CONTR &= ~ADC_FLAG; // 转换完成后,清完成标志
adc_dat = (ADC_RES<<8)|ADC_RESL;
return adc_dat;
}
//========================================================================
// 函数: 读取8次ADC数据取平均
//========================================================================
uint AdcDat_Avg8(uchar ch)
{
uint adc_avg8 ;
uint i;
ADCRead(ch);
ADCRead(ch); // 先转换两次,丢掉前两个数据
adc_avg8 = 0;
for (i=0; i<8; i++)
{
adc_avg8 += ADCRead(ch); // 读取8次电池ADC值
}
adc_avg8 >>=3; // 取8次平均值
return adc_avg8;
}
//========================================================================
// 函数: ADC电压读取函数
//========================================================================
uint Read_Adc_Vol()
{
uint ADC_CH0 = 0; // ADC0的ADC值
uint ADC_CH15 = 0; // ADC15的ADC值
uint BAT_V = 0; // 电池电压
ADC_CH0 = AdcDat_Avg8(0);
Uart1_Send(ADC_CH0 >>8 ); // 读取ADC0的值,此处实测:当不转换前面的ADC15通道时,实测为00 C1 即193
Uart1_Send(ADC_CH0);
ADC_CH15 = AdcDat_Avg8(15);
Uart1_Send(ADC_CH15 >>8 ); // 读取内部参考源电压对应ADC值,此处实测为 00 F1 即241,经过此处之后,ADC0就不再为00 C1,而是00 F1
Uart1_Send(ADC_CH15);
return BAT_V;
}
//========================================================================
// main函数
//========================================================================
void main()
{
P_SW2 |= 0x80;
GPIO_INIT(); // 初始化GPIO
Uart1_Init(); // 串口初始化
ADCInit(); // ADC初始化
while(1)
{
Read_Adc_Vol(); // 串口打印信息:00 C1 00 F1 00 F1 00 F1 00 F1 00 F1 ··· ··· 循环 00 F1; ==> 即只有第一次还未转换ADC15时,打印的ADC0是正常的,一旦转换过ADC15,ADC0就不正常了,变得更ADC15一样了,这是什么原因?
delay_ms(3000);
}
}
|
|