标题:
STC8A8K单片机+DHT11+DS1302+DS18B20源程序
[打印本页]
作者:
hfdgd
时间:
2020-5-8 23:16
标题:
STC8A8K单片机+DHT11+DS1302+DS18B20源程序
传感器的接口可以自己修改定义,这里就不放图了。
单片机源程序如下:
#include "stc8.h"
#include "spi.h"
#include "uart.h"
#include "delay.h"
#include "18b20.h"
#include "stdio.h"
#define uchar unsigned char
#define uint unsigned int
/*********** DHT11定义 *******************/
sbit dht_dat=P4^1; //dht11的IO口
uchar dht_num=0; //用于while 循环中计数,超时则跳出循环
uchar dht_d1=0,dht_d2=0; //依次为湿度整数部分和湿度小数部分
uchar dht_t1=0,dht_t2=0; //依次为温度整数部和小数部分
uchar dht_j=0; //和校验,可以选择是否使用,具体参照数据手册
/************ DS1302定义 ********/
//---定义ds1302使用的IO口---//
sbit SCLK=P2^5;
sbit DSIO=P2^4;
sbit rst=P2^3;
//---定义全局函数---//
void Ds1302Write(u8 addr, u8 dat);
u8 Ds1302Read(u8 addr);
void Ds1302Init();
void Ds1302ReadTime();
//---加入全局变量--//
extern u8 TIME[7]; //加入全局变量
u8 code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
u8 code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2017年2月17日星期五20点16分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
u8 TIME[7] = {0x00,0x16, 0x11, 0x20, 0x03, 0x03, 0x19};
u8 sec,min,hour,sec1,min1,hour1,ri,ri1,yue,yue1,nian,nian1,zhou,zhou1;
/********* 函数声明 ************/
void dht_init();
uchar read_date();
void get_temp();
void Ds1302Write(u8 addr, u8 dat);
u8 Ds1302Read(u8 addr);
void Ds1302Init();
void Ds1302ReadTime();
void pors(void);
void display();//显示函数
/******** 主函数 ********/
int main()
{
double temp;
char displaytemp[16];
dht_init(); //dht11初始化
uart_init(); //串口初始化
Lcd_Init(); //初始化OLED
Ds1302Init(); //ds1302初始化
LCD_Clear(WHITE);
BACK_COLOR=WHITE;
display();
while(1)
{
/*******ds18b20*****/
temp=readtemp();//读取温度
LCD_ShowChinese(20,150,14,16,BLACK); //水
LCD_ShowChinese(35,150,0,16,BLACK); //温
LCD_ShowString(50,150,":",BLACK); //:
sprintf(displaytemp,"%7.3f",temp);//打印温度值
LCD_ShowString(65,150,displaytemp,RED); //
LCD_ShowChinese(130,150,8,16,RED); //℃
/*******ds1302*******/
pors();
Ds1302ReadTime();
LCD_ShowString(20,45,"20",RED); //
LCD_ShowNum(35,45,nian1,1,RED); //
LCD_ShowNum(40,45,nian,1,RED); //显示年
LCD_ShowNum(75,45,yue1,1,RED); //
LCD_ShowNum(85,45,yue,1,RED); //显示月
LCD_ShowNum(115,45,ri1,1,RED); //
LCD_ShowNum(125,45,ri,1,RED); //显示日
LCD_ShowNum(205,45,zhou,1,RED); //显示周
LCD_ShowNum(75,80,hour1,1,RED);
LCD_ShowNum(85,80,hour,1,RED); //时
LCD_ShowNum(115,80,min1,1,RED);
LCD_ShowNum(125,80,min,1,RED); //分
LCD_ShowNum(155,80,sec1,1,RED);
LCD_ShowNum(165,80,sec,1,RED); //秒
/*******dht11******/
get_temp();//读取温湿度
LCD_ShowNum(80,115,dht_t1,2,RED); //显示温度整数
LCD_ShowNum(100,115,dht_t2,1,RED); //显示湿度小数
LCD_ShowNum(180,115,dht_d1,2,RED); //显示湿度整数
LCD_ShowNum(200,115,dht_d2,1,RED); //显示湿度小数
}
}
/*********************************************************
DS1302
**********************************************************/
/*******************************************************************************
* 函 数 名 : Ds1302Write
* 函数功能 : 向DS1302命令(地址+数据)
* 输 入 : addr,dat
* 输 出 : 无
*******************************************************************************/
void Ds1302Write(u8 addr, u8 dat)
{
u8 n;
rst = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
rst = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//写入8位数据
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
rst = 0;//传送数据结束
_nop_();
}
/*******************************************************************************
* 函 数 名 : Ds1302Read
* 函数功能 : 读取一个地址的数据
* 输 入 : addr
* 输 出 : dat
*******************************************************************************/
u8 Ds1302Read(u8 addr)
{
u8 n,dat,dat1;
rst = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
rst = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
rst = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/*******************************************************************************
* 函 数 名 : Ds1302Init
* 函数功能 : 初始化DS1302.
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302Init()
{
u8 n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
/*******************************************************************************
* 函 数 名 : Ds1302ReadTime
* 函数功能 : 读取时钟信息
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302ReadTime()
{
u8 n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
/***********数据处理***********************/
void pors(void)
{
u8 dat1,dat2;
Ds1302ReadTime();
dat1=TIME[0]/16; //对秒做进制处理
dat2=TIME[0]%16;
sec=(((TIME[0]/16*10)+(TIME[0]%16)))%10;
sec1=(((TIME[0]/16*10)+(TIME[0]%16)))/10;
dat1=TIME[1]/16; //对分做进制处理
dat2=TIME[1]%16;
min=(((TIME[1]/16*10)+(TIME[1]%16)))%10;
min1=(((TIME[1]/16*10)+(TIME[1]%16)))/10;
dat1=TIME[2]/16; //对小时做进制处理
dat2=TIME[2]%16;
hour=(((TIME[2]/16*10)+(TIME[2]%16)))%10;
hour1=(((TIME[2]/16*10)+(TIME[2]%16)))/10;
dat1=TIME[3]/16; //对日做进制处理
dat2=TIME[3]%16;
ri=(((TIME[3]/16*10)+(TIME[3]%16)))%10;
ri1=(((TIME[3]/16*10)+(TIME[3]%16)))/10;
dat1=TIME[4]/16; //对月做进制处理
dat2=TIME[4]%16;
yue=(((TIME[4]/16*10)+(TIME[4]%16)))%10;
yue1=(((TIME[4]/16*10)+(TIME[4]%16)))/10;
dat1=TIME[6]/16; //对年做进制处理
dat2=TIME[6]%16;
nian=(((TIME[6]/16*10)+(TIME[6]%16)))%10;
nian1=(((TIME[6]/16*10)+(TIME[6]%16)))/10;
dat1=TIME[5]/16; //对周做进制处理
dat2=TIME[5]%16;
zhou=(((TIME[5]/16*10)+(TIME[5]%16)))%10;
zhou1=(((TIME[5]/16*10)+(TIME[5]%16)))/10;
}
/*********************************************************
DHT11
**********************************************************/
/*****************************************/
void dht_init()
{
int a;
for(a=0;a<1000;a++)
{
Delay1ms();
} //DHT11上电前准备时间,大概1s
dht_dat=1; // 总线准备
}
uchar read_date() //接收一个8位数据,先高位后低位
{
uchar i,dat;
for(i=0;i<8;i++) //循环8次,把判断有“1”输入到dat中,然后输出一个八位的数据
{
dht_num=2;
while((dht_dat==0)&&(dht_num++)); //dht_dat 数据线由DH11拉低准备发送数据
delay_10us();
delay_10us();
delay_10us();
delay_10us();
dat=dat<<1;
if(dht_dat==1)
{
dht_num=2;
dat=dat|0x01; //如果DQ的数据是高电平1,则把1放到dat的最低位
while((dht_dat==1)&&(dht_num++));
}
}
return dat;
}
void get_temp() //给DHT11一个开始信号,然后读取一次数据,共五个8位字节
{ int a;
dht_dat=0;
for(a=0;a<25;a++)
{
Delay1ms();
}
dht_dat=1; //单片机给起始脉冲信号
delay_10us();
delay_10us();
delay_10us();
delay_10us();
dht_dat=1; //稍作延时,等待DHT11返回响应(响应为低电平)
if(dht_dat==0) //有响应才接收数据,否则不处理
{
dht_num=2;
while((dht_dat==0)&&(dht_num++));
dht_num=2;
while((dht_dat==1)&&(dht_num++));
dht_d1=read_date();
dht_d2=read_date();
dht_t1=read_date();
dht_t2=read_date();
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
STC8A8K dht11 ds1302 ds18b20.zip
(207.17 KB, 下载次数: 111)
2020-5-8 23:14 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
he2997761818
时间:
2020-11-15 16:05
程序太垃圾了,
作者:
imxuheng
时间:
2023-1-31 20:14
借用了delay、DS18B20和DHT11的程序,把DHT11.c文件里面的delay(1000)函数用delay.c文件中的Delay800ms()代替,delay(25)用3个Delay10ms()代替,delay(10)用户Delay10ms()代替即可,其余的没问题,good job!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1