一、系统方案
1、本设计采用STM32单片机作为主控器。
2、DS18B20采集温度值送到液晶1602显示。
3、水位传感器采集水位,送到液晶1602显示。
4、按键设置温度和水位上下限,低于下限或高于上限,对应继电器执行操作。
二、硬件设计
原理图如下:
三、单片机软件设计
1、首先是系统初始化
u8 i;
u16 adcx;
u16 adc;
InitGPIO();
LcdInit();
Adc_Init();
LcdWriteCom(0x80); //设置数据指针起点
KEY_Init();
LED_Init();
DHT11_Init();
2、液晶显示程序
/*******************************************************************************
- 函 数 名 : LcdWriteCom
- 函数功能 : 向LCD写入一个字节的命令
- 输 入 : com
- 输 出 : 无
/
void LcdWriteCom(uchar com) //写入命令
{
// LCD1602_E = 0; //使能
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
// LCD1602_RS = 0; //选择发送命令
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
// LCD1602_RW = 0; //选择写入
GPIO_ResetBits(GPIOB,GPIO_Pin_2);
// LCD1602_DATAPINS = com; //放入命令
GPIO_Write(GPIOC,0X00FF&com);
Lcd1602_Delay1ms(1); //等待数据稳定
// LCD1602_E = 1; //写入时序
GPIO_SetBits(GPIOB,GPIO_Pin_3);
Lcd1602_Delay1ms(5); //保持时间
// LCD1602_E = 0;
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
}
/ - 函 数 名 : LcdWriteData
- 函数功能 : 向LCD写入一个字节的数据
- 输 入 : dat
- 输 出 : 无
*******************************************************************************/
void LcdWriteData(uchar dat) //写入数据
{
// LCD1602_E = 0; //使能清零
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
// LCD1602_RS = 1; //选择输入数据
GPIO_SetBits(GPIOB,GPIO_Pin_1);
// LCD1602_RW = 0; //选择写入
GPIO_ResetBits(GPIOB,GPIO_Pin_2);
// LCD1602_DATAPINS = dat; //写入数据
GPIO_Write(GPIOC,0X00FF&dat);
Lcd1602_Delay1ms(1);
// LCD1602_E = 1; //写入时序
GPIO_SetBits(GPIOB,GPIO_Pin_3);
Lcd1602_Delay1ms(5); //保持时间
// LCD1602_E = 0;
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
}
/*******************************************************************************
函 数 名 : LcdInit()
函数功能 : 初始化LCD屏
输 入 : 无
输 出 : 无
*******************************************************************************/
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
// LcdWriteCom(0x80); //设置数据指针起点
}
3、按键程序
void KEY_Scan(void)
{if(KEY40) //读取K1按键状态
{
Delay(10);
if(KEY40)
{
while(KEY4==0);
LcdInit();
mode++;
if(mode>4) mode=0;} } if(KEY5==0) //读取K2按键状态 { Delay(10); if(KEY5==0) { while(KEY5==0); if(mode==1) { wendu++; if(wendu>50) wendu=50; } if(mode==2) { shidu++; if(shidu>50) wendu=50; } if(mode==3) { dy=dy+1; if(dy>100)dy=100; } if(mode==4) { dl=dl+1; if(dl>100)dy=100; } } } if(KEY6==0) //读取K3按键状态 { Delay(10); if(KEY6==0) { while(KEY6==0); if(mode==1) { if(wendu>0) wendu--; } if(mode==2) { if(shidu>0) shidu--; } if(mode==3) { if(dy>0)dy=dy-1; } if(mode==4) { if(dl>0)dl=dl-1; } } }
}
4、核心算法程序
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}
else return 1;
return 0;
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
void DHT11_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
DHT11_Rst(); //复位DHT11
DHT11_Check();//等待DHT11的回应
}
uint8_t DHT_ByteRead(unsigned char dat)
{ unsigned char temp=0;
unsigned char x,y;
unsigned char m=0;
unsigned char n=0;
unsigned char mask=0x01;
unsigned char sum=0;
DHT11_IO_IN() ;
for(y=0;y<5;y++)
{
for(mask=0x80;mask!=0;mask>>=1)
{
while(GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0&&m<200)m++;
delay(30);
if(GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)
temp|=mask;
else
temp&=(~mask);
while(GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)1&&n<200)n++;
}
(dat+y)=temp;
temp=0;
}
for(x=0;x<4;x++)
sum+=(dat+x);
if((sum&=0xff)(dat+4))
return 1;
else
return 0;
}
四、 proteus仿真设计
Proteus软件是一款应用比较广泛的工具,它可以在没有硬件平台的基础上通过自身的软件仿真出硬件平台的运行情况,这样就可以通过软件仿真来验证我们设计的方案有没有问题,如果有问题,可以重新选择器件,连接器件,直到达到我们设定的目的,避免我们搭建实物的时候,如果当初选择的方案有问题,我们器件都已经焊接好了,再去卸载下去,再去焊接新的方案的器件,测试,这样会浪费人力和物力,也给开发者带来一定困惑,Proteus仿真软件就很好的解决这个问题,我们在设计之初,就使用该软件进行模拟仿真,测试,选择满足我们设计的最优方案。最后根据测试没问题的仿真图纸,焊接实物,调试,最终完成本设计的作品。