100分,求温湿度传感器SHT11的源程序(51单片机语言)

100分,求温湿度传感器SHT11的源程序(51单片机语言),第1张

#include <reg52.h>

#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

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12347233.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存