17年電賽P題
單片機源程序如下:
- #include <STC15F2K60S2.H>// 包含STC115F2K60S2單片機寄存器定義文件
- #define VCC 5.0 // 存放用萬用表實測的單片機供電電壓
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- unsigned int ADvalue; // 存放AD轉換返回的結果
- sbit ADC_SCK=P2^6 ;//ADC時鐘
- sbit ADC_DIN= P2^7;//ADC數據入
- sbit ADC_DOUT=P2^4; //ADC數據出
- sbit ADC_DBY=P2^5;//ADC準備
- unsigned int channal1;
- sbit RS=P0^0; //片選信號 rs CS
- sbit RW=P0^1; //數據信號 rw SID
- sbit E=P0^2; //時鐘信號 e SCLK
- sbit RST=P0^6; //復位信號
- sbit PSB = P0^7; //并行、串行選擇信號 psb CH
- sbit c_send = P3^3; //超聲波發射 t
- sbit c_recive = P3^2; //超聲波接收 e
- uchar flag_hc_value; //超聲波中間變量
- long distance; //距離
- uint set_d; //距離
- bit flag_csb_juli; //超聲波超出量程
- uint flag_time0; //用來保存定時器0的時候的
- uint time;
- /********************************************************************
- * 名稱 : delay()
- * 功能 : 延時,延時時間為 100us * t。這是通過軟件延時,有一定誤差。
- * 輸入 : t
- * 輸出 : 無
- ***********************************************************************/
- void delay(unsigned int t)
- {
- unsigned int i,j;
- for(i=0; i<t; i++)
- for(j=0; j<10; j++);
- }
- void Delay_ms(unsigned int n)
- {
- unsigned int i,j;
- for(i=0;i<n;i++)
- for(j=0;j<123;j++);
- }
- void UART_init(void)
- {
- //下面代碼設置定時器1
- TMOD = 0x20; // 0010 0000 定時器1工作于方式2(8位自動重裝方式)
- TH1 = 0xFD; // 波特率:9600 /11.0592MHZ
- TL1 = 0xFD; // 波特率:9600 /11.0592MHZ
- TR1 = 1;
- //下面代碼設置定串口
- AUXR = 0x00; // 很關鍵,使用定時器1作為波特率發生器,S1ST2=0
- SCON = 0x50; // 0101 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允許接受)
- TI=1; // 很關鍵,使用printf函數時必須有此命令
- }
- /********************************************************************
- * 名稱 : sendbyte()
- * 功能 : 按照液晶的串口通信協議,發送數據
- * 輸入 : zdata
- * 輸出 : 無
- ***********************************************************************/
- void sendbyte(unsigned char zdata)
- {
- unsigned int i;
- for(i=0; i<8; i++)
- {
- if((zdata << i) & 0x80)
- {
- RW = 1;
- }
- else
- {
- RW = 0;
- }
- E = 0;
- E = 1;
- }
- }
- /********************************************************************
- * 名稱 : write_com()
- * 功能 : 寫串口指令
- * 輸入 : cmdcode
- * 輸出 : 無
- ***********************************************************************/
- void write_com(unsigned char cmdcode)
- {
- RS = 1;
- sendbyte(0xf8);
- sendbyte(cmdcode & 0xf0);
- sendbyte((cmdcode << 4) & 0xf0);
- delay(2);
- }
- /********************************************************************
- * 名稱 : write_data()
- * 功能 : 寫串口指令
- * 輸入 : cmdcode
- * 輸出 : 無
- ***********************************************************************/
- void write_data(unsigned char Dispdata)
- {
- RS = 1;
- sendbyte(0xfa);
- sendbyte(Dispdata & 0xf0);
- sendbyte((Dispdata << 4) & 0xf0);
- delay(2);
- }
- /********************************************************************
- * 名稱 : lcdinit()
- * 功能 : 初始化函數
- * 輸入 : cmdcode
- * 輸出 : 無
- ***********************************************************************/
- void lcdinit()
- {
- PSB = 0;
- delay(1);
- RST = 0;
- delay(100);
- RST = 1;
- delay(20000);
- write_com(0x30);
- delay(50);
- write_com(0x0c);
- delay(50);
- }
- /********************************************************************
- * 名稱 : hzkdis()
- * 功能 : 顯示字符串
- * 輸入 : *s
- * 輸出 : 無
- ***********************************************************************/
- void hzkdis(unsigned char code *s)
- {
- while(*s > 0)
- {
- write_data(*s);
- s++;
- delay(50);
- }
- }
- void time_init()
- {
- EA = 1; //開總中斷
- TMOD = 0X01; //定時器0、定時器1工作方式1
- ET0 = 1; //開定時器0中斷
- TR0 = 1; //允許定時器0定時
- }
- void send_wave()
- {
- c_send=1; //啟動一次檢測模塊
- delay(20);
- c_send=0; //停止向檢測模塊Trig端發送高電平
- while(!c_recive); //無回波時等待
- TR0=1; //計時開始
- while(c_recive); //有回波是計數并繼續等待
- TR0=0;
- time=TH0*256+TL0;
- TH0=0;
- TL0=0;
- distance=269.05-time*0.191;// 計算距離,算出來的單位是mm
- if(distance<=0)
- distance=0;
- if(distance>=269.05)
- distance=269.05;
-
- }
- void ADC_P11_init()
- {
- unsigned int i; // 用于軟件延時程序
- ADC_CONTR|=0x80; // 開AD轉換電源,第一次使用時要打開內部模擬電源
- for (i=0;i<10000;i++); // 適當延時等待AD轉換供電穩定,一般延時1ms以內即可,為了縮短AD
- // 調用時間,可把這2行剪切到主程序中去。
- P1ASF|=0x02; // 選擇P1.1作為AD轉換通道,0x02= 0000 0010
- ADC_CONTR=0xE1; // 選擇P1.1作為AD轉換通道,最高轉換速度,清轉換完成標志。
- for (i=0;i<200;i++); // 如果是多通道模擬量進行AD轉換,則更換AD轉換通道后要適當延時,
- // 使輸入電壓穩定,延時量取20μs~200μs即可,與輸入電壓源的內阻有關,如果輸入電壓信號源的內
- // 阻在10K以下,可不加延時,如果是單通道模擬量轉換,則不需要更換AD轉換通道,也不需要加延時。
- ADC_CONTR|=0x08; // 啟動 A/D 轉換,ADC_START=1。
- EADC=1;
- EA=1;
- }
- void ADC(void) interrupt 5
- {
- unsigned int AD_Dat=0,AD_Dat1=0; // 10位AD轉換值
- unsigned char Tmp=0,Tmp1=0; // 臨時變量用于將AD轉換出來的2個字節合成一個字節
- ADC_CONTR&=0xE7; // 將ADC_FLAG清0, 0xE7=1110 0111B,ADC_FLAG=0,ADC_START=0。
- AD_Dat = ADC_RES; // 默認高字節高8位。
- AD_Dat <<= 2;
- Tmp = ADC_RESL; // 默認低字節低2位。
- Tmp &= 0x03; // 屏蔽無關位
- AD_Dat|= Tmp; // 高低字節拼接成一個10位數。
- ADvalue=AD_Dat;
- ADC_CONTR|=0x08; // 重新啟動 A/D 轉換,ADC_START=1。
- }
- /******向AD7705寫入一個字節******/
- void WriteByte7705(unsigned char dat)
- {
- unsigned char i;
- for (i=0; i<8; i++)
- {
- ADC_SCK=0;
- _nop_();
- _nop_();
- _nop_();
- if(dat & 0x80){ADC_DIN=1;}
- else
- ADC_DIN=0;
- _nop_();
- _nop_();
- _nop_();
- ADC_SCK=1;
- _nop_();
- _nop_();
- _nop_();
- dat=dat<<1;
- }
- }
- /****** 從AD7705讀一個字節 ******/
- unsigned long ReadWord7705()
- {
- unsigned long read_dat=0;
- unsigned char i;
- for(i=0;i<16;i++)
- {
- read_dat=read_dat<<1;
- ADC_SCK=0;
- _nop_();
- _nop_();
- _nop_();
- if(ADC_DOUT == 1)
- {read_dat++; }
- _nop_();
- _nop_();
- _nop_();
- ADC_SCK=1;
- _nop_();
- _nop_();
- _nop_();
- }
- return read_dat;
- }
- /******ad7705通信端口復位******/
- void reset7705()
- {
- unsigned char i;
- ADC_DIN=1;
- for(i=0;i<36;i++)
- {
- ADC_SCK=0;
- _nop_();
- _nop_();
- _nop_();
- ADC_SCK=1;
- _nop_();
- _nop_();
- _nop_();
- }
- }
- /******AD7705通道1初始化******/
- void ad7705_init1()
- {
- reset7705();
- WriteByte7705(0x20);//寫通信寄存器,選擇通道1,將下一次操作設為寫時鐘寄存器
- WriteByte7705(0x01);//寫時鐘寄存器,不分頻,更新頻率25Hz
- WriteByte7705(0x10);//寫通信寄存器,選擇通道1
- WriteByte7705(0x44);//寫設置寄存器4,單極性,非緩沖模式,清除濾波器同步,啟動對1通道的自校準
- }
- /******讀取AD7705通道1轉換數據函數******/
- unsigned int ReadData1_7705()
- {
- unsigned int value;
- ad7705_init1();
- reset7705();
- while(ADC_DBY); //等待轉換結束
- WriteByte7705(0x38); //寫通信寄存器,下一次操作為讀數據寄存器
- value=5000*ReadWord7705()/65535;
- return value;
- }
- void main(void)
- {
- float Vin,N,U; // 存放計算出來的外部輸入電壓
- uint PH;
- ADC_P11_init();
- UART_init(); // 串口初始化9600/11.0592MHz
- time_init();
- send_wave();
- lcdinit();
- delay(10);
- write_com(0x03);
- while(1)
- {
-
- channal1=ReadData1_7705(); //測電池電壓
- channal1=channal1*1.618;
- delay(50);
- send_wave(); //測距
- delay(50);
- Vin=VCC*ADvalue/1023; // 注意是1023才正確
- U=Vin*1010.33;
- N=(4418.5-U)/177.28;
- PH=N*100; //測PH值
- write_com(0x81);
- hzkdis("水情檢測系統");
- write_com(0x90);
- hzkdis("液位高度: ");
- write_data(distance%1000/100 + 0x30);
- write_data(distance%100/10 + 0x30);
- write_data(distance%10 + 0x30);
- hzkdis("mm");
- write_com(0x88);
- hzkdis("當前PH值: ");
- write_data(PH%10000/1000 + 0x30);
- write_data(PH%1000/100 + 0x30);
- hzkdis(".") ;
- write_data(PH%100/10 + 0x30);
- write_com(0x98);
- hzkdis("電池電壓: ");
- write_data(channal1%10000/1000 + 0x30);
- hzkdis(".");
- write_data(channal1%1000/100 + 0x30);
- write_data(channal1%100/10 + 0x30);
- hzkdis("V");
- Delay_ms(10);
- }
- }
復制代碼
所有資料51hei提供下載:
17年電賽簡易水情檢測系統代碼.zip
(45.21 KB, 下載次數: 40)
2019-3-30 13:58 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|