这个课设可以说写了四天,因为我接触单片机的时间也不是很长,基础也不是太扎实。写的代码bug真的是太多,绝大多数的时间都画在了找bug上了。但是幸运的是我有一个能够为我传道,授业,解惑的好老师,没有老师的帮忙,这个代码估计到现在也写不好。在实习的过程中也看到了很多厉害的同学,写代码思路很清晰,对于模块的理解也很透彻,写的也很快。我也是比较嫉妒的,希望有一天我的单片机也能学的很透彻。以后我一定要加强对于单片机方面的学习,我还想靠着单片机在一些比赛上拿一些奖项呢。
main函数
#include "1602.h"
#include "DHT11.h"
#include "juzhen.h"
void Selay(unsigned char k);
unsigned char TTop=30;
unsigned char TLow=10;
unsigned char RHTop=80;
unsigned char RHLow=30;
extern T_Data_H;
volatile unsigned char KeyValue=0;
unsigned char Temp=0;
extern unsigned char DHT11_Data[17];
unsigned char *DHT11_Dis;
unsigned char SegData[4]={0};
unsigned char SegSata[4]={0};
void Init();
unsigned char k=0;
sbit led1=P2^4;
sbit led2=P2^5;
sbit led3=P2^6;
sbit led4=P2^7;
sbit buzzer=P1^0;
void main()
{
unsigned char T;
unsigned char RH;
Init();
LCD_Init(); //液晶初始化
LCD_Cls(); //液晶清屏
LCD_DisplayString(0,0,"S:",2);
LCD_DisplayString(9,0,"X:",2);
LCD_DisplayChar(2,0,TTop/10+0X30);
LCD_DisplayChar(3,0,TTop%10+0X30);
LCD_DisplayChar(11,0,TLow/10+0X30);
LCD_DisplayChar(12,0,TLow%10+0X30);
LCD_DisplayChar(5,0,RHTop/10+0X30);
LCD_DisplayChar(6,0,RHTop%10+0X30);
LCD_DisplayChar(14,0,RHLow/10+0X30);
LCD_DisplayChar(15,0,RHLow%10+0X30);
LCD_DisplayString(4,0,":",1);
LCD_DisplayString(13,0,":",1);
DHT11_Dis = Read_DHT11(); //获取温湿度
LCD_DisplayString(0,1,DHT11_Dis,16); //显示温湿度
while(1)
{
KeyValue=keyscan();
if(KeyValue)
{
Temp = KeyValue;
KeyValue=0;
switch(Temp)
{
case 1:TTop++;if(TTop>99)TTop=10;
LCD_DisplayChar(2,0,TTop/10+0X30);
LCD_DisplayChar(3,0,TTop%10+0X30);
break;
case 2:TTop--;if(TTop<10)TTop=99;
LCD_DisplayChar(2,0,TTop/10+0X30);
LCD_DisplayChar(3,0,TTop%10+0X30);
break;
case 3:TLow++;if(TLow>99)TLow=10;
LCD_DisplayChar(11,0,TLow/10+0X30);
LCD_DisplayChar(12,0,TLow%10+0X30);
break;
case 4:TLow--;if(TLow<10)TLow=99;
LCD_DisplayChar(11,0,TLow/10+0X30);
LCD_DisplayChar(12,0,TLow%10+0X30);
break;
case 5:RHTop++;if(RHTop>99)RHTop=30;
LCD_DisplayChar(5,0,RHTop/10+0X30);
LCD_DisplayChar(6,0,RHTop%10+0X30);
break;
case 6:RHTop--;if(RHTop<50)RHTop=51;
LCD_DisplayChar(5,0,RHTop/10+0X30);
LCD_DisplayChar(6,0,RHTop%10+0X30);
break;
case 7:RHLow++;if(RHLow>50)RHLow=49;
LCD_DisplayChar(14,0,RHLow/10+0X30);
LCD_DisplayChar(15,0,RHLow%10+0X30);
break;
case 8:RHLow--;if(RHLow<20)RHLow=21;
LCD_DisplayChar(14,0,RHLow/10+0X30);
LCD_DisplayChar(15,0,RHLow%10+0X30);
break;
}
}
if(k>=40)
{
k = 0;
DHT11_Dis = Read_DHT11(); //获取温湿度
LCD_DisplayString(0,1,DHT11_Dis,16); //显示温湿度
}
T=(DHT11_Dis[11]-0x30)*10+DHT11_Dis[12]-0x30;
RH=(DHT11_Dis[3]-0x30)*10+DHT11_Dis[4]-0x30;
if(TTop<T || TLow>T || RHTop<RH || RHLow>RH)
{
buzzer=0;
}
if(TTop<T) led1=0; else {led1=1;buzzer=1;}
if(TLow>T) led2=0; else {led2=1;buzzer=1;}
if(RHTop<RH) led3=0; else {led3=1;buzzer=1;}
if(RHLow>RH) led4=0; else {led4=1;buzzer=1;}
}
}
//定时器初始化
void Init()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
TR0=1;
EA=1;
}
void Timer0() interrupt 1
{
//led1=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
k++;//led1=0;
}
DHT11.C
//----以下变量均为全局变量--------
//----温度高8位== T_Data_H------
//----温度低8位== T_Data_L------
//----湿度高8位== RH_Data_H-----
//----湿度低8位== RH_Data_L-----
//----校验 8位 == CRC_Data-----
#include "DHT11.h"
//----------------IO口定义区--------------------//
sbit DHT11_IO = P1^1 ;
//----------------定义区--------------------//
unsigned char CRC_Error = 0,flag = 0;
void Delay(unsigned int j)
{
unsigned char i;
for(;j>0;j--)
{
for(i=0;i<127;i++);
}
}
void Delay_10us(void)
{
unsigned char i;
i--;
i--;
i--;
i--;
i--;
i--;
}
unsigned char Receive_Byte(void)
{
unsigned char i = 0;
unsigned char ReceiveData = 0;
bit temp;
for(i=0;i<8;i++)
{
while((!DHT11_IO)&&flag++);
Delay_10us();
Delay_10us();
Delay_10us();
temp=0;
if(DHT11_IO)
temp=1;
while((DHT11_IO)&&flag++);//超时则跳出for循环
ReceiveData <<= 1;
ReceiveData |= temp;
}
return ReceiveData;
}
unsigned char * Read_DHT11(void)
{
unsigned char T_Data_H,T_Data_L,RH_Data_H,RH_Data_L,CRC_Data;
static unsigned char DHT11_Data[17] = {0};
DHT11_IO=0;
Delay(20); //主机拉低 18ms,由于上电的不稳定性,延长时间适当拉长。
DHT11_IO=1; //总线由上拉电阻拉高 主机延时40us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
DHT11_IO=1; //主机设为输入 判断从机响应信号
if(!DHT11_IO) //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
{
flag=2;
while((!DHT11_IO)&&flag++); //判断从机是否发出 80us 的低电平响应信号是否结束
flag=2;
while((DHT11_IO)&&flag++); //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
RH_Data_H = Receive_Byte(); //数据接收
RH_Data_L = Receive_Byte();
T_Data_H = Receive_Byte();
T_Data_L = Receive_Byte();
CRC_Data = Receive_Byte();
DHT11_IO = 1;
if( CRC_Data != RH_Data_H + RH_Data_L + T_Data_H + T_Data_L)
{
RH_Data_H = 0;
RH_Data_L = 0;
T_Data_H = 0;
T_Data_L = 0;
}
else
{
DHT11_Data[0] = 'R';
DHT11_Data[1] = 'H';
DHT11_Data[2] = ':';
DHT11_Data[3] = RH_Data_H / 10 + 0x30;
DHT11_Data[4] = RH_Data_H % 10 + 0x30;
DHT11_Data[5] = '.';
DHT11_Data[6] = RH_Data_L / 10 + 0x30;
DHT11_Data[7] = '%';
DHT11_Data[8] = ' ';
DHT11_Data[9] = 'T';
DHT11_Data[10] = ':';
DHT11_Data[11] = T_Data_H / 10 + 0x30;
DHT11_Data[12] = T_Data_H % 10 + 0x30;
DHT11_Data[13] = '.';
DHT11_Data[14] = T_Data_L / 10 + 0x30;
DHT11_Data[15] = 0xdf; //1602液晶度的字符码
}
return DHT11_Data;
}
return 0;
}
DHT11.h
#ifndef __DHT11_H_
#define __DHT11_H_
#include
#include
void Delay(unsigned int j);
void Delay_10us(void);
unsigned char Receive_Byte(void);
unsigned char * Read_DHT11(void);
#endif
LCD1602.C
/******** (C) Copyright 2012 All rights reserved ********
* 文件名 : 160.2.c
* 版本 : V1.0
* 完成日期 : 2011-05-17
* 功能描述 : 1602液晶驱动程序
********************************************************************/
#include "1602.H"
sbit RS = P3^5;
sbit RW = P3^6;
sbit E = P3^7;
#define RS_High() RS = 1;_nop_();_nop_() //数据
#define RS_Low() RS = 0;_nop_();_nop_() //指令
#define RW_High() RW = 1;_nop_();_nop_() //读操作
#define RW_Low() RW = 0;_nop_();_nop_() //写操作
#define E_High() E = 1;_nop_();_nop_() //使能
#define E_Low() E = 0;_nop_();_nop_() //禁止
#define DataPort P0
#define DataInput() DataPort = 0xff
#define FirstLineAdd 0x80
#define SecondLineAdd 0xC0
#define DisplayData 1
#define Command 0
#define DisplayMode 0x38
#define DisplayOFF 0x08
#define LcdCls 0x01
#define DisplayCursor 0x06
#define DisplayOn 0x0C
/**************************************************
*函数名:Delay_Ms
*功能 :毫秒延时函数
*参数 :DelayTime - 延时时间 DelayTime 毫秒 晶振:12Mhz
**************************************************/
void Delay_Ms(unsigned char DelayTime)
{
unsigned int j;
while(DelayTime)
{
for(j = 0;j < 250;j ++)
_nop_();
DelayTime --;
}
}
/**************************************************
* 函数名称:LCD_CheckBusy()
* 功能 :判断液晶工作状态
* 返回值 :
**************************************************/
void LCD_CheckBusy()
{
DataInput(); //将P0口设置为数据输入
RS_Low(); //命令
RW_High(); //读数据
E_Low();
_nop_();
E_High(); //使能
while((bit)(DataPort & 0x80))
{
LCD_CheckBusy();
}
}
/**************************************************
* 函数名称:LCD_Cls()
* 功能 :清屏
**************************************************/
void LCD_Cls()
{
LCD_WriteByte(Command,LcdCls);
Delay_Ms(10);
}
/**************************************************
* 函数名称:LCD_WriteByte(bit DataOrCommand,unsigned char Data)
* 功能 :向液晶写入数据或者命令
* 参数 :DataOrCommand:数据或者命令判断 Data
**************************************************/
void LCD_WriteByte(bit DataOrCommand,unsigned char Data)
{
if(DataOrCommand == Command) //判断指令或者数据
{ RS_Low();}
else
{ RS_High();}
RW_Low(); //写入
E_High();
DataPort = Data;
Delay_Ms(5);
E_Low();
}
/**************************************************
* 函数名称:LCD_DisplayChar
* 功能 :在指定位置显示字符
* 参数 :Local_X X坐标, Local_Y Y坐标, Data 待显示字符
**************************************************/
void LCD_DisplayChar(unsigned char Local_X,unsigned char Local_Y,unsigned char Data)
{
LCD_CheckBusy();
if (Local_Y == FirstLine)
LCD_WriteByte(Command,FirstLineAdd + Local_X); //第一行X位置
else
LCD_WriteByte(Command,SecondLineAdd + Local_X); //第二行X位置
LCD_WriteByte(DisplayData,Data);
}
/**************************************************
* 函数名称:LCD_DisplayString
* 功能 :在指定位置显示字符
* 参数 :Local_X X坐标(0-15), Local_Y Y坐标(0-1), Str 待显示字符串
**************************************************/
void LCD_DisplayString(unsigned char Local_X,unsigned char Local_Y,unsigned char *Str,unsigned char Num)
{
LCD_CheckBusy();
if (Local_Y == FirstLine)
LCD_WriteByte(Command,FirstLineAdd + Local_X); //第一行X位置
else
LCD_WriteByte(Command,SecondLineAdd + Local_X); //第二行X位置
while(Num--)
{
LCD_WriteByte(DisplayData,*Str);
Str ++;
}
}
/**************************************************
* 函数名称:LCD_Init
* 功能 :液晶屏初始化
**************************************************/
void LCD_Init()
{
LCD_WriteByte(Command,DisplayMode); //显示模式: 16*2行显示,5*7点阵,8位数据接口
Delay_Ms(10);
LCD_WriteByte(Command,DisplayMode); //显示模式: 16*2行显示,5*7点阵,8位数据接口
Delay_Ms(10);
LCD_WriteByte(Command,DisplayMode); //显示模式: 16*2行显示,5*7点阵,8位数据接口
Delay_Ms(10);
LCD_WriteByte(Command,DisplayMode); //显示模式: 16*2行显示,5*7点阵,8位数据接口
LCD_WriteByte(Command,DisplayOFF); //显示关闭
LCD_WriteByte(Command,LcdCls); //显示清屏
LCD_WriteByte(Command,DisplayCursor); //显示光标 地址加1,光标加1
Delay_Ms(10);
LCD_WriteByte(Command,DisplayOn); //显示开
}
LCD1602.h
#ifndef __1602_H_
#define __1602_H_
#include
#include
#define FirstLine 0
#define SecondLine 1
void Delay_Ms(unsigned char DelayTime);
void LCD_CheckBusy();
void LCD_Cls();
void LCD_WriteByte(bit DataOrCommand,unsigned char Data);
void LCD_DisplayChar(unsigned char Local_X,unsigned char Local_Y,unsigned char Data);
void LCD_DisplayString(unsigned char Local_X,unsigned char Local_Y,unsigned char *Str,unsigned char Num);
void LCD_Init();
#endif
JuZhen.C
#include
#include
#include "juzhen.h"
#define u8 unsigned char
//矩阵键盘的扫描
unsigned char keyscan()
{
unsigned char value = 0;//定义按键值
u8 row,column;
P2=0xf0;
if(P2!=0xf0)
{
Selay(20);
if(P2!=0xf0)
{
row=P2;
P2=0x0f;
column=P2;
switch(row|column)
{
case 0x77:Selay(50);value=1;if(value==1);Selay(50);break;//温度上限阈值+1
case 0xb7:Selay(50);value=2;if(value==2);Selay(50);break;//温度上限阈值-1
case 0xd7:Selay(50);value=3;if(value==3);Selay(50);break;//温度下限阈值+1
case 0xe7:Selay(50);value=4;if(value==4);Selay(50);break;//温度下限阈值-1
case 0x7b:Selay(50);value=5;if(value==5);Selay(50);break;
case 0xbb:Selay(50);value=6;if(value==6);Selay(50);break;
case 0xdb:Selay(50);value=7;if(value==7);Selay(50);break;
case 0xeb:Selay(50);value=8;if(value==8);Selay(50);break;
default:value=0;break;
}
}
}
return value;//返回最终的键值
}
void Selay(unsigned char k) //@11.0592MHz
{
unsigned char o, u;
while(k--)
{
_nop_();
o = 2;
u = 199;
do
{
while (--u);
} while (--o);
}
}
JuZhen.h
#ifndef __JUZHEN_H_
#define __JUZHEN_H_
unsigned char keyscan();
void Selay(unsigned char k);
#endif
通过这次课设我也学习到了很多,通过写博客的方式来分享我的学习成果:
1.要学会使用switch case语句,要不一直用if语句会很麻烦。
2.定时器延时与Delay延时的区别:
定时器的做法是在你的程序里还有其他事要做的情况下去设置的。也就是说设置了定时器后就可以去做其他事情了,delay就是不做事光用消耗的,消耗一定的时间后再去做其他事。
3.extern后面要加全局变量,不能加局部变量。
4.使用指针定义的时候,要将指针指向一个区域。例如:unsigned char *p; p=&a;
5.指针与数组是可以相互转换的。
6.要让lcd上面显示相应的字符,要写入这个字符对应的Ascll码值,写入的整数字符要+0x30。要想变回原来的整数也要减去相应的0x30。
例: T=(DHT11_Dis[11]-0x30)*10+DHT11_Dis[12]-0x30;
7.要多看数据手册,多看一些比较成体系的视频,学习不要碎片化。