dsp28335+dht11+matlab实时绘制温湿度(3种取数据方式)
·
1.dht11基础
1.1单线通信
设备(主机或从机)通过一个一个漏极开路或三态端口连接至该数据线,以允许设备在不发送数据时能够释放总线,而让其他设备使用总线。——GPBPUD=0——DSP使能上拉。
1.2数据位定义
一次传送40位数据,高位先出。数据格式:

1.3 数据时序图

关于电平时间的定义

2.外设的读取步骤

步骤1:等待

gpio40_init();
EALLOW;
DAT_DIR=0;//输入
EDIS;
for(i=0;i<2000;i++) //等待稳定
DELAY_US(1000);
步骤2:起始信号

void DHT11_Rst(void)
{
uchar i;
EALLOW;
DAT_DIR=1;//输出
EDIS;
DAT = 0; //拉低DQ
for(i=0;i<25;i++) //18-30ms
DELAY_US(1000);
DAT = 1;
DELAY_US(30);//主机拉高20~40us释放总线
}
步骤3:CHECK

Uint16 Dht11_Check(void){ //等待DHT11回应,返回1:未检测到DHT11,返回0:成功(IO接收)
Uint16 retry=0;
EALLOW;
DAT_DIR=0;
EDIS;//IO到输入状态
//找DHT11发出的低电平
while (DAT&&retry<100){//DHT11会拉低78~88us
retry++;
DELAY_US(1);
}
if(retry>=100)return 1; else retry=0;
//找DHT11发出的高电平
while (!DAT&&retry<100){//DHT11拉低后会再次拉高80~92us
retry++;
DELAY_US(1);
}
if(retry>=100)return 1;
return 0;
}
总的DHT11初始化程序
Uint16 DHT11_Init (void){ //DHT11初始化
DHT11_Rst();//DHT11端口复位,发出起始信号
return Dht11_Check(); //等待DHT11回应
}
步骤4:读数据


