标题:
单片机水环境监测系统程序设计 蓝牙控制电机
[打印本页]
作者:
ZHR小白
时间:
2019-5-15 10:49
标题:
单片机水环境监测系统程序设计 蓝牙控制电机
水环境系统的设计,完成了池塘中的循迹以及水环境的监测
单片机源程序如下:
//定义头文件
#include <STC12C5A60S2.H>
#include <math.h> //Keil library
#include <stdio.h>
#include <intrins.h>
//定义引脚、常量和变量
sbit LCD12864_RS = P1^2; //RS控制引脚
sbit LCD12864_RW = P1^1; //RW控制引脚
sbit LCD12864_EN = P1^0; //EN控制引脚
sbit LCD12864_PSB = P1^6; //CS1模式选择引脚,ST7920控制器,1为8位并行接口,0为串行接口
sbit DQ=P1^5; //18B20温度传感器引脚
sbit dianji0=P0^0;
sbit dianji1=P0^1;
sbit dianji2=P0^2;
// PH接 = P1^4;
// LM35接 = P1^3;
#define LCDPORT P2 //数据引脚
unsigned char ucStr1[] = "温度内: 00.00 度"; //显示信息1
unsigned char ucStr2[] = "温度外: 00.00 度"; //显示信息2
unsigned char ucStr3[] = " PH 值: 00.00 "; //显示信息3
unsigned char code ucStr4[] = "鱼塘环境监控系统"; //显示信息4
unsigned char code ucStr5[] = "硬件初始化中...."; //显示信息4
unsigned char code ucStr6[] = " 10 % "; //显示信息4
unsigned char code ucStr7[] = " 20 % "; //显示信息4
unsigned char code ucStr8[] = " 30 % "; //显示信息4
unsigned char code ucStr9[] = " 40 % "; //显示信息4
unsigned char code ucStr10[] = " 50 % "; //显示信息4
unsigned char code ucStr11[] = " 60 % "; //显示信息4
unsigned char code ucStr12[] = " 70 % "; //显示信息4
unsigned char code ucStr13[] = " 80 % "; //显示信息4
unsigned char code ucStr14[] = " 90 % "; //显示信息4
unsigned char code ucStr15[] = "100 % "; //显示信息4
unsigned char code b1[]=" go\n ",b2[]=" left\n ",b3[]=" right\n ";
unsigned int x,y;
unsigned char flag,a;
//需要串口发送到GSM模块的字符串
unsigned char code UartAT8[] = "AT\r\n";
unsigned char code UartAT1[] = "AT+CSTT\r\n";
unsigned char code UartAT2[] = "AT+CIICR\r\n";
unsigned char code UartAT3[] = "AT+CIFSR\r\n";
unsigned char code UartAT4[] = "AT+CIPSTART=\"TCP\",\"123.206.21.219\",8080\r\n";
unsigned char code UartAT5[] = "AT+CIPSEND\r\n";
unsigned char UartAT6[] = "t1=00.00 t2=00.00 PH=00.00<br />";
// 0123456789012345678901234567890
char code UartAT7[] = {0x1A};
unsigned char code UartAT9[] = "\r\n";
/*
任务
需处理计算
1.温度LM35
2.温度18B20
3.PH
需输出显示
1.串口输出
2.12864显示
*/
//AD检测PH和温度1
void delayAD(unsigned int a) //延时约1ms
{
unsigned int i;
while (--a!=0)
for(i=600;i>0;i--); //1T单片机i=600,若是12T单片机i=125
}
void AD_init() //AD初始化
{
P1ASF=0x18; //P1口全部作为模拟功能AD使用
ADC_RES=0; //清零转换结果寄存器高8位
ADC_RESL=0; //清零转换结果寄存器低2位
ADC_CONTR=0x80;//开启AD电源
delayAD(2); //等待1ms,让AD电源稳定
}
unsigned int AD_get(unsigned char channel)
{
ADC_CONTR=0x88|channel; //开启AD转换1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0
_nop_(); _nop_(); _nop_(); _nop_();//要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器
while(!(ADC_CONTR&0x10)); //等待转换完成
ADC_CONTR&=0xe7; //关闭AD转换,ADC_FLAG位由软件清0
return(ADC_RES*4+ADC_RESL); //返回AD转换完成的10位数据(16进制)
}
float AD_work(unsigned char channel)
{
float AD_val; //定义处理后的数值AD_val为浮点数
unsigned char i;
for(i=0;i<250;i++)
AD_val+=AD_get(channel); //转换100次求平均值(提高精度)
AD_val/=250;
AD_val=(AD_val*5)/1024; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值
return AD_val;
}
void chuliLM35wendu(void)
{
float ADLM35 = AD_work(3);
int wenduLM35 = (int)(ADLM35*10000/3);
ucStr1[8] = wenduLM35/1000+0x30;
UartAT6[3] = ucStr1[8];
ucStr1[9] = wenduLM35%1000/100+0x30;
UartAT6[4] = ucStr1[9];
ucStr1[11] = wenduLM35%100/10+0x30;
UartAT6[6] = ucStr1[11];
ucStr1[12] = wenduLM35%10+0x30;
UartAT6[7] = ucStr1[12];
}
void PH(void)
{
float PHAD = AD_work(4);
int PH = (23.34-5.51*PHAD)*100;
ucStr3[8] = PH/1000+0x30;
ucStr3[9] = PH%1000/100+0x30;
ucStr3[11] = PH%100/10+0x30;
ucStr3[12] = PH%10+0x30;
UartAT6[23] = ucStr3[8];
UartAT6[24] = ucStr3[9];
UartAT6[26] = ucStr3[11];
UartAT6[27] = ucStr3[12];
}
//单总线检测18B20
void Delay18B20_us(unsigned int uiUs) //us延时函数
{
for(;uiUs > 0;uiUs--)
{
_nop_();
}
}
void Delay18B20_ms(unsigned int uiMs) //ms延时函数
{
unsigned int i;
for(;uiMs > 0;uiMs--)
{
for(i = 1498;i > 0;i--);
}
}
void DS18B20_Init(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
Delay18B20_us(10);
//Delay(8); //稍做延时,10us
DQ = 0; //单片机将DQ拉低
Delay18B20_us(700);
//Delay(80); //精确延时 大于 480us ,498us
DQ = 1; //拉高总线
Delay18B20_us(60);
//Delay(14); //154us
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
Delay18B20_us(60);
//Delay(20); //212us
}
void DS18B20_WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
Delay18B20_us(4);
DQ = dat&0x01;
Delay18B20_us(59);
//Delay(5); //66us
DQ = 1;
Delay18B20_us(4);
dat>>=1;
}
}
unsigned char DS18B20_ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
Delay18B20_us(4);
dat>>=1;
DQ = 1; // 给脉冲信号
Delay18B20_us(9);
if(DQ)
dat|=0x80;
Delay18B20_us(66);
//Delay(4); //56us
DQ = 1; // 给脉冲信号
Delay18B20_us(4);
}
return(dat);
}
unsigned int DS18B20_ReadTemperature(void) //返回温度值
{
unsigned char tempL=0;
unsigned char tempH=0;
unsigned int sdate;//测量到的温度的整数部分
unsigned char xiaoshu1;//小数第一位
unsigned char xiaoshu2;//小数第二位
unsigned char xiaoshu;//两位小数
bit fg=1; //温度正负标志
unsigned int t=0;
DS18B20_Init();
DS18B20_WriteOneChar(0xCC); // 跳过读序号列号的操作
DS18B20_WriteOneChar(0x44); // 启动温度转换
DS18B20_Init();
DS18B20_WriteOneChar(0xCC); //跳过读序号列号的操作
DS18B20_WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
tempL=DS18B20_ReadOneChar();
tempH=DS18B20_ReadOneChar();
// t=b;
// t<<=8;
// t=t|a;
// //t= t/2; //放大10倍输出并四舍五入---此行没用
// return(t);
if(tempH>0x7f) //最高位为1时温度是负
{
tempL=~tempL; //补码转换,取反加一
tempH=~tempH+1;
fg=0; //读取温度为负时fg=0
}
sdate = tempL/16+tempH*16; //整数部分
xiaoshu1 = (tempL&0x0f)*10/16; //小数第一位
xiaoshu2 = (tempL&0x0f)*100/16%10;//小数第二位
xiaoshu=xiaoshu1*10+xiaoshu2; //小数两位
//if(sdate>9)
ucStr2[8] = sdate/10+0x30;
UartAT6[13] = ucStr2[8];
ucStr2[9] = sdate%10+0x30;
UartAT6[14] = ucStr2[9];
// else
// {
// ucStr2[8] = 0x00;
// ucStr2[9] = sdate+0x30;
// }
ucStr2[11] = xiaoshu1+0x30;
UartAT6[16] = ucStr2[11];
ucStr2[12] = xiaoshu2+0x30;
UartAT6[17] = ucStr2[12];
return 0;
}
//12864显示数据
/******************************************************************************
函数名称:Delay
函数功能:延时函数
入口参数:uiCount-延时参数
返回值:无
备注:无
*******************************************************************************/
void DelayL(unsigned int uiCount)
{
while(uiCount--);
}
/******************************************************************************
函数名称:LCD12864_CheckBusy
函数功能:忙检测
入口参数:无
返回值:无
备注:使用变量i做计时,避免液晶在死循环处停滞。
*******************************************************************************/
void LCD12864_CheckBusy(void)
{
unsigned char i = 250; //局部变量
LCD12864_RS = 0; //拉低
LCD12864_RW = 1; //拉高
LCD12864_EN = 1; //使能
while((i > 0) && (P0 & 0x80))i--; //判断忙标志位
LCD12864_EN = 0; //释放
}
/******************************************************************************
函数名称:LCD12864_WriteInfomation
函数功能:向LCD12864写入命令或者数据
入口参数:ucData-要写入液晶的数据或者命令的内容
bComOrData-命令或者数据的标志位选择,0或者1,其中
1:写入的是数据
0:写入的是命令
返回值:无
备注:无
*******************************************************************************/
void LCD12864_WriteInfomation(unsigned char ucData,bit bComOrData)
{
LCD12864_CheckBusy(); //忙检测
LCD12864_RW = 0; //拉低RW
LCD12864_RS = bComOrData; //根据标志位判断写入的是命令还是数据
DelayL(150); //延时,等待操作
LCDPORT = ucData; //将数据送至数据端口
LCD12864_EN = 1; //使能信号
DelayL(150); //延时
LCD12864_EN = 0; //按照时序来操作
DelayL(150);
}
/******************************************************************************
函数名称:LCD12864_Init
函数功能:LCD12864液晶初始化
入口参数:无
返回值:无
备注:无
*******************************************************************************/
void LCD12864_Init(void)
{
DelayL(400);//延时
LCD12864_PSB = 1; //8位并口工作模式
DelayL(150);//延时
LCD12864_WriteInfomation(0x30,0); //基本指令集
DelayL(150);
LCD12864_WriteInfomation(0x08,0); //显示设置
DelayL(150);
LCD12864_WriteInfomation(0x10,0); //光标设置
DelayL(150);
LCD12864_WriteInfomation(0x0c,0); //游标设置
DelayL(150);
LCD12864_WriteInfomation(0x01,0); //清屏
DelayL(150);
LCD12864_WriteInfomation(0x06,0); //进入点设定
DelayL(150);
}
/******************************************************************************
函数名称:LCD12864_DisplayOneLine
函数功能:显示一行汉字(8个汉字或者16个英文字符)
入口参数:position-要显示的行的首地址,可选值0x80,0x88,0x90,0x98,其中:
0x80:液晶的第一行;
0x88:液晶的第三行;
0x90:液晶的第二行;
0x98:液晶的第四行。
p-要显示的内容的首地址。
返回值:无
备注:无
*******************************************************************************/
void LCD12864_DisplayOneLine(unsigned char position,unsigned char *p)
{
unsigned char i;
LCD12864_WriteInfomation(position,0);//写入要显示文字的行的首地址
DelayL(150);
for(i = 0;i<16;i++) //依次执行写入操作
{
LCD12864_WriteInfomation(*p,1);
p++;
}
}
void Delay10000ms() //@11.0592MHz开机用延时10秒
{
unsigned char i, j, k;
i = 165;
j = 59;
k = 28;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void fangxiang()
{
switch(a)//判断a从串口读取到的数据
{
case 49://如果是0x1f就前进
if(flag==1)
{
ES=0;
flag=0;
for(x=0;b1[x]!='\0';x++)
{
SBUF=b1[x];//28;
while(!TI);
TI=0; }
ES=1;
}
dianji0=0;
a=0;
break;
case 50://如果是0x2f就后退
if(flag==1)
{
ES=0;
flag=0;
for(x=0;b2[x]!='\0';x++)
{
SBUF=b2[x];//28;
while(!TI);
TI=0; }
ES=1;
}
dianji1=0;
a=0;
break;
case 51://如果是0x3f就左转
if(flag==1)
{
ES=0;
flag=0;
for(x=0;b3[x]!='\0';x++)
{
SBUF=b3[x];//28;
while(!TI);
TI=0; }
ES=1;
}
a=0;
dianji2=0;
break;
case 52://如果是0x1f就前进
if(flag==1)
{
ES=0;
flag=0;
for(x=0;b1[x]!='\0';x++)
{
SBUF=b1[x];//28;
while(!TI);
TI=0; }
ES=1;
}
dianji0=1;
dianji1=1;
dianji2=1;
a=0;
break;
}
}
void init()//初始化子程序
{
TMOD=0x20; //设置定时器T1为工作方式2
TH1=0xfd;
TL1=0xfd; //T1定时器装初值
TR1=1; //启动定时器T1
REN=1; //允许串口接收
SM0=0;
SM1=1; //设置串口工作方式1
EA=1; //开总中断
ES=1; //开串口中断
}
//主函数
void main(void)
{ init();
AD_init(); //ADinit
LCD12864_Init(); //初始化液晶
/* LCD12864_DisplayOneLine(0x98,ucStr4); //显示信息4
LCD12864_DisplayOneLine(0x90,ucStr5); //显示信息2
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr6); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr7); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr8); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr9); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr10); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr11); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr12); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr13); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr14); //显示信息3
Delay10000ms();
LCD12864_DisplayOneLine(0x88,ucStr15); //显示信息3
Delay18B20_ms(500);*/
while(1)
{ fangxiang();
chuliLM35wendu(); //LM35xianshi
PH(); //PHADxianshi
DS18B20_ReadTemperature(); //18B20xianshi
LCD12864_DisplayOneLine(0x80,ucStr1); //显示信息1
LCD12864_DisplayOneLine(0x90,ucStr2); //显示信息2
LCD12864_DisplayOneLine(0x88,ucStr3); //显示信息3
Delay18B20_ms(50);
}
}
void chuan() interrupt 4//串口中断服务程序
{
RI=0;//软件清除串口响应
a=SBUF;//读取单片机串口接受的蓝牙模块发送的数据
flag=1;
}
复制代码
所有资料51hei提供下载:
池塘巡检1.2(完成蓝牙控制电机).rar
(59.68 KB, 下载次数: 18)
2019-5-15 10:47 上传
点击文件名下载附件
水环境循迹+监测
下载积分: 黑币 -5
作者:
admin
时间:
2019-5-15 21:15
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1