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)
|