This is an old revision of the document!
Your approach to implementing the microsecond delay function using a loop and the `nop` instruction is valid. The `nop` (no operation) instruction typically consumes one CPU cycle, making it a straightforward way to create delays based on the CPU frequency.
Here is the updated function including your `delay_uSec` implementation:
#include "stm32f1xx_hal.h" #define DHT11_PIN GPIO_PIN_0 #define DHT11_PORT GPIOA void _delay_uSec(unsigned int i) { for (; i > 0; i--) { // 'i' = the uSeconds needed to delay for (int j = 0; j < 72; ++j) { // the 72 being the frequency in MHz the MCU is running __asm__ __volatile__("nop\n\t":::"memory"); } } } void DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // Configure the GPIO pin as output GPIO_InitStruct.Pin = DHT11_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(DHT11_PORT, &GPIO_InitStruct); } void DHT11_StartSignal(void) { // Pull the pin low for at least 18 ms HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET); HAL_Delay(18); // Pull the pin high for 20-40 us HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET); _delay_uSec(30); // Change the pin to input mode GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DHT11_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(DHT11_PORT, &GPIO_InitStruct); } uint8_t DHT11_ReadByte(void) { uint8_t byte = 0; for (int i = 0; i < 8; i++) { // Wait for the start of the bit while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET); // Wait for 30-40 us to read the bit value _delay_uSec(35); // Read the bit value if (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET) { byte |= (1 << (7 - i)); } // Wait for the end of the bit while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET); } return byte; } void DHT11_ReadData(uint8_t* temperature, uint8_t* humidity) { DHT11_StartSignal(); // Wait for the response signal from the DHT11 while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET); while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET); while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET); // Read the 40-bit data uint8_t data[5] = {0}; for (int i = 0; i < 5; i++) { data[i] = DHT11_ReadByte(); } // Extract the temperature and humidity values *humidity = data[0]; *temperature = data[2]; }
This code now includes the `_delay_uSec` function to handle microsecond delays by using nested loops with the `nop` instruction. The `nop` instruction is used to create a precise delay, with each `nop` consuming one CPU cycle. The nested loop counts up to 72, which corresponds to the 72 MHz frequency of the STM32F103.
Keep in mind that this approach assumes the CPU is running at exactly 72 MHz. If your MCU operates at a different frequency, you will need to adjust the inner loop count accordingly.
