本帖最后由 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
|