51单片机个人课程设计–基于stc89c52及红外遥控的测温智能电风扇
个人学校的课程设计-智能电风扇,包含proteus原理图与源代码。
代码部分由我个人写的也有普中实验中的代码块。
3.1 硬件设计
主要器件:
- 单片机 AT89C52
- 红外接收 HS0038
- LCD1602
- 温度测量 DS18B20
- 驱动集成芯片 L298N
- 导线及各类电阻
- 红外遥控器
功能设计:
本智能风扇采用 stc89c52 为芯片,使用 lcd1602 作为信息输出设备,配
备有红外遥控器,同时使用 DS18B02 作为温度收集元件,而使用 L298N 芯片
来实现 pwm 控制电机不同转速。图 1 智能风扇仿真
DS18B20图 3 DS18B20 温度测量模块
DS18B20dq 为数据传输线。
(3) HS0038 红外接收模块
PROTEUS 中无 HS0038 元件,所以无仿真图,实物连接时连接 P3^2。
HS0038 红外接收通过接收红外信号,信号经过芯片处理后即可判别选择不同功
能。
(4) L298N 电机驱动模块
图 4 L298N 直流电机模块
3.2 软件设计
本程序设计采用多个头文件形式,使得程序结构层次分明,逻辑清晰,在
后续的开发改进升级维护时更加容易。
本程序分为多个功能程序单独文件编写调用形式,在很大程度上减少了主
程序长度,代码逻辑清晰分明,程序分为多个模块,包含了 lcd1602 显示程序,
temp 测温模块,红外遥控模块,及各个模块的初始化程序。在主程序中包含了
一些定义与对各个模块函数的调用,以及风扇驱动与状态判断程序。
(1) .红外接收模块:
此模块使用了红外接收头 HS0038 作为硬件功能部分, 在主要程序上其连接
P3^2 即 INT0 引脚,设定为下降沿触发,在接收到红外信号后进入中断程序,
在中断程序中通过判断 P3^2 上电平持续时间来得到所需要的信息。在这里不得
不提到红外协议中的 NEC 协议。载波 38khz 包含了逻辑 0 与逻辑 1。
逻辑 1 共计 2.25ms 先是持续 0.56ms 的低电平然后是 1.69ms 的高电平。
逻辑 0 共计 1.12ms,先为 0.56ms 的低电平然后是 0.56ms 的高电平。
NEC 协议格式:
P3.6
P3.7 5 IN1
7 IN2
6 ENA
OUT1 2
OUT2 3
11 ENB OUT3 13
OUT4 14
10 IN3
12 IN4
1 SENSA
15 SENSB GND
8
VS
4
VCC
9 U2
L298
+88.8图 5 红外 NEC 协议
首先发送 9ms 的起始码然后是 4.5ms 的低电平,然后是 8 位用户码之后是
8 位用户码的反码(主要用于校验是否出错) 然后是 8 位数据码之后是 8 位数
据码的反码。需要注意的是数据从低位开始发送选择右移接收方式。
(1) .红外接收程序;
Ired.c 文件包含了红外接收的各种函数及中断程序
/*******************************************************************************
- 函 数 名 : ired_init
- 函数功能 : 红外端口初始化函数,外部中断 0 配置
- 输 入 : 无
- 输 出 : 无
/
void ired_init(void)
{
IT0=1; //下降沿触发
EX0=1; //打开中断 0 允许
EA=1; //打开总中断
IRED=1; //初始化端口
}
void ired() interrupt 0 //外部中断 0 服务函数
{
u8 ired_high_time=0;
u16 time_cnt=0;
u8 i=0,j=0;
if(IRED0){
time_cnt=1000;
while((!IRED)&&(time_cnt))//等待引导信号 9ms 低电平结束,若超过 10ms 强制退
出
{
delay_10us(1);//延时约 10us
time_cnt–;
if(time_cnt0)return;
}
if(IRED)//引导信号 9ms 低电平已过,进入 4.5ms 高电平
{
time_cnt=500;
while(IRED&&time_cnt)//等待引导信号 4.5ms 高电平结束,若超过 5ms 强制
退出
{
delay_10us(1);
time_cnt–;
if(time_cnt0)return;
}
for(i=0;i<4;i++)//循环 4 次,读取 4 个字节数据
{
for(j=0;j<8;j++)//循环 8 次读取每位数据即一个字节
{
time_cnt=600;
while((IRED0)&&time_cnt)//等待数据 1 或 0 前面的 0.56ms 结束,
若超过 6ms 强制退出
{
delay_10us(1);
time_cnt–;
if(time_cnt==0)return;}
time_cnt=20;
while(IRED)//等待数据 1 或 0 后面的高电平结束,若超过 2ms 强制
退出
{
delay_10us(10);//约 0.1ms
ired_high_time++;
if(ired_high_time>20)return;
}
gired_data[i]>>=1;//先读取的为低位,然后是高位
if(ired_high_time>=8)//如果高电平时间大于 0.8ms,数据则为 1,
否则为 0
gired_data[i]|=0x80;
ired_high_time=0;//重新清零,等待下一次计算时间
}
}
}
if(gired_data[2]!=~gired_data[3])//校验控制码与反码,错误则返回
{
for(i=0;i<4;i++)
gired_data[i]=0;
return;
}
}
}
(2) .lcd1602 显示模块;
此功能模块硬件选择 lcd1602 作为硬件部分在硬件部分上 vo 位额外使用滑动变阻器使得能够
自由调整亮度,软件部分包含了写命令与写字符部分,以次来实现写入字符与命令等。
Lcdplus.c 文件包含 lcd1602 的各种函数包括写命令和写入字符功能等。
#include"lcdplus.h"void Lcd1602_Delay1ms(int c) //误差 0us
{
u8 a,b;
for (; c>0; c–)
{
for (b=199;b>0;b–)
{
for(a=1;a>0;a–);
}
}
}
void init()
{
wc51r(0x38);
wc51r(0x0c);
wc51r(0x06);
}
void fbusy()
{
P2=0Xff;RS=0;RW=1;
E=0;
E=1;
while(P0&0X80){E=0;E=1;}
}
void wc51r(u8 j)
{
fbusy();
E=0;RS=0;RW=0;
E=1;P0=j;
Lcd1602_Delay1ms(2);E=0;}
void wc51ddr(u8 j)
{
fbusy();
E=0;RS=1;RW=0;Lcd1602_Delay1ms(2);
E=1;P0=j;E=0;
}
( 3) .温度检测程序部分:
硬件采用 DS18b20 进行温度的采集处理。 软件部分有初始化,写
数据等函数, 对于各个函数在函数前有队函数的说明。 模块包含两个
文件 temp.H 与 temp.C 文件
temp.h 此文件包含了 temp.c 所需的各种宏定义等。
/ - 函数名 : Ds18b20Init
- 函数功能 : 初始化
- 输入 : 无
- 输出 : 初始化成功返回 1,失败返回 0
/
unsigned char Ds18b20Init()
{
unsigned int i;
DSPORT=0; //将总线拉低 480us~960us
i=70;
while(i–);//延时 642us
DSPORT=1; //然后拉高总线,如果 DS18B20 做出反应会将在 15us~60us 后总线
拉低
i=0;
while(DSPORT) //等待 DS18B20 拉低总线
{i++;
if(i>5000)//等待>5MS
return 0;//初始化失败
}
return 1;//初始化成功
}
/ - 函数名 : Ds18b20WriteByte
- 函数功能 : 向 18B20 写入一个字节
- 输入 : com
- 输出 : 无
/
void Ds18b20WriteByte(unsigned char dat)
{
unsigned int i,j;
for(j=0;j<8;j++)
{
DSPORT=0; //每写入一位数据之前先把总线拉低 1us
i++;
DSPORT=dat&0x01; //然后写入一个数据,从最低位开始
i=6;
while(i–); //延时 68us,持续时间最少 60us
DSPORT=1; //然后释放总线,至少 1us 给总线恢复时间才能接着写入第二个数值
dat>>=1;
}
}/ - 函数名 : Ds18b20ReadByte
- 函数功能 : 读取一个字节
- 输入 : com
- 输出 : 无
**/
unsigned char Ds18b20ReadByte()
{
unsigned char byte,bi;
unsigned int i,j;
for(j=8;j>0;j–)
{
DSPORT=0;//先将总线拉低 1us
i++;
DSPORT=1;//然后释放总线
i++;
i++;//延时 6us 等待数据稳定
bi=DSPORT; //读取数据,从最低位开始读取
/将 byte 左移一位,然后与上右移 7 位后的 bi,注意移动之后移掉那位补 0。 /
byte=(byte>>1)|(bi<<7);
i=4; //读取完之后等待 48us 再接着读取下一个数
while(i–);
}
return byte;
}
/ - 函数名 : Ds18b20ChangTemp
- 函数功能 : 让 18b20 开始转换温度
- 输入 : com
- 输出 : 无*******************************************************************************/
void Ds18b20ChangTemp()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //跳过 ROM 操作命令
Ds18b20WriteByte(0x44); //温度转换命令
}
/******************************************************************************* - 函数名 : Ds18b20ReadTempCom
- 函数功能 : 发送读取温度命令
- 输入 : com
- 输出 : 无
/
void Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //跳过 ROM 操作命令
Ds18b20WriteByte(0xbe); //发送读取温度命令
}
/ - 函数名 : Ds18b20ReadTemp
- 函数功能 : 读取温度
- 输入 : com
- 输出 : 无*******************************************************************************/
short Ds18b20ReadTemp()
{
unsigned char temp=0;
unsigned char tmh,tml;
short tem;
Ds18b20ChangTemp(); //先写入转换命令
Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令
tml=Ds18b20ReadByte(); //读取温度值共 16 位,先读低字节
tmh=Ds18b20ReadByte(); //再读高字节
if(tmh>7)
{
tmh=~tmh;
tml=~tml;
temp=0;//温度为负
}
else
{
temp=1;//温度为正
}
tem=tmh; //获得高八位
tem<<=8;
tem|=tml;//获得底八位
tem=(double)tem*0.625;//转换 放大 10 倍 精度 0.1
if(temp)
return tem; //返回温度值
elsereturn -tem;
}
( 4) 主程序部分:
程序运行的主体部分,调用以上各文件中函数实现智能电风扇的功能。
遥控器开关数据码: 44 开关启动 40 43 加数 46 47 减数 按下 eq07 后 设置定时时间按对应数字键。
程序主体:
#include “reg52.h”
#include “public.h”
#include “ired.h”
#include “lcdplus.h”
#include “temp.h”
sbit PWM=P3^6;
sbit PWM2=P3^7;
unsigned char time;
double count=0;
int eq1;
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u8 lcdnum[10]={‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’};
u8 p={’ ‘};
u8 E1,E2,E3,EQ;
u8 blueh ;u8 bluel;
u8 blue1,blue2,blue3;
int red1,red2,red3;
sbit led=P2^0;
static unsigned char time1,time2,time3,time4;
unsigned char num = 0;
void delay(u8 c) //误差 0us 1ms 延时;{
for (; c>0; c–);
}
u8 temp_buf[5];
void Temp_DataPros()
{
short temp;
temp=Ds18b20ReadTemp();
if(temp<0)
{
temp=-temp;
}
temp_buf[0]=temp/100+0x30;
temp_buf[1]=temp%100/10+0x30;
temp_buf[2]=’.’;
temp_buf[3]=temp%100%10+0x30;
temp_buf[4]=’\0’; //显示检测的温度 xx.x
}
void tmtime() interrupt 1
{
TH0=0X3C;
TL0=0XB0;
num++;
if(num20)
{num = 0;
time4=time4-1;if(IRED1)
if(time40)
{time4=9;time3=time3-1;
if(time30){time3=6;time2=time2-
1;if(time2==0){time2=9;time1=time1-1;}}
}
}
}
*******************************************************************************/ - 函数名 : time0()
- 函数功能 : 电机转速 pwm 控制
- 输入 : 无
- 输出 : 无
*******************************************************************************/
void time0() interrupt 3
{
TR1=0; //设置定时器初值期间,关闭定时器
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
TR1=1;
PWM2=0;
time++;
if(time<count) //count 为占空比
{
PWM=1;
//输出高电平
}
else
PWM=0;if(time>=100)
{
time=0;
}
}
*******************************************************************************/ - 函数名 : fengshan()
- 函数功能 : 红外遥控控制
- 输入 : 无
- 输出 : 无
*******************************************************************************/
void fengshan ()
{
unsigned char a;
unsigned char b;
a=gsmg_code[gired_data[2]/16];//将控制码高 4 位转换为段码
b=gsmg_code[gired_data[2]%16];//将控制码低 4 位转换为段码
switch(a)
{
case 0x66:
{a=0x00;
switch(b)
{
case 0x3f: //档位减小
{
red1=red1-1;b=0x00;count=count-10;
gired_data[2]=0;
if(red1<0){
red1=0;count=0;
}
}break;
case 0x7d: //时间减少
{time2=time2-1;b=0x00;if(time20)
{time2=9;time1=time1-1;}
gired_data[2]=0;
}break;
case 0x4f: //档位加大
{
red1=red1+1;b=0x00;
gired_data[2]=0;count=count+10;
if(red1>9)
{red1=0;count=0;
}
}break;
case 0x07: //时间曾大
{ time2=time2+1;b=0x00;
if(time2>=9){time2=0;time1=time1+1;}
gired_data[2]=0;
} break;
case 0x6d: //风扇开关
{ TR1=~TR1;gired_data[2]=0;
}break;
case 0x66: //定时开关 默认关默认时间 10 分钟
{ TR0=~TR0;gired_data[2]=0;
} break;}
}break;
case 0x3f:
{
if(b0x07)
{
E1=’ ';E2=‘O’,E3=‘N’;
gired_data[2]=0;
eq1=1;
}
if(b==0x39)
{
E1=‘O’;E2=‘F’,E3=‘F’; eq1=0;
}
} break;
}
}
*******************************************************************************/ - 函数名 : main
- 函数功能 : 主函数
- 输入 : 无
- 输出 : 无
*******************************************************************************/
void main()
{
ired_init();//红外初始化
P2=0X00;
SP=0X50;
init();blue1=blue2=blue3=0;//比分初始化
time1=0,time2=9,time3=5;time4=9;
EA=1;TMOD=0X01;TR0=1;ET0=1;
TH0=0X3C;
TL0=0XB0;
P2=0X00;
Ds18b20Init();
TH1=(65536-100)/256;
TL1=(65536-100)%256;
ET1=1;
TR1=0;//默认风扇开
E1=‘O’;E2=‘F’,E3=‘F’;
while(1)
{ TR1=0;
Ds18b20ReadTempCom();
Temp_DataPros();
fengshan ();
wc51r(0x80);
wc51ddr(‘T’);wc51ddr(‘E’);wc51ddr(‘M’);wc51ddr(‘P’);wc51ddr(’:’);wc51ddr(
temp_buf[0]);wc51ddr(temp_buf[1]);wc51ddr(temp_buf[2]);wc51ddr(temp_buf[3]);wc
51ddr§; wc51ddr§;wc51ddr§;wc51ddr(‘K’);wc51ddr(lcdnum[red1]);
wc51ddr§;wc51ddr§;
wc51r(0xc0);wc51ddr(‘t’);wc51ddr(‘i’);wc51ddr(‘m’);wc51ddr(‘e’);wc51ddr(l
cdnum[time1]);wc51ddr(lcdnum[time2]);wc51ddr(’:’);wc51ddr(lcdnum[time3]);wc51d
dr(lcdnum[time4]);
wc51ddr§;wc51ddr(‘E’);wc51ddr(‘Q’);wc51ddr§;wc51ddr(E1);wc51ddr(E2);wc51dd
r(E3);
if(eq11){TR1=1;
if(temp_buf[0]‘2’||temp_buf[0]‘3’||temp_buf[0]‘4’||temp_buf[0]‘5’
||temp_buf[0]‘6’||temp_buf[0]‘7’||temp_buf[0]‘8’||temp_buf[0]‘9’)
if(temp_buf[1]‘5’||temp_buf[1]‘6’||temp_buf[1]‘7’||temp_buf[1]‘8’
||temp_buf[1]‘9’)
{red1=red1+1;count=count+10;
if(red1>=9)
red1=9;count=90;}
else
red1=count=0;
}
else
TR1=1;
} }
proteus仿真图:
文章来源:https://www.toymoban.com/news/detail-409852.html
完整代码:
包含多个头文件,各位在复现时可创建新文件然后复制代码即可。文章来源地址https://www.toymoban.com/news/detail-409852.html
1 完整代码
文件 main.C
//44 开关启动 40 43 加数 46 47 减数 按下 eq07 后 设置定时时间按对应数字键。
#include "reg52.h"
#include "public.h"
#include "ired.h"
#include "lcdplus.h"
#include "temp.h"
sbit PWM=P3^6;
sbit PWM2=P3^7;
unsigned char time;
double count=0;
int eq1;
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u8 lcdnum[10]={'0','1','2','3','4','5','6','7','8','9'};
u8 p={' '};
u8 E1,E2,E3,EQ;
u8 blueh ;u8 bluel;
u8 blue1,blue2,blue3;
int red1,red2,red3;
sbit led=P2^0;static unsigned char time1,time2,time3,time4;
unsigned char num = 0;
void delay(u8 c) //误差 0us 1ms 延时;
{
for (; c>0; c--);
}
u8 temp_buf[5];
void Temp_DataPros()
{
short temp;
temp=Ds18b20ReadTemp();
if(temp<0)
{
temp=-temp;
}
temp_buf[0]=temp/100+0x30;
temp_buf[1]=temp%100/10+0x30;
temp_buf[2]='.';
temp_buf[3]=temp%100%10+0x30;
temp_buf[4]='\0'; //显示检测的温度 xx.x
}
void tmtime() interrupt 1
{
TH0=0X3C;
TL0=0XB0;num++;
if(num==20)
{
num = 0;
time4=time4-1;if(IRED==1)
if(time4==0)
{time4=9;time3=time3-1;
if(time3==0){time3=6;time2=time2-1;if(time2==0){time2=9;time1=time1-1;}}
}
}
}
void time0() interrupt 3
{
TR1=0; //设置定时器初值期间,关闭定时器
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
TR1=1;
PWM2=0;
time++;
if(time<count) //count 为占空比
{
PWM=1;
//输出高电平
}
else
PWM=0;
if(time>=100)
{
time=0;
}}
void fengshan ()
{
unsigned char a;
unsigned char b;
a=gsmg_code[gired_data[2]/16];//将控制码高 4 位转换为数码管段码
b=gsmg_code[gired_data[2]%16];//将控制码低 4 位转换为数码管段码
switch(a)
{
case 0x66:
{a=0x00;
switch(b)
{
case 0x3f: //档位减小
{
red1=red1-1;b=0x00;count=count-10;
gired_data[2]=0;
if(red1<0)
{
red1=0;count=0;
}
}break;
case 0x7d: //时间减少
{time2=time2-1;b=0x00;if(time2==0)
{time2=9;time1=time1-1;}
gired_data[2]=0;
}break;case 0x4f: //档位加大
{
red1=red1+1;b=0x00;
gired_data[2]=0;count=count+10;
if(red1>9)
{red1=0;count=0;
}
}break;
case 0x07: //时间曾大
{ time2=time2+1;b=0x00;
if(time2>=9){time2=0;time1=time1+1;}
gired_data[2]=0;
} break;
case 0x6d: //风扇开关
{ TR1=~TR1;gired_data[2]=0;
}break;
case 0x66: //定时开关 默认关默认时间 10 分钟
{ TR0=~TR0;gired_data[2]=0;
} break;
}
}break;
case 0x3f:
{
if(b==0x07)
{
E1=' ';E2='O',E3='N';
gired_data[2]=0;
eq1=1;}
if(b==0x39)
{
E1='O';E2='F',E3='F'; eq1=0;
}
} break;
}
}
void main()
{
ired_init();//红外初始化
P2=0X00;
SP=0X50;
init();
blue1=blue2=blue3=0;//比分初始化
time1=0,time2=9,time3=5;time4=9;
EA=1;TMOD=0X01;TR0=1;ET0=1;
TH0=0X3C;
TL0=0XB0;
P2=0X00;
Ds18b20Init();
TH1=(65536-100)/256;
TL1=(65536-100)%256;
ET1=1;
TR1=0;//默认风扇开
E1='O';E2='F',E3='F';
while(1){ TR1=0;
Ds18b20ReadTempCom();
Temp_DataPros();
fengshan ();
wc51r(0x80);
wc51ddr('T');wc51ddr('E');wc51ddr('M');wc51ddr('P');wc51ddr(':');wc51ddr(temp_buf[0]);w
c51ddr(temp_buf[1]);wc51ddr(temp_buf[2]);wc51ddr(temp_buf[3]);wc51ddr(p);
wc51ddr(p);wc51ddr(p);wc51ddr('K');wc51ddr(lcdnum[red1]); wc51ddr(p);wc51ddr(p);
wc51r(0xc0);wc51ddr('t');wc51ddr('i');wc51ddr('m');wc51ddr('e');wc51ddr(lcdnum[time1]);
wc51ddr(lcdnum[time2]);wc51ddr(':');wc51ddr(lcdnum[time3]);wc51ddr(lcdnum[time4]);
wc51ddr(p);wc51ddr('E');wc51ddr('Q');wc51ddr(p);wc51ddr(E1);wc51ddr(E2);wc51ddr(E3);
if(eq1==1)
{TR1=1;
if(temp_buf[0]=='2'||temp_buf[0]=='3'||temp_buf[0]=='4'||temp_buf[0]=='5'||temp_buf[0]=
='6'||temp_buf[0]=='7'||temp_buf[0]=='8'||temp_buf[0]=='9')
if(temp_buf[1]=='5'||temp_buf[1]=='6'||temp_buf[1]=='7'||temp_buf[1]=='8'||temp_buf[1]=
='9')
{red1=red1+1;count=count+10;
if(red1>=9)
red1=9;count=90;}
else
red1=count=0;
}
else
TR1=1;
}}
*******************************************************************************/
*******************************************************************************/
PUBLIC.H 文件
#ifndef _public_H
#define _public_H
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
typedef unsigned long u32;
void delay_10us(u16 ten_us);
void delay_ms(u16 ms);
#endif
PUBLIC.C 文件
#include "public.h"
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数, ten_us=1 时,大约延时 10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms 延时函数, ms=1 时,大约延时 1ms
* 输 入 : ms: ms 延时时间
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}*******************************************************************************/
*******************************************************************************/
Ired.c 文件
#include "ired.h"
u8 gired_data[4];//存储 4 个字节接收码(地址码+地址反码+控制码+控制反码)
/*******************************************************************************
* 函 数 名 : ired_init
* 函数功能 : 红外端口初始化函数,外部中断 0 配置
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void ired_init(void)
{
IT0=1; //下降沿触发
EX0=1; //打开中断 0 允许
EA=1; //打开总中断
IRED=1; //初始化端口
}
void ired() interrupt 0 //外部中断 0 服务函数
{
u8 ired_high_time=0;
u16 time_cnt=0;
u8 i=0,j=0;
if(IRED==0)
{
time_cnt=1000;
while((!IRED)&&(time_cnt))//等待引导信号 9ms 低电平结束,若超过 10ms 强制退
出
{
delay_10us(1);//延时约 10us
time_cnt--;
if(time_cnt==0)return;
}
if(IRED)//引导信号 9ms 低电平已过,进入 4.5ms 高电平
{
time_cnt=500;
while(IRED&&time_cnt)//等待引导信号 4.5ms 高电平结束,若超过 5ms 强制
退出
{delay_10us(1);
time_cnt--;
if(time_cnt==0)return;
}
for(i=0;i<4;i++)//循环 4 次,读取 4 个字节数据
{
for(j=0;j<8;j++)//循环 8 次读取每位数据即一个字节
{
time_cnt=600;
while((IRED==0)&&time_cnt)//等待数据 1 或 0 前面的 0.56ms 结束,
若超过 6ms 强制退出
{
delay_10us(1);
time_cnt--;
if(time_cnt==0)return;
}
time_cnt=20;
while(IRED)//等待数据 1 或 0 后面的高电平结束,若超过 2ms 强制
退出
{
delay_10us(10);//约 0.1ms
ired_high_time++;
if(ired_high_time>20)return;
}
gired_data[i]>>=1;//先读取的为低位,然后是高位
if(ired_high_time>=8)//如果高电平时间大于 0.8ms,数据则为 1,否
则为 0
gired_data[i]|=0x80;
ired_high_time=0;//重新清零,等待下一次计算时间
}
}
}
if(gired_data[2]!=~gired_data[3])//校验控制码与反码,错误则返回
{
for(i=0;i<4;i++)
gired_data[i]=0;
return;
}
}
}
*******************************************************************************/
*******************************************************************************/
Ired.h 文件#ifndef _ired_H
#define _ired_H
#include "public.h"
//管脚定义
sbit IRED=P3^2;
//声明变量
extern u8 gired_data[4];
//函数声明
void ired_init(void);
#endif
Lcdplus.H 文件
#ifndef _lcdplus_H
#define _lcdplus_H
#include "public.h"
sbit RS = P2^6;
sbit RW = P2^5;
sbit E = P2^7;
void init(void);
void wc51r(u8 i);
void wc51ddr(u8 i);
void fbust(void);
void Lcd1602_Delay1ms(u8 c);
#endif
*******************************************************************************/
*******************************************************************************/
Lcdplus.C 文件
#include"lcdplus.h"
void Lcd1602_Delay1ms(int c) //误差 0us
{
u8 a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}}
}
void init()
{
wc51r(0x38);
wc51r(0x0c);
wc51r(0x06);
}
void fbusy()
{
P2=0Xff;RS=0;RW=1;
E=0;
E=1;
while(P0&0X80){E=0;E=1;}
}
void wc51r(u8 j)
{
fbusy();
E=0;RS=0;RW=0;
E=1;P0=j;
Lcd1602_Delay1ms(2);E=0;
}
void wc51ddr(u8 j)
{
fbusy();
E=0;RS=1;RW=0;Lcd1602_Delay1ms(2);
E=1;P0=j;E=0;
}
*******************************************************************************/
*******************************************************************************/
Temp.c 文件
#include "temp.h"
/*******************************************************************************
* 函数名 : Delay1ms
* 函数功能 : 延时函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Delay1ms(unsigned int y)
{
unsigned int x;for(y;y>0;y--)
for(x=110;x>0;x--);
}
/*******************************************************************************
* 函数名 : Ds18b20Init
* 函数功能 : 初始化
* 输入 : 无
* 输出 : 初始化成功返回 1,失败返回 0
*******************************************************************************/
unsigned char Ds18b20Init()
{
unsigned int i;
DSPORT=0; //将总线拉低 480us~960us
i=70;
while(i--);//延时 642us
DSPORT=1; //然后拉高总线,如果 DS18B20 做出反应会将在 15us~60us 后
总线拉低
i=0;
while(DSPORT) //等待 DS18B20 拉低总线
{
i++;
if(i>5000)//等待>5MS
return 0;//初始化失败
}
return 1;//初始化成功
}
/*******************************************************************************
* 函数名 : Ds18b20WriteByte
* 函数功能 : 向 18B20 写入一个字节
* 输入 : com
* 输出 : 无
*******************************************************************************/
void Ds18b20WriteByte(unsigned char dat)
{
unsigned int i,j;
for(j=0;j<8;j++)
{
DSPORT=0; //每写入一位数据之前先把总线拉低 1us
i++;
DSPORT=dat&0x01; //然后写入一个数据,从最低位开始
i=6;while(i--); //延时 68us,持续时间最少 60us
DSPORT=1; //然后释放总线,至少 1us 给总线恢复时间才能接着写入第二个数
值
dat>>=1;
}
}
/*******************************************************************************
* 函数名 : Ds18b20ReadByte
* 函数功能 : 读取一个字节
* 输入 : com
* 输出 : 无
*******************************************************************************/
unsigned char Ds18b20ReadByte()
{
unsigned char byte,bi;
unsigned int i,j;
for(j=8;j>0;j--)
{
DSPORT=0;//先将总线拉低 1us
i++;
DSPORT=1;//然后释放总线
i++;
i++;//延时 6us 等待数据稳定
bi=DSPORT; //读取数据,从最低位开始读取
/*将 byte 左移一位,然后与上右移 7 位后的 bi,注意移动之后移掉那位补 0。 */
byte=(byte>>1)|(bi<<7);
i=4; //读取完之后等待 48us 再接着读取下一个数
while(i--);
}
return byte;
}
/*******************************************************************************
* 函数名 : Ds18b20ChangTemp
* 函数功能 : 让 18b20 开始转换温度
* 输入 : com
* 输出 : 无
*******************************************************************************/
void Ds18b20ChangTemp()
{
Ds18b20Init();
Delay1ms(1);Ds18b20WriteByte(0xcc); //跳过 ROM 操作命令
Ds18b20WriteByte(0x44); //温度转换命令
}
/*******************************************************************************
* 函数名 : Ds18b20ReadTempCom
* 函数功能 : 发送读取温度命令
* 输入 : com
* 输出 : 无
*******************************************************************************/
void Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //跳过 ROM 操作命令
Ds18b20WriteByte(0xbe); //发送读取温度命令
}
/*******************************************************************************
* 函数名 : Ds18b20ReadTemp
* 函数功能 : 读取温度
* 输入 : com
* 输出 : 无
*******************************************************************************/
short Ds18b20ReadTemp()
{
unsigned char temp=0;
unsigned char tmh,tml;
short tem;
Ds18b20ChangTemp(); //先写入转换命令
Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令
tml=Ds18b20ReadByte(); //读取温度值共 16 位,先读低字节
tmh=Ds18b20ReadByte(); //再读高字节
if(tmh>7)
{
tmh=~tmh;
tml=~tml;
temp=0;//温度为负
}else
{
temp=1;//温度为正
}
tem=tmh; //获得高八位
tem<<=8;
tem|=tml;//获得底八位
tem=(double)tem*0.625;//转换 放大 10 倍 精度 0.1
if(temp)
return tem; //返回温度值
else
return -tem;
}
*******************************************************************************/
*******************************************************************************/
Temp.h 文件
#ifndef _temp_H_
#define _temp_H_
#include "public.h"
sbit DSPORT=P1^7;
void Delay1ms(unsigned int );
unsigned char Ds18b20Init();
void Ds18b20WriteByte(unsigned char com);
unsigned char Ds18b20ReadByte();
void Ds18b20ChangTemp();
void Ds18b20ReadTempCom();
short Ds18b20ReadTemp();
#endif
到了这里,关于免费开源51单片机个人课程设计--基于stc89c52及红外遥控的测温智能电风扇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!