#define uchar unsigned char
#define uint unsigned int
//数码管位定义
sbit dula = P2^6
sbit wela = P2^7
#define OK 1
#define ERROR 0
#define NUMBER 20
#define SIZE 5
sbit dht11 = P2^0
uchar status
//存放五字节数据的数组
uchar value_array[SIZE]
/*可在其他的文件引用温湿度值,实际是温度的整数的10 倍
如dht11 读回的温度是26,则temp_value = 260, 湿度同理*/
uchar flag
//数码管编码
uchar code array[]= {
0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f
}
int temp_value, humi_value
void InitTime(void)
//void Delay_1ms(uint ms)
void SMG_Display(uint value)
void Delay_1ms(uint ms)
{
uint x, y
for(x = msx >0x--)
{
for(y = 124y >0y--)
}
}
void Delay_10us(void)
{
unsigned char i
i--
i--
i--
i--
i--
i--
}
/*读一个字节的数据*/
uchar ReadValue(void)
{
uchar count, value = 0, i
status = OK//设定标志为正常状态
for(i = 8i >0i--)
{
//高位在先
value <<= 1
count = 0
/做历宏/每一位数据前会有一个50us 的低电平时间.等待50us 低电平结束
while(dht11 == 0 &&count++ <NUMBER)
if(count >= NUMBER)
{
status = ERROR//设定错误标志
return 0//函数执行过程发生错误就退出函数
}
//26-28us 的高电平表示该位是0,为70us 高电平表该位1
Delay_10us()
Delay_10us()
Delay_10us()
//延时30us 后检测数据线是否还是高电平烂如
if(dht11 != 0)
{
//进入这里表示该位是1
value++
//等待剩余(约40us)的高电平结束
while(dht11 != 0 &&count++ <NUMBER)
{
dht11 = 1
}
if(count >= NUMBER)
{
status = ERROR//设定错误标志
return 0
}
}
}
return (value)
}
//读一次的数据,共五字节
uchar ReadTempAndHumi(void)
{
uchar i = 0, check_value = 0,count = 0
EA = 0
dht11 = 0//拉低数据线大于18ms 发送开始信号
Delay_1ms(20)//需大于18 毫纯册秒
dht11 = 1//释放数据线,用于检测低电平的应答信号
//延时20-40us,等待一段时间后检测应答信号,应答信号是从机拉低数据线80us
Delay_10us()
Delay_10us()
Delay_10us()
Delay_10us()
if(dht11 != 0) //检测应答信号,应答信号是低电平
{
//没应答信号
EA = 1
return ERROR
}
else
{
//有应答信号
while(dht11 == 0 &&count++ <NUMBER)//等待应答信号结束
if(count >= NUMBER) //检测计数器是否超过了设定的范围
{
dht11 = 1
EA = 1
return ERROR//读数据出错,退出函数
}
count = 0
dht11 = 1//释放数据线
//应答信号后会有一个80us 的高电平,等待高电平结束
while(dht11 != 0 &&count++ <NUMBER)
if(count >= NUMBER)
{
dht11 = 1
EA = 1
return ERROR//退出函数
}
//读出湿.温度值
for(i = 0i <SIZEi++)
{
value_array[i] = ReadValue()
if(status == ERROR)//调用ReadValue()读数据出错会设定status 为ERROR
{
dht11 = 1
EA = 1
return ERROR
}
//读出的最后一个值是校验值不需加上去
if(i != SIZE - 1)
{
//读出的五字节数据中的前四字节数据和等于第五字节数据表示成功
check_value += value_array[i]
}
}//end for
//在没用发生函数调用失败时进行校验
if(check_value == value_array[SIZE - 1])
{
//将温湿度扩大10 倍方便分离出每一位
humi_value = value_array[0] * 10
temp_value = value_array[2] * 10
dht11 = 1
EA = 1
return OK//正确的读出dht11 输出的数据
}
else
{
//校验数据出错
EA = 1
return ERROR
}
}
}
void main(void)
{
uchar mark = 0
//先等上电稳定
Delay_1ms(1000)
//因为读一次数据dht11 才会触发一次采集数据.
//即在先使用数据时采集一次数据
ReadTempAndHumi()
//因为在两次采集数据需一定的时间间隔,这里还可减少
Delay_1ms(3000)
//设定定时器
InitTime()
while(1)
{
//三秒读一次温湿度
if(flag == 60)
{
flag = 0
mark++
/*
//读温湿度,可检测函数调用是否失败,
//函数返回OK(1)表示成功,返回ERROR(0)表示失败
//OK和ERROR是在DHT11.H中定义的宏
*/
ReadTempAndHumi()
}
if(mark % 2 == 0)
{
//显示温度
SMG_Display(temp_value)
}
else
{
//显示湿度
SMG_Display(humi_value)
}
}
}
//设定定时器
void InitTime(void)
{
TH0 = (65535 - 50000)/256
TL0 = (65535 - 50000)%256
TMOD = 0X01
TR0 = 1
ET0 = 1
EA = 1
}
//数码管显示函数
void SMG_Display(uint value)
{
uchar ge, bai, shi
ge = value % 10
shi = value % 100 / 10
bai = value % 1000 / 100
wela=1
P0 = 0XFE
wela=0
P0 = 0XFF
dula=1
P0 = array[bai]
dula=0
Delay_1ms(2)
wela=1
P0 = 0XFD
wela=0
P0 = 0XFF
dula=1
P0 = array[shi]
P0 |= 0x80/*显示小数点*/
dula=0
Delay_1ms(2)
wela=1
P0 = 0XFB
wela=0
P0 = 0XFF
dula=1
P0 = array[ge]
dula=0
Delay_1ms(2)
}
//中断函数
void timer(void) interrupt 1
{
TH0 = (65535 - 50000)/256
TL0 = (65535 - 50000)%256
flag++
}
用显旅胡卡(1)、DHT11和DHT21供电范围都是3V~5.5V,对于STM32单片机,我们VDD引脚接3.3V即可;
(2)、DHT11的手册中说,SDA数据引脚接线长度短于20米时,用5K上拉电阻。大于20米兆镇誉时根据实际情况使用合适的上拉电阻;
(3)、DHT11上电后,需要等待1s以越过不稳定状态,在此期间无需发现任何族段指令;本人尝试上电即读取,返回温湿度值都为0,1S以后温湿度值即可恢复正常;
(4)、电源引脚(VDD,GND)之间可增加一个100nF的电容,用以去耦滤波。
几点说明:
1.主要是分以下几个模块写的:SHT10,LCD1602,主函数,头文件。
2.每支SHTxx传感器都在25℃(77 °F)和 3.3V条件下进行过标定并且完全符合精度指标.因为考虑到实际硬件5V的电压比较好 *** 作,所以SHT10用的精度采用的为5V时的参数。其他的都采取默认值(14bit湿度, 12bit 温度)。
3.SHT10中所以部分我都编颤源余写了。有的部分在本次程序中没用到,也可以作为参考。
4.所有程序都已经加了注释,且有仿真图。
5.个人认为还可以在此基础上添加个中断。
6.程序编写keil 4 ,仿真 protues7.5
/***********************************************************************************************************************************************************/
头文件(tou.h):
#ifndef __TOU_H__
#define __TOU_H__
#include<reg52.h>
#include <intrins.h>
//#include <math.h> //Keil library
#define uchar unsigned char
enum {TEMP,HUMI}
sbit DATA = P1^7
sbit SCK = P1^6
sbit LcdRs = P2^4
sbit LcdRw = P2^5
sbit LcdEn = P2^6
sfr DBPort = 0x80 //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
/******** DS1602函数声明 ********/
void LCD_Initial()
void GotoXY(unsigned char x, unsigned chary)
void Print(unsigned char *str)
void LCD_Write(bit style, unsigned charinput)
/******** SHT10函数声明 ********/
void s_connectionreset(void)
char s_measure(unsigned char *p_value,unsigned char *p_checksum, unsigned char mode)
void calc_sth10(float *p_humidity ,float*p_temperature)
//float calc_dewpoint(float h,float t)
#endif
/***********************************************************************************************************************************************************/
SHT10程序(SHT10.c):
#include<tou.h>
#define noACK 0 //继续传输数据,用于判断是否结束通讯
#define ACK 1 //结束数据传输;
//地址 命令 读/写
#define STATUS_REG_W 0x06 //000 0011 0
#define STATUS_REG_R 0x07 //000 0011 1
#define MEASURE_TEMP 0x03 //000 0001 1
#define MEASURE_HUMI 0x05 //000 0010 1
#define RESET 0x1e //000 1111 0
//写字节程序
char s_write_byte(unsigned char value)
{
unsignedchar i,error=0
for(i=0x80i>0i>>=1) //高位为1,循环右移
{
if(i&value) DATA=1 //和要发送的数相与,结果为发送的位
else DATA=0
SCK=1
_nop_()_nop_()_nop_() //延时3us
SCK=0
}
DATA=1 裂漏 //释放数据线
SCK=1 茄滚
error=DATA //检查应答信号,确认通讯正常
_nop_()_nop_()_nop_()
SCK=0
DATA=1
returnerror //error=1 通讯错误
}
//读字节程序
char s_read_byte(unsigned char ack)
//----------------------------------------------------------------------------------
{
unsignedchar i,val=0
DATA=1 //释放数据线
for(i=0x80i>0i>>=1) //高位为1,循环右移
{
SCK=1
if(DATA) val=(val|i) //读一位数据线的值
SCK=0
}
DATA=!ack //如果是校验,读取完后结束通讯;
SCK=1
_nop_()_nop_()_nop_() //延时3us
SCK=0
_nop_()_nop_()_nop_()
DATA=1 //释放数据线
returnval
}
//启动传输
void s_transstart(void)
// generates a transmission start
// _____ ________
// DATA: |_______|
// ___ ___
// SCK : ___| |___| |______
{
DATA=1SCK=0 //准备
_nop_()
SCK=1
_nop_()
DATA=0
_nop_()
SCK=0
_nop_()_nop_()_nop_()
SCK=1
_nop_()
DATA=1
_nop_()
SCK=0
}
//连接复位
void s_connectionreset(void)
// communication reset: DATA-line=1 and atleast 9 SCK cycles followed by transstart
// _____________________________________________________ ________
// DATA: |_______|
// _ _ _ _ _ _ _ _ _ ___ ___
// SCK : __| |__| |__| |__| |__| |__| |__||__| |__| |______| |___| |______
{
unsignedchar i
DATA=1SCK=0 //准备
for(i=0i<9i++) //DATA保持高,SCK时钟触发9次,发送启动传输,通迅即复位
{
SCK=1
SCK=0
}
s_transstart() //启动传输
}
//软复位程序
char s_softreset(void)
// resets the sensor by a softreset
{
unsignedchar error=0
s_connectionreset() //启动连接复位
error+=s_write_byte(RESET) //发送复位命令
returnerror //error=1 通讯错误
}
/*读状态寄存器
char s_read_statusreg(unsigned char*p_value, unsigned char *p_checksum)
//----------------------------------------------------------------------------------
// reads the status register with checksum(8-bit)
{
unsignedchar error=0
s_transstart() //transmission start
error=s_write_byte(STATUS_REG_R)//send command to sensor
*p_value=s_read_byte(ACK) //read status register (8-bit)
*p_checksum=s_read_byte(noACK) //read checksum (8-bit)
returnerror //error=1 incase of no response form the sensor
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)