完整代码,最好修改下SERIAL_RX_BUFFER_SIZE 的大小。
#include <SoftwareSerial.h>
#define DHT11_PIN (5) //SCL引脚内部和ANALOG5相连,实际是PC5端口
byte dht11_dat[5]; //存储dht11的5字节数据
SoftwareSerial mySerial = SoftwareSerial(11, 12);
char ok[] = "OK";
char ipd[] = "+IPD,";
char rdy[] = "ready";
char GET[] = "GET /";
char SEND[] = ">";
int headlength;
char Header[] = "HTTP/1.1 200 OK\r\n\
Server: nginx/1.10.3 (Ubuntu)\r\n\
Date: Wed, 08 Apr 2020 09:29:22 GMT\r\n\
Content-Type: text/plain\r\n\
Content-Length: 42\r\n\
Connection: keep-alive\r\n\
Last-Modified: Tue, 18 Sep 2018 03:55:48 GMT\r\n\
Accept-Ranges: bytes\r\n\
\r\n";
void setup()
{
DDRC |= _BV(DHT11_PIN); //Data Direction Register(数据方向寄存器)
PORTC |= _BV(DHT11_PIN); //数据寄存器
mySerial.begin(9600);
mySerial.println(Header);
Serial.begin(115200);
Serial.print(F("AT+RST\r\n"));
if (waitForStr(rdy, 5000) == true)
mySerial.println(F("ready ok"));
Serial.println(F("ATE0")); //disable echo
if (waitForStr(ok, 1000) == true)
mySerial.println(F("ATE0 ok"));
Serial.println(F("AT+CWMODE=2")); //station, AP is 3
if (waitForStr(ok, 1000) == true)
mySerial.println(F("AT+CWMODE=2 ok"));
Serial.println(F("AT+CIPMUX=1"));
if (waitForStr(ok, 1000) == true)
mySerial.println(F("AT+CIPMUX=1 ok"));
Serial.println(F("AT+CIPSERVER=1,8080"));
if (waitForStr(ok, 1000) == true)
mySerial.println(F("AT+CIPSERVER=1,8080 ok"));
headlength = getStrLength(Header);
}
void loop()
{
delay(1000); //最快1s读一次传感器的数据
byte ret = read_dht11();
if (ret != 0)
{
mySerial.println("dht11 error!");
return ;
}
static char mux; //记录连接的通道号
if (waitForStr(ipd, 1000) == true) //有新的连接接入
{
mux = Serial.read(); //ipd字符串下一个字节就是连接通道号
if (waitForStr(GET, 1000) == true) //有新的GET请求
{
//组建Body
char Body[64];
int bodylength = 0;
sprintf(Body, "Current humdity = %2d.%1d%%\r\ntemperature=%2d.%1dC", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3]);
bodylength = getStrLength(Body);
//调试串口打印 组建的数据的内容及长度
//Header中的Content-Length必须设置成和这里的bodylength一样,否则浏览器不能正确解析,导致解析失败
mySerial.println(Body);
mySerial.print(F("Body length:"));
mySerial.println(bodylength);
//AT+CIPSEND=x,y 进入透传模式进行回复,x为通道号,y为要返回的数据长度
Serial.print(F("AT+CIPSEND="));
Serial.print(mux);
Serial.print(",");
Serial.println(headlength + bodylength);
if (waitForStr(SEND, 1000) == true) //出现'>'符号开始发送,发送头和体
{
Serial.print(Header);
Serial.println(Body);
if (waitForStr(ok, 10000) != true) mySerial.println(F("send timeout"));
//强制断开该连接
Serial.print(F("AT+CIPCLOSE="));
Serial.println(mux);
if (waitForStr(ok, 1000) != true) mySerial.println(F("close failed"));
}
else
{
mySerial.println(F("no >"));
}
}
else
mySerial.println(F("no GET"));
}
else
mySerial.println(F("no connect"));
}
/*---------------------------------------------------------------------------------------------------------------*/
int getStrLength(char* str) {
int i = 0;
while (str[i] != '\0') {
i++;
}
return i;
}
bool waitForStr(char* str, long timeout) {
long intime = millis();
int i = 0, j = 0, cur = 0, index = 0;
int len = getStrLength(str);
bool ret = true;
char* temp = new char(len);
while (str[i] != '\0') {
while (j - cur < len) {
if (timeout > 0)
if (millis() - intime > timeout) {
ret = false;
goto OUT;
}
if (Serial.available()) {
index = j % len;
temp[index] = Serial.read();
j++;
}
}
index = (cur + i) % len;
if (str[i] == temp[index])
i++;
else
i = 0, cur++;
}
OUT:
delete temp;
return ret;
}
/*---------------------------------------------------------------------------------------------------------------*/
/*
从DHT11中读取一个byte的数据
*/
byte read_dht11_dat()
{
byte i = 0;
byte result = 0;
for (i = 0; i < 8; i++) {
while (!(PINC & _BV(DHT11_PIN))); // wait for 50us //#define _BV(bit) (1 << (bit))
delayMicroseconds(30);
if (PINC & _BV(DHT11_PIN))
result |= (1 << (7 - i));
while ((PINC & _BV(DHT11_PIN))); // wait '1' finish
}
return result;
}
/*
从DHT11中读取一次数据
*/
byte read_dht11()
{
byte dht11_in; //存储当前端口读取的值
byte i;
// start condition
// 1. pull-down i/o pin from 18ms
PORTC &= ~_BV(DHT11_PIN); //拉低
delay(18);
PORTC |= _BV(DHT11_PIN); //拉高
delayMicroseconds(40);
DDRC &= ~_BV(DHT11_PIN);
delayMicroseconds(40);
dht11_in = PINC & _BV(DHT11_PIN);
if (dht11_in) {
//Serial.println("dht11 start condition 1 not met");
return 1;
}
delayMicroseconds(80);
dht11_in = PINC & _BV(DHT11_PIN);
if (!dht11_in) {
//Serial.println("dht11 start condition 2 not met");
return 2;
}
delayMicroseconds(80);
// now ready for data reception
for (i = 0; i < 5; i++)
dht11_dat[i] = read_dht11_dat();
DDRC |= _BV(DHT11_PIN);
PORTC |= _BV(DHT11_PIN);
byte dht11_check_sum = dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3];
// check check_sum
if (dht11_dat[4] != dht11_check_sum)
{
//Serial.println("DHT11 checksum error");
return 3;
}
return 0;
}
但是下面这个loop个人感觉是写得稍微规范些,和上面应该是差不多的,但有时候会出现浏览器等待无响应的情况。
void loop()
{
mySerial.print(F("current time:"));
mySerial.println(millis());
char Body[64];
int bodylength = 0;
delay(1000); //最快1s读一次传感器的数据
int ret = read_dht11();
if (ret != 0)
{
mySerial.print(F("dht11 error:"));
mySerial.println(ret);
return ;
}
static char mux; //记录连接的通道号
if (waitForStr(ipd, 1000) != true) //无新的连接接入,直接超时退出
{
mySerial.println(F("no connect"));
return;
}
//有新的连接,开始读取通道号,ipd字符串下一个字节就是连接通道号
mux = Serial.read();
if (waitForStr(GET, 1000) != true) //不是GET请求,直接断开连接
{
mySerial.println(F("no GET"));
goto close_ipd;
}
//组建Body
sprintf(Body, "Current humdity = %2d.%1d%%\r\ntemperature=%2d.%1dC", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3]);
bodylength = getStrLength(Body);
//调试串口打印 组建的数据的内容及长度
//Header中的Content-Length必须设置成和这里的bodylength一样,否则浏览器不能正确解析,导致解析失败
mySerial.println(Body);
mySerial.print(F("Body length:"));
mySerial.println(bodylength);
//AT+CIPSEND=x,y 进入透传模式进行回复,x为通道号,y为要返回的数据长度
Serial.print(F("AT+CIPSEND="));
Serial.print(mux);
Serial.print(",");
Serial.println(headlength + bodylength);
if (waitForStr(SEND, 1000) != true) //没有进入透传模式,一般是不会进这里的,做错误检查,但还是要释放连接
{
mySerial.println(F("no >"));
goto close_ipd;
}
//出现'>'符号开始发送,发送头和体
Serial.print(Header);
Serial.println(Body);
if (waitForStr(ok, 10000) != true) //发送超时,或者可能是数据包长度不对,退出透传模式,并断开连接
{
mySerial.println(F("send timeout"));
Serial.println("+++");
goto close_ipd;
}
close_ipd:
//强制断开该连接
Serial.print(F("AT+CIPCLOSE="));
Serial.println(mux);
if (waitForStr(ok, 1000) != true) //强制断开连接失败……怎么可能失败……
mySerial.println(F("close failed"));
}