? In the previous chapter, I showed you the functions of clock display and key adjustment. In this chapter, I will use DHT 1 1 temperature and humidity sensor to measure the ambient temperature and humidity.
The DHT 1 1 temperature and humidity sensor is digital, including 1 resistive humidity sensing element and 1 NTC temperature measuring element. It has its own AD conversion function and adopts single bus, which has the characteristics of fast response, strong anti-interference ability and high cost performance. The module has ***4 pins, two of which are power pins VCC and GND, one is data pin and the other is empty pin.
At present, the popular data transmission buses are II2C bus, SPI bus and single bus, and DHT 1 1 uses single bus to transmit data. Single bus, as its name implies, is to use a signal line to transmit clock and data at the same time. Data transmission is bidirectional, so there is a master-slave division. Here, stm32 is the master as the core controller, and DHT 1 1 is the slave. Using single bus for data transmission, you need to look at the timing chart of the data manual. ?
The bus idle state is high, and the host pulls down the bus and waits for the response of DHT 1 1. The host must pull down the bus for more than18ms to ensure that the startup signal can be detected by DHT 1 1. DHT 1 1 After receiving the startup signal of the host, wait for the startup signal of the host to end, and then send a low-level response signal of 80us. The response signal of DHT 1 1 is read after a delay of 20-40us. After the host sends a start signal, it can switch to the input mode or output a high-power average bus.
According to the timing diagram, the microcontroller should at least pull down the bus 18ms and then pull up the bus for 20~40us. At this point, the start signal of the host computer is over, and the response signal of DHT 1 1 is detected. If a low level is detected, DHT 1 1 responds, and the low level lasts for 80us, then DHT 1 1 pulls the bus high for 80us. At this time, DHT 1 1 is ready to transmit data, and the gap between data transmission is 50us low level. The transmitted data can be distinguished between "0" and "1" by the length of high level. After data transmission, DHT 1 1 pulls down the bus for 50us, and finally the host pulls up the bus again.
(1) write delay function
Because the time sequence of DHT 1 1 is strict, it needs millisecond delay and subtle delay. Here we use Systick to realize the delay. Delay has also been used in the previous key scanning function, so I will describe it here.
We need to configure the system clock, and then set the Systick to 72 to generate the time reference of 1us. Secondly, we need to write the Systick interrupt handler to reduce the variables themselves, so as to achieve the effect of delay. Finally, we need to write the delay function, that is, assign an initial value to the variable that we reduce.
_ _ IO uint32 _ t TimingDelay
/* Configure the SysTick function */
void systick_init(void)
{
/* Configure the Systick overload value, and the system clock is 72MHz*/
/* setting 72, interruption time: 72 * (1/72000000) =1us */
If (sy stick _ Config (72) =1)//If the systick _ config function returns an interrupt signal, the return value is 0.
{
while( 1); ? //The return value of the //SysTick_Config function is 1, so wait.
}
}
/* Time-varying self-decreasing function */
void TimingDelay_Decrement(void)
{
if(TimingDelay! =0x00)
{
timing delay-;
}
}
/*SysTick interrupt handler */
void SysTick_Handler(void)
{
timing delay _ Decrement();
}
/* Delay function, with time reference of 1ms*/
Invalid delay _ ms (_ _ iount32 _ t time)
{
timing delay = nTime * 1000;
while(TimingDelay! =0);
}
/* Delay function, time reference is 1us*/
Invalid delay _ us (_ _ iount32 _ ttime)
{
TimingDelay = nTime
while(TimingDelay! =0);
}
(2) Configure the corresponding GPIO port as a single bus data terminal.
/* Configure the DHT 1 1 data pin and set it to floating-point input mode */
void DHT 1 1 _ gpio _ portIn(void)
{
GPIO _ init typedef GPIO _ init structure;
RCC _ APB2 PeriphClockcmd (RCC _ APB2 PERIPH _ GPIOA, enabled);
GPIO_InitStructure。 GPIO _ Pin = GPIO _ Pin _ 4;
GPIO_InitStructure。 GPIO _ Mode = GPIO _ Mode _ IN _ FLOATING;
GPIO_InitStructure。 GPIO _ Speed = GPIO _ Speed _ 50MHz
GPIO _ Init(GPIOA & amp; GPIO _ init structure);
}
/* Configure DHT 1 1 data pin and set it to push-pull output mode */
void DHT 1 1 _ gpio _ port out(void)
{
GPIO _ init typedef GPIO _ init structure;
RCC _ APB2 PeriphClockcmd (RCC _ APB2 PERIPH _ GPIOA, enabled);
GPIO_InitStructure。 GPIO _ Pin = GPIO _ Pin _ 4;
GPIO_InitStructure。 GPIO _ Mode = GPIO _ Mode _ Out _ PP
GPIO_InitStructure。 GPIO _ Speed = GPIO _ Speed _ 50MHz
GPIO _ Init(GPIOA & amp; GPIO _ init structure);
}
Since DHT 1 1 adopts the single bus communication protocol and data transmission is bidirectional, the data ports are set to the floating input mode and the push-pull output mode respectively. And the input and output of the data port are defined as macro definitions.
# define DHT 1 1 _ OUT _ H GPIO _ set bits(GPIO a,GPIO_Pin_4)
# define DHT 1 1 _ OUT _ L GPIO _ reset bits(GPIO a,GPIO_Pin_4)
# define DHT11_ inpio _ readinputdatabit (gpioa, GPIO_Pin_4).
(3) According to DHT 1 1 timing chart, the time series function is written.
Now, let's write the bus driver function. According to the timing diagram, the host sends a command to start conversion, then waits for the conversion response of DHT 1 1 and outputs data, and finally reads the data.
/* Start the bus function */
void DHT 1 1 _ reset(void)
{
DHT 1 1 _ gpio _ port out(); //Set to output mode
DHT 1 1 _ OUT _ L; ? //The host pulls the bus low at least 18ms.
delay _ ms( 18);
DHT 1 1 _ OUT _ H; ? //The main engine is pulled up for 20~40us.
delay _ us(30);
DHT 1 1 _ gpio _ portIn(); ? //Set to input mode and wait for DHT 1 1 to respond.
}
/*DHT 1 1 response function */
u8 dht 1 1_scan(void)
{
Returns DHT11_ in; ? //Response signal with return value of DHT 1 1
}
Monitor the data line of DHT 1 1 in real time until a low level is generated, indicating that DHT 1 1 responds to the host request and starts to transmit data.
/*DHT 1 1 read bit function */
u8 DHT 1 1 _ read _ bit(void)
{
while(DHT 1 1 _ IN = = RESET); //There is a low level of 50us before the data bit is transmitted.
delay _ us(40); ? //Determines whether the level is 1 or 0 according to the high level duration.
if(DHT 1 1_IN==SET)? //"0" level duration is 26 ~ 28 us, and "1" level duration is 70us.
{
while(DHT 1 1 _ IN = = SET);
Returns1; ? //If high level is detected, the return value is 1.
}
other
{
Returns 0; ? //If a high level is detected, the return value is 0.
}
}
/*DHT 1 1 byte reading function */
//Note: most significant bit is the first to transmit data.
u8 DHT 1 1 _ read _ byte(void)
{
u8 i,dat = 0x00
for(I = 0; I<8; i++)
{
dat = dat & lt& lt 1;
dat = dat | DHT 1 1 _ read _ bit(); //Read serial data.
}
Return dat
}
When DHT 1 1 responds, it starts to transmit data through the single bus. In the bit reading function, it is judged whether the output is'1'or' 0' by the time of high level. In the read byte function, call the read bit function to integrate the data transmitted every 8 bits into bytes and read them out.
We refer to the DHT 1 1 data manual and know the structure of data transmission (in order): humidity integer part (1 byte), humidity decimal part (1 byte), temperature integer part (1 byte) and temperature decimal part (/kloc) Here, it is actually a simple communication protocol. The checksum is the lower 8 bits of the sum of all bytes of the source data, which ensures the correctness and stability of the transmitted data.
/*DHT 1 1 data reading function */
u8 DHT 1 1 _ read _ data(void)
{
u8i;
DHT 1 1 _ reset();
If (DHT11_ scan () = = reset)//DHT1/sends a response signal.
{
while(DHT 1 1 _ IN = = RESET); //DHT 1 1 pull down the bus 80us.
while(DHT 1 1_IN! = reset); //DHT 1 1 Pull up the bus 80us.
for(I = 0; I<5; i++)
{
buffer[I]= DHT 1 1 _ read _ byte();
}
while(DHT 1 1 _ IN = = RESET); //After sending the last 1 bit data, wait for 50us low level to end.
DHT 1 1 _ gpio _ port out();
DHT 1 1 _ OUT _ H; //The host pulls the bus high.
If (buffer [0]+ buffer [1]+ buffer [2]+ buffer [3]= = buffer [4])
{
Returns1; ? //Verification succeeded.
}
other
{
Returns 0; ? //Verification failed.
}
}
other
{
Returns 0; ? //DHT 1 1 did not send a response signal.
}
}
In the read byte, wait for the response of DHT 1 1, and then start to receive data, and read it five times in a row and store it in a predefined array. The host sends an end signal and finally checks the read data.
(4) Measuring and displaying temperature and humidity
The main function calls data reading function DHT 1 1 and lcd display function to display temperature and humidity.
If (DHT 1 1 _ read _ data () =1)/reads the data, provided that DHT1/responds and the data is verified successfully.
{
Humidity = buffer [0]; //buffer[0] stores the integer part of humidity.
Temperature = buffer [2]; //buffer[2] stores the integer part of the temperature.
}
LCD _ display _ string (2,0, "temperature");
LCD _ display _ num _ m (2,32, temperature/10);
LCD _ display _ num _ m (2,40, temperature%10);
LCD _ display _ string (4,0, "humidity");
LCD _ display _ num _ m (4,32, humidity/10);
LCD _ display _ num _ m (4,40, humidity%10);
At this point, through the explanation of this chapter, I believe everyone should have a general understanding of DHT 1 1 module. Of course, if you just read the article, the effect may not be ideal. These things need hands-on. As the saying goes, "Practice makes perfect." So, you can buy development boards and some modules online, not necessarily the same as mine. Of course, if you want to challenge yourself, you can buy a minimum system board, so that the peripheral hardware circuit can be built by yourself (the function is customized), which is flexible and exercises your hands-on ability. If you are a big boss who can design PCB, so much the better. To estimate your level, just browse my article.