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 做出反应会将在 15us60us 后总线 拉低 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仿真图:
完整代码:
包含多个头文件,各位在复现时可创建新文件然后复制代码即可。
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
本文转载自: https://blog.csdn.net/clonearm/article/details/121979749
版权归原作者 茅山大师兄 所有, 如有侵权,请联系我们删除。
版权归原作者 茅山大师兄 所有, 如有侵权,请联系我们删除。