请教:15W408AS的ADC转换后两位为什么始终是0,1,2,3 ?| 已解决
用STC15W408AS的ADC功能,转换出来的前8位是正确的,而后两位出来的数据始终是0,1,2,3这4个数值,不管输入的电阻怎么改变,这后两位始终是出来这4个数值中的一个,3以上的从来不出现,但前8位的转换一直是正确。有朋友知道这是什么原因吗?调试好几天了,一直是这个情况。我都怀疑是这个408AS本身有bug?但仔细想应该不可能,但到底是什么原因呢?知道的朋友指点一下吧,谢谢。//------------------------------------------------------
void InitADC(){
ADC_RES = 0; //清除结果寄存器
//ADC_RESL= 0;//清除结果低两位寄存器
ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
Delay(2); //ADC上电并延时
}
//----------------------------------------------------
WORD GetADCResult(BYTE ch){
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
_nop_(); //等待4个NOP
_nop_();
_nop_();
_nop_();
while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
ADC_CONTR &= ~ADC_FLAG; //Close ADC
// ADC_Result= (ADC_RES<<8|ADC_RESL);
return ADC_RES; //返回ADC结果
//return ADC_Result; //返回ADC结果
}
//-------------------------------------------------------------
SendData(ADC_RES);//STC15前8位结果是正确的
SendData(ADC_RESL);//STC15后两位始终是出来0,1,2,3,这4个数值中的一个
//-------------------------------------------------------------
深圳国芯人工智能有限公司-工具软件 (stcai.com)
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */
/* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序 */
/*---------------------------------------------------------------------*/
//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz
#include "reg51.h"
#include "intrins.h"
#define FOSC 11059200UL
#define BAUD 115200
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define URMD 0 //0:使用定时器2作为波特率发生器
//1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
//2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器
sfr T2H = 0xd6; //定时器2高8位
sfr T2L = 0xd7; //定时器2低8位
sfr P1M1 = 0x91; //PxM1.n,PxM0.n =00--->Standard, 01--->push-pull
sfr P1M0 = 0x92; // =10--->pure input,11--->open drain
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
sfr P4M1 = 0xB3;
sfr P4M0 = 0xB4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;
sfrAUXR = 0x8e; //辅助寄存器
sfr ADC_CONTR = 0xBC; //ADC控制寄存器
sfr ADC_RES = 0xBD; //ADC高8位结果
sfr ADC_LOW2 = 0xBE; //ADC低2位结果
sfr P1ASF = 0x9D; //P1口第2功能控制寄存器
#define ADC_POWER 0x80 //ADC电源控制位
#define ADC_FLAG 0x10 //ADC完成标志
#define ADC_START 0x08 //ADC起始控制位
#define ADC_SPEEDLL 0x00 //540个时钟
#define ADC_SPEEDL0x20 //360个时钟
#define ADC_SPEEDH0x40 //180个时钟
#define ADC_SPEEDHH 0x60 //90个时钟
void InitUart();
void SendData(BYTE dat);
void Delay(WORD n);
void InitADC();
BYTE ch = 0; //ADC通道号
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
InitUart(); //初始化串口
InitADC(); //初始化ADC
IE = 0xa0; //使能ADC中断
//开始AD转换
while (1);
}
/*----------------------------
ADC中断服务程序
----------------------------*/
void adc_isr() interrupt 5
{
ADC_CONTR &= !ADC_FLAG; //清除ADC中断标志
SendData(ch); //显示通道号
SendData(ADC_RES); //读取高8位结果并发送到串口
// SendData(ADC_LOW2); //显示低2位结果
if (++ch > 7) ch = 0; //切换到下一个通道
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
}
/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
P1ASF = 0xff; //设置P1口为AD口
ADC_RES = 0; //清除结果寄存器
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
Delay(2); //ADC上电并延时
}
/*----------------------------
初始化串口
----------------------------*/
void InitUart()
{
SCON = 0x5a; //设置串口为8位可变波特率
#if URMD == 0
T2L = (65536 - (FOSC/4/BAUD));
T2H = (65536 - (FOSC/4/BAUD)) >> 8;
AUXR = 0x14; //T2为1T模式, 并启动定时器2
AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
#elif URMD == 1
AUXR = 0x40; //定时器1为1T模式
TMOD = 0x00; //定时器1为模式0(16位自动重载)
TL1 = (65536 - (FOSC/4/BAUD));
TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
TR1 = 1; //定时器1开始启动
#else
TMOD = 0x20; //设置定时器1为8位自动重装载模式
AUXR = 0x40; //定时器1为1T模式
TH1 = TL1 = (256 - (FOSC/32/BAUD));
TR1 = 1;
#endif
}
/*----------------------------
发送串口数据
----------------------------*/
void SendData(BYTE dat)
{
while (!TI); //等待前一个数据发送完成
TI = 0; //清除发送标志
SBUF = dat; //发送当前数据
}
/*----------------------------
软件延时
----------------------------*/
void Delay(WORD n)
{
WORD x;
while (n--)
{
x = 5000;
while (x--);
}
}
本帖最后由 fsy 于 2024-3-9 15:33 编辑
神农鼎 发表于 2024-3-9 15:20
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */
/* 如果要在文章中应用此代 ...
谢谢回复。又看了一下手册,好像后两位只能出现0,1,2,3,如果要得到10位的转换结果的话,应该根据公式重新计算。我再仔细看一下,公式应该怎么用程序来实现。朋友能帮我看一下,程序应该怎么写吗?最后得出一个10位的转换值。谢谢。(哎,看来还是得仔细的看手册。) fsy 发表于 2024-3-9 15:32
谢谢回复。又看了一下手册,好像后两位只能出现0,1,2,3,如果要得到10位的转换结果的话,应该根据公式重新 ...
10位ADC是分两个寄存器存放,左对齐就是8位+2位,低字节就是2位,取值0、1、2、3,就是你说的结果。
值需要将两个结果拼在一起即可啊。。。
u16adc;
adc = ((u16)ADC_RES <<2) + (ADC_RESL & 0x03);
谢谢版主,搞清楚了。就是浮噪没有仔细看手册。谢谢。 再告诉楼主一下,高8位+低2位设计还有个好处就是,为了去除抖动,得到一个”稳定“的ADC值,在精度要求不高的情况下(比如检测系统电池电压),可以只用高8位;精度要求较高时可以多次转换求平均值;精度要求再高就得上专用的ADC芯片了。 21cnsound 发表于 2024-3-9 19:46
再告诉楼主一下,高8位+低2位设计还有个好处就是,为了去除抖动,得到一个”稳定“的ADC值,在精度要求不高 ...
谢谢,迟到的谢谢。(好久没到这里来了)
页:
[1]