本帖最后由 dbxzjq 于 2021-8-31 00:14 编辑
#define ADC_POWER 0x80 //ADC电源控制位
#define ADC_FLAG 0x10 //ADC完成标志
#define ADC_START 0x08 //ADC起始控制位
#define ADC_SPEEDLL 0x00 //540个时钟
#define ADC_SPEEDL 0x20 //360个时钟
#define ADC_SPEEDH 0x40 //180个时钟
#define ADC_SPEEDHH 0x60 //90个时钟
/*----------------------------
初始化ADC
----------------------------*/
void InitADC(void)
{
//P1M0 &= ~0x10;
//P1M1 |= 0x10;
P1ASF = 0x07; //设置P1口为AD口
ADC_RES = 0; //清除结果寄存器
ADC_RESL = 0;
CLK_DIV |= 0x20; //ADRJ=1,ADC_RES[1:0]存放高2位ADC结果,ADC_RESL[7:0]存放低8位结果
ADC_CONTR = ADC_POWER | ADC_SPEEDL; //开启ADC电源,配置ADC转换速度为180个时钟
//Delay(2); //ADC上电并延时
}
unsigned int GetADCResult(unsigned char ch)
{
//unsigned int a=0;
ADC_CONTR = ADC_POWER | ADC_SPEEDL | ch | ADC_START;
_nop_(); //等待4个NOP
_nop_();
_nop_();
_nop_();
while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
ADC_CONTR &= ~ADC_FLAG; //Close ADC
//a=ADC_RES;
//a=a<<8|ADC_RESL;
return (unsigned int)ADC_RES<<8|ADC_RESL; //返回ADC结果
}
测量出来的ADC都非常正常的啊!切换通道后必须等待四个空周期才能进行测量,另外这型号对于IO口不用设置为高阻输入的,只管P1ASF设置对应为模拟口即可,不过手册上也说最好把ADC对应的测量IO配置为高阻输入为好楼主的代码:发现合成10位有问题,如下:
AD_Dat = (ADC_RES<<2)|(ADC_RESL&0x03); //高低字节拼接成一个10位数。
修改为AD_Dat =(int)(ADC_RES<<2)|(ADC_RESL&0x03); //高低字节拼接成一个10位数。
这里(int)(ADC_RES<<2)因为左移2位后,超出来寄存器的8位宽度,8位机只能默认R0-R7寄存器组都为8位的,必须得强制转换为16位,
编译器才会把ADC_RES<<2放在两个临时的R0-R7寄存器组里头再进行运算,得到的最终结果才是正确的值
比如ADC_RES=11111111的二进制值,执行ADC_RES<<2后=11111100,但是如果(int)(ADC_RES<<2)就会不一样了,它会换成16位进行运算
得到的会是0000 0011 1111 1100的16位值再位或|(ADC_RESL&0x03)这部分的结果送给予6位变量AD_Dat
|