标题:
17年电赛简易水情检测系统单片机代码
[打印本页]
作者:
1824380946
时间:
2019-3-30 13:58
标题:
17年电赛简易水情检测系统单片机代码
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
作者:
admin
时间:
2019-3-31 02:10
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
作者:
zhongzl728
时间:
2019-7-18 10:30
感谢分享学习了
作者:
MC_城洛
时间:
2019-7-20 11:01
ph传感器用的是什么型号的
作者:
何甘酸
时间:
2019-8-1 15:52
xxxxxxxxxxxxxxxxxx
datasheet.pdf
2019-8-1 15:52 上传
点击文件名下载附件
下载积分: 黑币 -5
1.06 MB, 下载次数: 10, 下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1