STC12C5A60S2片內AD程序- /*(1)
- P1_ADC_EN:特殊功能寄存器
- P1.x作為A/D轉換輸入通道來用允許特殊功能寄存器。
- 相應位為“1”時,對應的P1.x口作為A/D轉換使用
- ,內部上拉電阻自動斷開。
- (2)ADC_CONTR:特殊功能寄存器
- CHS2/CHS1/CHS0是模擬輸入通道選擇,
-
- CHS2/CHS1/CHS0的取值如下表所示
- CHS2 CHS1 CHS0 模擬輸入通道選擇
- 0 0 0 選擇P1.0為A/D輸入
- 0 0 1 選擇P1.1為A/D輸入
- 0 1 0 選擇P1.2為A/D輸入
- 0 1 1 選擇P1.3為A/D輸入
- 1 0 0 選擇P1.4為A/D輸入
- 1 0 1 選擇P1.5為A/D輸入
- 1 1 0 選擇P1.6為A/D輸入
- 1 1 1 選擇P1.7為A/D輸入
- ADC_START是模擬/數字轉換(ADC)啟動控制位,設置為1時,開始轉換。
- ADC_FLAG是模擬/數字轉換結束標志位,當A/D轉換完成后,ADC_FLAG=1。
- (3)ADC_DATA:A/D轉換結果特殊功能寄存器
- 模擬/數字轉換結果計算公式為 結果=256×Vin/Vcc
- Vin是模擬輸入通道輸入電壓,Vcc為單片機實際工作電壓,
- 用單片機工作電壓作為模擬參考電壓 */
- //2、STC12C5A60S2內ADC采樣電壓值,
- //先采樣30次然后去掉上下10個再取平均值
- //STC12C5A60S2內ADC采樣
- #include <reg51.h>
- #include<math.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define segp P0 //數據端口
- #define scanp P2 //位端口
- sbit wei=P0^6;
- sbit duan=P0^7;
- sbit fmq =P1^7;
- uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82, 0xf8,0x80,
- 0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //不帶點共陽段驅動信號
- uchar code tab_d[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //帶點共陽段驅動
- uchar code scan[]={0xfe,0xfd,0xfb,0xf7};
- //位掃描驅動信號
- uint display[4]={0,0,0,0}; //初始顯示數字
- uint con=0, _data=0,data2=0; //con顯示循環變量_data為ADC采樣值臨時變量data2顯示數據臨時變量
- //下面五行為ADC定義
- sfr P1ASF=0x9d;
- sfr ADC_CONTR=0xbc;
- sfr ADC_RES=0xbd;
- sfr ADC_RESL=0xbe;
- sfr AUXR1=0xa2;
- /*sfr P1_ADC_EN=0x97;
- sfr ADC_CONTR=0xc5;
- sfr ADC_DATA=0xc6;*/
- void t0_t1_init();//t0顯示掃描定時器和t1串口比特率定時器初始化函數
- void adc_init(); //adc初始化函數
- void uart_out(uchar byte); //串口發送字節函數
- uint average(uint buffer[30]); //采樣數據處理函數
- void AD(); //電壓采樣30次函數
- void delay1ms(uchar x); //延時函數
- void beep()
- {
- fmq=0;
- delay1ms(100);
- fmq=1;
- delay1ms(100);
- }
- void main()
- {
- t0_t1_init();
- adc_init();
- while(1)
- {
- AD();
- if(data2>4700|data2<4000)
- beep(); //報警
- }
- }
- /////////定時器初始化///////
- void t0_t1_init()
- {
- SCON=0x50;
- PCON=0;
- TMOD=0x21;
- TH1=TL1=0xe6;
- TH0=0xf0;
- TL0=0x60;
- EA=ET0=1;
- // ES=1;
- TR1=1;
- TR0=1;
- }
- ////ADC初始化///////
- void adc_init()
- {
- P1ASF=0x01;//啟動P10為ADC模擬輸入口把內部上拉電阻斷開
- P1ASF=0x02; //啟動P11為ADC模擬輸入口把內部上拉電阻斷開
- AUXR1&=0xfb; //adrj_0 高8位在ADC_RES
- ADC_RES=0; //初值
- //開啟ADC電源 并設置轉換周期為540個時鐘周期轉換一次。
- //SPEED_1_1,chs000(選擇AD采樣通道p10)
- //ADC_POWER=1; CHS2,1,0為0,用p1.0作為輸入。SPEED1,0
- ADC_CONTR=0x80;//用p1.0作為輸入
- ADC_CONTR=0x81;//用p1.1作為輸入
- delay1ms(2);
- // IE|=0xa0;
- }
- //////采集30次電壓值//////
- void AD()
- {
- char i; uint temp_buf[30]={0};
- for(i=0;i<30;i++)
- {
- ADC_CONTR |=0x08; //開啟轉換
- while((ADC_CONTR&0x10)==0);
- ADC_CONTR &=0xe7; //清除標志
- temp_buf[i]=ADC_RES; //取出數值到temp_buf
- }
- _data=average(temp_buf); //采樣30次后的數據代入處理函數處理后返回處理后的數值,給下面用串口發送出去
- uart_out(_data);
- }
- ////先對整個數組的三十個值進行從小到大的排列,
- ////// ///再去掉最大5個和最少5個再求平均值;函數返回temp值///
- uint average(uint buffer[30])
- {
- uchar i,j;
- uint temp;
- for(i=1; i<30; i++)
- for(j=29; j>=i; --j)
- {
- if(buffer[j-1] > buffer[j])
- {
- temp = buffer[j-1];
- buffer[j-1] = buffer[j];
- buffer[j] = temp;
- }
- }
- temp = 0;
- for(i=5; i<25; i++)
- {
- temp += buffer[i];
- }
- temp = (uint)(((float)temp) / 20 + 0.5);
- return(temp);
- }
- ///顯示數據處理及掃描顯示中斷服務函數////
- void t0_4ms(void) interrupt 1
- {
- data2=_data;
- data2=_data*19.53;
- display[0]=tab_d[data2/1000]; //用帶小數點的段碼
- display[1]=tab[(data2/100)%10]; //用不帶小數點的段碼
- display[2]=tab[(data2/10)%10];
- display[3]=tab[data2%10];
- TH0=0xf0;
- TL0=0x60;
- if(++con==5) con=1;
- // segp=0xff;
- wei=1;
- P2=scan[con-1];
- wei=0;
- duan=1;
- P2=display[con-1];
- duan=0;
- delay1ms(10) ;
- P2=0xff;
- // segp=display[con-1];
- // scanp=scan[con-1];
- }
- //串口發送節字函數////
- void uart_out(uchar byte)
- {
- SBUF=byte;
- while(TI==0);
- TI=0;
- }
- ///1ms延時////
- void delay1ms(uchar x)
- {
- uchar i,j;
- for(i=0;i<x;i++)
- for(j=0;j<250;j++);
- }
復制代碼 |