读Bit
法1:——延时检测高电平
uchar Dht11_ReadBit(void){ //从DHT11读取一个位 返回值:1/0
uchar retry=0;
while(DAT&&retry<100){//等待变为低电平(54us前边那段)
retry++;
DELAY_US(1);
}
retry=0;
while(!DAT&&retry<100){//等待变高电平
retry++;
DELAY_US(1);
}
DELAY_US(40);//等待40us //用于判断高低电平,即数据1或0
if(DAT)return 1; else return 0;
}
法2:——判断高电平时间
uchar Dht11_ReadBit(void){ //从DHT11读取一个位 返回值:1/0
uchar retry=0;
while(DAT&&retry<100){//等待变为低电平(54us前边那段)
retry++;
DELAY_US(1);
}
retry=0;
while(!DAT&&retry<60){//等待54us的低电平
retry++;
DELAY_US(1);
}
retry=0;
while(DAT)
{
retry++;
DELAY_US(1);
}
if(40<retry)return 1; else return 0;//高电平维持的时间跟手册有出入。
}
//***************************甚至你可以这样写*********************************//
uchar Dht11_ReadBit(void){ //从DHT11读取一个位 返回值:1/0
uchar retry=0;
while(DAT){//等待变为低电平
}
while(!DAT){//等待变高电平
}
while(DAT)
{
retry++;
DELAY_US(1);
}
if(40<retry)return 1; else return 0;
}
读湿度+温度字节
法1——用的是全局变量temp[4]
dht11.h
extern char temp[4];
//***********************全局变量*******************//
dht11.c
#include "dht11.h"
char temp[4];
void DHT11_ReadData(void){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
uchar buf[5];
uchar i;
DHT11_Rst();//DHT11端口复位,发出起始信号
if(Dht11_Check()==0){ //等待DHT11回应
for(i=0;i<5;i++){//读取5位数据
buf[i]=Dht11_ReadByte(); //读出数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){ //数据校验
temp[0]=buf[0]; //将湿度值放入指针1
temp[1]=buf[1];
temp[2]=buf[2]; //将温度值放入指针2
temp[3]=buf[3];
}
}
}
main.c
DHT11_ReadData();
hum=temp[0]*1;
tep=10*(temp[2]*1+0.1*temp[3]);
int_char(hum,tep);
UARTa_SendString(table);
法2——用的是数组指针
char *s;
char a[ ] ;
前面说到 a代表字符串的首地址,而s 这个指针也保存字符串的地址(其实首地址),即第一个字符的地址,这个地址单元中的数据是一个字符,
可以 s = a
当然也可以这样:
char a [ ] = "hello";
char *s =a;
for(int i= 0; i < strlen(a) ; i++)
printf("%c", s[i]);
或 printf("%c",*s++);
当定义 char a[10 ] 时,编译器会给数组分配十个单元,每个单元的数据类型为字符。
而定义 **char *s 时, 这是个指针变量,只占四个字节,32位,**用来保存一个地址。
也就是说如果char msg;那么msg是一个指针变量,占有4个字节。取值赋值msg;msg++;或者msg[1],msg[2]
void DHT11_ReadData1(uchar *msg1){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
uchar buf[5];
uchar i;
DHT11_Rst();//DHT11端口复位,发出起始信号
if(Dht11_Check()==0){ //等待DHT11回应
for(i=0;i<5;i++){//读取5位数据
buf[i]=Dht11_ReadByte(); //读出数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){ //数据校验
*msg1 = buf[0]; //将湿度值放入指针1
msg1++;
*msg1 = buf[1];
msg1++;
*msg1=buf[2]; //将温度值放入指针2
msg1++;
*msg1=buf[3];
}
}
}
***********************main.c**********************
DHT11_ReadData2(msg);
temp[0]=msg[0];
temp[2]=msg[2];
temp[3]=msg[3];
hum=temp[0]*1;
tep=10*(temp[2]*1+0.1*temp[3]);
int_char(hum,tep);
UARTa_SendString(table);
法3——用的是msg[1]
void DHT11_ReadData2(uchar *msg1){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
uchar buf[5];
uchar i;
DHT11_Rst();//DHT11端口复位,发出起始信号
if(Dht11_Check()==0){ //等待DHT11回应
for(i=0;i<5;i++){//读取5位数据
buf[i]=Dht11_ReadByte(); //读出数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){ //数据校验
msg1[0] = buf[0]; //将湿度值放入指针1
msg1[1] = buf[1];
msg1[2]=buf[2]; //将温度值放入指针2
msg1[3]=buf[3];
}
}
}
3.总的DSP程序
main.c
#include "DSP2833x_Device.h" // DSP2833x 头文件
#include "DSP2833x_Examples.h" // DSP2833x 例子相关头文件
#include "dht11.h"
#include "time.h"
#include "uart.h"
#include "leds.h"
char table[14];
uchar Z_F_judge(char a);
void int_char(int a,int b);
void main(void)
{
uchar i;
uchar * msg;
Uint16 hum;
Uint16 tep;
InitSysCtrl();
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
gpio40_init();
EALLOW;
DAT_DIR=0;//输入
EDIS;
LED_Init();
TIM0_Init(150,200000);//200ms
UARTa_Init(9600);
for(i=0;i<2000;i++) //等待稳定
DELAY_US(1000);
while(1)
{
//使用DHT11_ReadData();
#if 1
DHT11_ReadData();
hum=temp[0]*1;
tep=10*(temp[2]*1+0.1*temp[3]);
int_char(hum,tep);
UARTa_SendString(table);
#endif
//使用DHT11_ReadData2(uchar *msg)或者DHT11_ReadData1(uchar *msg)
#if 0
DHT11_ReadData2(msg);
temp[0]=msg[0];
temp[2]=msg[2];
temp[3]=msg[3];
hum=temp[0]*1;
tep=10*(temp[2]*1+0.1*temp[3]);
int_char(hum,tep);
UARTa_SendString(table);
#endif
}
}
//生成要发送的字符串
void int_char(int a,int b)
{
int tt1,tt2;
uchar m;
tt1=a;
tt2=b;
m=Z_F_judge(temp[3]);
if(!m)
table[5]=('-');
else
table[5]=(' ');
table[0]=tt1/10+0x30; //湿度十位
table[1]=tt1%10+0x30;//个位
table[2]=0x25;//%
table[3]='r';
table[4]='h';
table[6]=tt2/100+0x30; //温度十位
table[7]=tt2%100/10+0x30;//个位
table[8]='.';
table[9]=tt2%100%10+0x30;//小数
table[10]='C';
table[11]='\r';//r回车n换行0结束
table[12]='\n';//换行
table[13]='\0';//表明字符串的结束
}
//温度正负判断函数
uchar Z_F_judge(char a)
{
char b;
b=a&0xf0;
if(b == 0x01)
return 0;
else
return 1;
}
dht11.c
#include "dht11.h"
char temp[4];
void gpio40_init(void)
{
EALLOW;
GpioCtrlRegs.GPBPUD.bit.GPIO40 = 0; // 使能GPIO10 引脚内部上拉
GpioCtrlRegs.GPBMUX1.bit.GPIO40 =0; // 配置GPIO10为通用I/O口
GpioCtrlRegs.GPBQSEL1.bit.GPIO40 = 0; // GPIO40与系统时钟SYSCLKOUT 同步
EDIS;
}
void DHT11_Rst(void)
{
uchar i;
EALLOW;
DAT_DIR=1;//输出
EDIS;
DAT = 0; //拉低DQ
for(i=0;i<25;i++) //18-30ms
DELAY_US(1000);
DAT = 1;
DELAY_US(30);//主机拉高20~40us
}
Uint16 Dht11_Check(void){ //等待DHT11回应,返回1:未检测到DHT11,返回0:成功(IO接收)
Uint16 retry=0;
EALLOW;
DAT_DIR=0;
EDIS;//IO到输入状态
while (DAT&&retry<100){//DHT11会拉低40~80us
retry++;
DELAY_US(1);
}
if(retry>=100)return 1; else retry=0;
while (!DAT&&retry<100){//DHT11拉低后会再次拉高40~80us
retry++;
DELAY_US(1);
}
if(retry>=100)return 1;
return 0;
}
Uint16 DHT11_Init (void){ //DHT11初始化
DHT11_Rst();//DHT11端口复位,发出起始信号
return Dht11_Check(); //等待DHT11回应
}
uchar Dht11_ReadBit(void){ //从DHT11读取一个位 返回值:1/0
uchar retry=0;
while(DAT){//等待变为低电平
// retry++;
//DELAY_US(1);
}
// retry=0;
while(!DAT){//等待变高电平
// retry++;
// DELAY_US(1);
}
// retry=0;
while(DAT)
{
retry++;
DELAY_US(1);
}
if(40<retry)return 1; else return 0;
}
uchar Dht11_ReadByte(void){ //从DHT11读取一个字节 返回值:读到的数据
uchar i,dat;
dat=0;
for (i=0;i<8;i++){
dat<<=1;
dat|=Dht11_ReadBit();
}
return dat;
}
void DHT11_ReadData(void){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
uchar buf[5];
uchar i;
DHT11_Rst();//DHT11端口复位,发出起始信号
if(Dht11_Check()==0){ //等待DHT11回应
for(i=0;i<5;i++){//读取5位数据
buf[i]=Dht11_ReadByte(); //读出数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){ //数据校验
temp[0]=buf[0]; //将湿度值放入指针1
temp[1]=buf[1];
temp[2]=buf[2]; //将温度值放入指针2
temp[3]=buf[3];
}
}
}
void DHT11_ReadData1(uchar *msg1){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
uchar buf[5];
uchar i;
DHT11_Rst();//DHT11端口复位,发出起始信号
if(Dht11_Check()==0){ //等待DHT11回应
for(i=0;i<5;i++){//读取5位数据
buf[i]=Dht11_ReadByte(); //读出数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){ //数据校验
*msg1 = buf[0]; //将湿度值放入指针1
msg1++;
*msg1 = buf[1];
msg1++;
*msg1=buf[2]; //将温度值放入指针2
msg1++;
*msg1=buf[3];
}
}
}
void DHT11_ReadData2(uchar *msg1){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
uchar buf[5];
uchar i;
DHT11_Rst();//DHT11端口复位,发出起始信号
if(Dht11_Check()==0){ //等待DHT11回应
for(i=0;i<5;i++){//读取5位数据
buf[i]=Dht11_ReadByte(); //读出数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){ //数据校验
msg1[0] = buf[0]; //将湿度值放入指针1
msg1[1] = buf[1];
msg1[2]=buf[2]; //将温度值放入指针2
msg1[3]=buf[3];
}
}
}
dht11.h
#ifndef APP_DHT11_DHT11_H_
#define APP_DHT11_DHT11_H_
#include "DSP2833x_Device.h" // DSP2833x 头文件
#include "DSP2833x_Examples.h" // DSP2833x 例子相关头文件
#define uchar unsigned char
#define DAT_DIR GpioCtrlRegs.GPBDIR.bit.GPIO40 //方向1为输出,0为输入
#define DAT GpioDataRegs.GPBDAT.bit.GPIO40//数值
extern char temp[4];
void gpio40_init(void);
void DHT11_Rst(void);
Uint16 Dht11_Check(void);
Uint16 DHT11_Init (void);
uchar Dht11_ReadBit(void);
void DHT11_ReadData(void);//三种方法取数据
void DHT11_ReadData1(uchar * msg1);
void DHT11_ReadData2(uchar *msg1);
#endif /* APP_DHT11_DHT11_H_ */
4.MATLAB脚本
main.m
clear all;
delete(instrfindall)
clear obj1
global obj1;
global data;
global sendbuff;
global data1;
global data2;
global data3;
global data4;
global data5;
global dian_ya;
global wen_du;
global shi_du;
global x;%用于画图
global y;
x=0;
y=0;
dian_ya=0;
wen_du=0;
shi_du=0;
data1=0;
data2=0;
data3=0;
data4=0;
data5=0;
global n;
n=0;
data = zeros(5,1);
sendbuff = zeros(1,8);
obj1 = serial('com8');%需要修改
fclose(obj1);
set(obj1, 'InputBufferSize', 100);
set(obj1, 'OutputBufferSize', 100);
set(obj1, 'BaudRate', 9600);
set(obj1, 'Timeout', 15.0);
set(obj1,'BytesAvailableFcnMode','terminator');
set(obj1,'terminator',10);
set(obj1,'BytesAvailableFcn',@my_callback1);
fopen(obj1);
my_callback1
function my_callback1(obj1,event)
global data;
global data1;
global data2;
global data3;
global data4;
global data5;
global dian_ya;
global wen_du;
global shi_du;
global x;
global y;
data = fread(obj1 , 14);%取决于发送的数组大小,真实的个数(1,9)
if length(data)==14
if data(3)=='%'
data1=data(1)-48;%减48就是去掉0x30;
data2=data(2)-48;
data3=data(7)-48;
data4=data(8)-48;
data5=data(9)-48;
shi_du=10*data1+data2;
wen_du=10*data3+1*data4+0.1*data5;
end
end
disp(shi_du);
disp(wen_du);
x = [x shi_du];
y = [y wen_du];
plot(x,'r');
hold on;
plot(y,'g');
axis([0 inf 27 100]);
title('From Dsp');
xlabel('Sample');
ylabel('Result');
drawnow;
end
draw_total.main
clc;
t=1:length(x);
plot(t,x)
hold on;
plot(t,y);
legend('湿度','温度');
axis([0 inf 27 100]);
title('From Dsp');
xlabel('Sample');
ylabel('Result');
draw_total运行的figure

更多推荐



所有评论(0)