
{"id":581,"date":"2025-04-21T11:29:00","date_gmt":"2025-04-21T03:29:00","guid":{"rendered":"https:\/\/darcyjprojects.xyz\/?p=581"},"modified":"2026-05-28T14:34:37","modified_gmt":"2026-05-28T06:34:37","slug":"developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal","status":"publish","type":"post","link":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/","title":{"rendered":"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL)"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Introduction<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">During the firmware development of my <a href=\"https:\/\/darcyjprojects.xyz\/#projects\" type=\"link\" id=\"https:\/\/darcyjprojects.xyz\/#projects\">embedded controller<\/a>, I wanted to start adding some more complicated sensor support; something beyond just a 0 to 3.3V analogue signal. I had used the DHT11 before, and its quite inexpensive too, so I wanted to see if I could create a &#8220;from scratch&#8221; driver for it, working with the individual bits, as it would be a good primer before I started trying to do the same but for the whole of MODBUS RTU.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The DHT11<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The DHT11 is a basic, low cost digital temperature and humidity sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air, outputting a digital signal on its data pin <a href=\"#reference-1\">[1]<\/a>. As it is not an analogue sensor, the readings are encoded in binary and sent one bit at a time, so a driver is required to decode this data.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"alignright size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"970\" height=\"728\" src=\"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg\" alt=\"\" class=\"wp-image-587\" style=\"aspect-ratio:1.3324391879534232;width:408px;height:auto\" srcset=\"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg 970w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02-300x225.jpg 300w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02-768x576.jpg 768w\" sizes=\"auto, (max-width: 970px) 100vw, 970px\" \/><figcaption class=\"wp-element-caption\"><strong>Figure 1. <\/strong>A DHT11 inserted into a breadboard <a href=\"#reference-1\">[1]<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">The DHT11 has four pins, although only three are used. Pin <code>1<\/code> is <code>VCC (+)<\/code> which is rated for <code>3.3V<\/code> to <code>5V DC<\/code>, Pin <code>2 <\/code>is the bidirectional data pin, Pin <code>3<\/code> is not connected, and Pin <code>4<\/code> is <code>GND (-)<\/code>. You can source the DHT11 in its bare form, or in the PCB module form which often includes a pull up resistor. The PCB module may not have the <code>NC<\/code> pin, so in that case, Pin <code>3<\/code> is often <code>GND<\/code> instead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The DHT11 is rated for <code>20-80%<\/code> humidity readings with <code>5%<\/code> accuracy and <code>0-50\u00b0C<\/code> temperature readings <code>\u00b12\u00b0C<\/code> accuracy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ll be writing this driver for the STM32G4 microcontroller using the STM32CubeIDE in C.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Communication Protocol<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To get started, I found some resources online outlining the communication protocol for the DHT11. This article from <a data-type=\"link\" data-id=\"https:\/\/www.engineersgarage.com\/articles-arduino-dht11-humidity-temperature-sensor-interfacing\/\" href=\"https:\/\/www.engineersgarage.com\/articles-arduino-dht11-humidity-temperature-sensor-interfacing\/\">engineersgarage.com<\/a> was immensely helpful <a href=\"#reference-2\">[2]<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From this article, I was able to deduce this set of operations to read from the DHT11 sensor:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Send a start signal &#8211; set the data pin to a logical <code><strong>LOW<\/strong><\/code> for <strong><code>18ms<\/code><\/strong>, and then pull <code><strong>HIGH<\/strong><\/code>.<\/li>\n\n\n\n<li>Read the response from the DHT11 which should be a logical <strong><code>LOW<\/code> <\/strong>(for <strong><code>54\u00b5s<\/code><\/strong>) followed by a logical <strong><code>HIGH<\/code> <\/strong>(for <strong><code>80\u00b5s<\/code><\/strong>).<\/li>\n\n\n\n<li>The DHT11 will then begin transmitting the sensor data. The data packet consists of five bytes:\n<ul class=\"wp-block-list\">\n<li>[0] Humidity Integer<\/li>\n\n\n\n<li>[1] Humidity Decimal<\/li>\n\n\n\n<li>[2] Temperature Integer<\/li>\n\n\n\n<li>[3] Temperature Decimal<\/li>\n\n\n\n<li>[4] Checksum\n<ul class=\"wp-block-list\">\n<li>Simply the sum of the first four bytes<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>The transmitted bits start with a logical <strong><code>LOW<\/code><\/strong> for <strong><code>54 \u00b5s<\/code><\/strong>, followed by a logical <code><strong>HIGH<\/strong><\/code>. The length of the logical <strong><code>HIGH<\/code> <\/strong>determines whether the bit is a <code><strong>1<\/strong><\/code> or a <code><strong>0<\/strong><\/code>.\n<ul class=\"wp-block-list\">\n<li><code>0<\/code> Bit &#8211;&gt; <code>HIGH<\/code> for <code>24\u00b5s<\/code><\/li>\n\n\n\n<li><code>1<\/code> Bit &#8211;&gt; <code>HIGH<\/code> for <code>70\u00b5s<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>End of the frame<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">With an oscilloscope probe on the data pin of the DHT11, we can see this behaviour (<em>images taken utilising the completed driver<\/em>):<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"480\" src=\"https:\/\/www.darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-out.png\" alt=\"\" class=\"wp-image-430\" srcset=\"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-out.png 800w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-out-300x180.png 300w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-out-768x461.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\"><strong>Figure 2. <\/strong>A view of an entire DHT11 read cycle<\/figcaption><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"480\" src=\"https:\/\/www.darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-in.png\" alt=\"\" class=\"wp-image-431\" srcset=\"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-in.png 800w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-in-300x180.png 300w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/dht11-zoomed-in-768x461.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\"><strong>Figure 3.<\/strong> Zoomed in on the data reply from the DHT11<\/figcaption><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 id=\"microsecond-accuracy\" class=\"wp-block-heading\">Microsecond Accuracy<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As such, it is clear that microsecond timing is a key part in communicating with the DHT. To work on such a time scale, we can&#8217;t used the <code>HAL_Delay<\/code> function as it only offers pausing at a minimum of <code>1<\/code> millisecond (<code>1000<\/code> microseconds).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As such, we&#8217;ll have the utilise the STM32&#8217;s Data Watchpoint and Trace (DWT) unit which allows us to get the CPU&#8217;s current cycle count, which we can use to calculate the required number of CPU cycles to surpass a certain microsecond time period. With this, we can delay for a certain number of microseconds, and also time signals in microseconds.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I found this really useful article which outlined how to implement a DWT microsecond delay function: <a href=\"https:\/\/kbiva.wordpress.com\/2013\/03\/25\/microsecond-delay-function-for-stm32\/\">kbiva.wordpress.com<\/a> <a href=\"#reference-3\">[3]<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ --- Initialise the DWT ---\n\/\/ Initates the DWT (Data Watchpoint and Trace) unit (if not already initiated)\n\/\/ Used for microsecond timing\nstatic void DWT_Init(void) {\n    if (!(DWT->CTRL &amp; DWT_CTRL_CYCCNTENA_Msk)) {\n        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;\n        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;\n    }\n}\n\n\/\/ --- Delay for microseconds ---\nstatic void delay_us(uint32_t us) {\n    uint32_t start = DWT->CYCCNT; \/\/ get the current cycle count\n    uint32_t ticks = us * (SystemCoreClock \/ 1000000); \/\/ calculate how many CPU cycles represent the required us delay\n    while ((DWT->CYCCNT - start) &lt; ticks); \/\/ do nothing (wait) until the required number of ticks for the us delay have been achieved\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Initialise the DWT ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Initates the DWT (Data Watchpoint and Trace) unit (if not already initiated)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Used for microsecond timing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DWT_Init<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #FF79C6\">!<\/span><span style=\"color: #F8F8F2\">(DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CTRL <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\"> DWT_CTRL_CYCCNTENA_Msk)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        CoreDebug<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">DEMCR <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> CoreDebug_DEMCR_TRCENA_Msk;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CTRL <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> DWT_CTRL_CYCCNTENA_Msk;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Delay for microseconds ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">delay_us<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">us<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> start <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT;<\/span><span style=\"color: #6272A4\"> \/\/ get the current cycle count<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> ticks <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> us <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\"> (SystemCoreClock <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1000000<\/span><span style=\"color: #F8F8F2\">);<\/span><span style=\"color: #6272A4\"> \/\/ calculate how many CPU cycles represent the required us delay<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">while<\/span><span style=\"color: #F8F8F2\"> ((DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT <\/span><span style=\"color: #FF79C6\">-<\/span><span style=\"color: #F8F8F2\"> start) <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\"> ticks);<\/span><span style=\"color: #6272A4\"> \/\/ do nothing (wait) until the required number of ticks for the us delay have been achieved<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#282A36;color:#efefe1;font-size:12px;line-height:1;position:relative\">C<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Pin Switching<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The DHT11 only has a single data pin, and this is used for both talking and listening to the DHT11. As an GPIO pin can only be an input or an output at one time, I created a function to set the mode of the data pin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When we are wanting to trigger a read out, we need to talk to the DHT11, so we configure the GPIO pin as an output and re-initiate the GPIO.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When listening to what the DHT11 is reading out, we must set it to an input so we can actually read the data. Some sources state that a pull up is required, but it worked just fine for me without an internal or external pull up, but the choice to add an internal one is left up to you in the code.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ --- Pin Mode Switching ---\nstatic void set_input(void) {\n    GPIO_InitTypeDef GPIO_InitStruct = {0};\n    GPIO_InitStruct.Pin = DHT11_PIN;\n    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;\n    GPIO_InitStruct.Pull = GPIO_NOPULL; \/\/ Works for me without internal or external pull up. External may be required for some models?\n    HAL_GPIO_Init(DHT11_PORT, &amp;GPIO_InitStruct);\n}\n\nstatic void set_output(void) {\n    GPIO_InitTypeDef GPIO_InitStruct = {0};\n    GPIO_InitStruct.Pin = DHT11_PIN;\n    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;\n    GPIO_InitStruct.Pull = GPIO_NOPULL;\n    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;\n    HAL_GPIO_Init(DHT11_PORT, &amp;GPIO_InitStruct);\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Pin Mode Switching ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">set_input<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitTypeDef GPIO_InitStruct <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> {<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">};<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pin <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DHT11_PIN;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Mode <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_MODE_INPUT;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pull <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_NOPULL;<\/span><span style=\"color: #6272A4\"> \/\/ Works for me without internal or external pull up. External may be required for some models?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">HAL_GPIO_Init<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">GPIO_InitStruct);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">set_output<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitTypeDef GPIO_InitStruct <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> {<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">};<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pin <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DHT11_PIN;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Mode <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_MODE_OUTPUT_PP;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pull <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_NOPULL;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Speed <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_SPEED_FREQ_LOW;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">HAL_GPIO_Init<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">GPIO_InitStruct);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#282A36;color:#efefe1;font-size:12px;line-height:1;position:relative\">C<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Readings<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As we know from the communication protocol, the DHT11 encodes it&#8217;s binary output in a <code>HIGH<\/code> pin state on the data pin, with a different <code>HIGH<\/code> duration indicating a <code>0<\/code> or a <code>1<\/code>. The <code>LOW<\/code> pin state is purely for indicating the end of that duration, so we can read out more than one bit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As the <code>LOW<\/code> pin state is purely a separator, we don&#8217;t need to time that, we only have the time how long the data pin is <code>HIGH<\/code> for.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To do so, I implemented a <code>wait_for_input_state<\/code> function which measures how long it takes for the input state to change. This is reusing some code from the <a href=\"#microsecond-accuracy\"><code>delay_us<\/code> function<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ --- Pulse Duration Measurement ---\nstatic uint32_t wait_for_input_state(uint8_t state, uint32_t timeout_us) {\n    uint32_t start = DWT->CYCCNT; \/\/ get current cycle count\n    uint32_t ticks = timeout_us * (SystemCoreClock \/ 1000000); \/\/ get the number of ticks for the timeout\n\n    while ((DWT->CYCCNT - start) &lt; ticks) {\n        if (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == state) {\n            return (DWT->CYCCNT - start) \/ (SystemCoreClock \/ 1000000);\n        }\n    }\n    return 0xFFFFFFFF; \/\/ timeout\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Pulse Duration Measurement ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">uint8_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">state<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">timeout_us<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> start <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT;<\/span><span style=\"color: #6272A4\"> \/\/ get current cycle count<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> ticks <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> timeout_us <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\"> (SystemCoreClock <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1000000<\/span><span style=\"color: #F8F8F2\">);<\/span><span style=\"color: #6272A4\"> \/\/ get the number of ticks for the timeout<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">while<\/span><span style=\"color: #F8F8F2\"> ((DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT <\/span><span style=\"color: #FF79C6\">-<\/span><span style=\"color: #F8F8F2\"> start) <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\"> ticks) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">HAL_GPIO_ReadPin<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, DHT11_PIN) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> state) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">            <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> (DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT <\/span><span style=\"color: #FF79C6\">-<\/span><span style=\"color: #F8F8F2\"> start) <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> (SystemCoreClock <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1000000<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">0x<\/span><span style=\"color: #BD93F9\">FFFFFFFF<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\"> \/\/ timeout<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#282A36;color:#efefe1;font-size:12px;line-height:1;position:relative\">C<\/span><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">With this, we now can distinguish a <code>0<\/code> from a <code>1<\/code>, but we don&#8217;t have any way to actually facilitate the full reception.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s create the decoding protocol in code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First we have to send the <strong>start signal<\/strong> -&gt; the data pin is set to an output, we pull it low for <code>18ms<\/code> and then back to high.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>set_output();\n\nHAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET); \/\/ pull low\ndelay_us(18000); \/\/ for 18 ms\nHAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET); \/\/ pull high\ndelay_us(20); \/\/ short delay<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">set_output<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">HAL_GPIO_WritePin<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET); <\/span><span style=\"color: #6272A4\">\/\/ pull low<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">delay_us<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #BD93F9\">18000<\/span><span style=\"color: #F8F8F2\">); <\/span><span style=\"color: #6272A4\">\/\/ for 18 ms<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">HAL_GPIO_WritePin<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET); <\/span><span style=\"color: #6272A4\">\/\/ pull high<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">delay_us<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #BD93F9\">20<\/span><span style=\"color: #F8F8F2\">); <\/span><span style=\"color: #6272A4\">\/\/ short delay<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Next, we listen to what the DHT11 has to say -&gt; the data pin is set as an input, and we read the &#8220;I heard you!&#8221; response from the DHT11. The timing of the response isn&#8217;t exactly mission critical, so I just use <code>100us<\/code> as the cut-off. There&#8217;s a checksum at the end for the data anyway, and that&#8217;s all we really care about.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>set_input();\n\n\/\/ Require LOW (54us) then HIGH (80us)\nif (wait_for_input_state(GPIO_PIN_RESET, 100) == 0xFFFFFFFF) return DHT11_ERROR_NO_RESPONSE; \/\/ require LOW\nif (wait_for_input_state(GPIO_PIN_SET, 100) == 0xFFFFFFFF) return DHT11_ERROR_NO_RESPONSE; \/\/ require HIGH\n\n\/\/ Require LOW (the start of data)\nif (wait_for_input_state(GPIO_PIN_RESET, 100) == 0xFFFFFFFF) return DHT11_ERROR_TIMEOUT; \/\/ require LOW<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">set_input<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Require LOW (54us) then HIGH (80us)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_RESET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0xFFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_NO_RESPONSE; <\/span><span style=\"color: #6272A4\">\/\/ require LOW<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_SET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0xFFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_NO_RESPONSE; <\/span><span style=\"color: #6272A4\">\/\/ require HIGH<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Require LOW (the start of data)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_RESET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0xFFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_TIMEOUT; <\/span><span style=\"color: #6272A4\">\/\/ require LOW<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Now we start listening to the actual data from the DHT11 -&gt; <code>5<\/code> bytes is <code>40<\/code> bits we listen out for, timing how long each <code>HIGH<\/code> pulse of the data pin is.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For each bit, we initially wait for the data pin to go <code>HIGH<\/code>, indicating the start of the bit, and then wait for it to go <code>LOW<\/code> again &#8211; this time until <code>LOW<\/code> is what we are measuring to distinguish the bit&#8217;s value. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>if (wait_for_input_state(GPIO_PIN_SET, 70) == 0xFFFFFFFF) return DHT11_ERROR_TIMEOUT;\nuint32_t held = wait_for_input_state(GPIO_PIN_RESET, 100);\n\nif (held == 0xFFFFFFFF) return DHT11_ERROR_TIMEOUT;<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_SET, <\/span><span style=\"color: #BD93F9\">70<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0xFFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_TIMEOUT;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">uint32_t held <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_RESET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (held <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0xFFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_TIMEOUT;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">If the hold time is greater than <code>40us<\/code>, then we can safely assume that the bit is a <code>1<\/code>, and if not, a <code>0<\/code>. I then put this read bit into the array of bytes. As its an array of bytes, its only contains <code>5<\/code> elements, so we have to insert the next LSB into the byte. This is done by left shifting all the bits in the byte, opening up the LSB for entry, and using the bitwise OR assignment operator to insert the new bit into the LSB of the byte. (<em>More info in the <a href=\"#the-final-driver\">source code<\/a> comments<\/em>)<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>uint8_t bit = (held > 40) ? 1 : 0; \/\/ if was held for >40us, then its a 1, less than 40us, its a 0\n\ndata&#91;i \/ 8&#93; &lt;&lt;= 1;\ndata&#91;i \/ 8&#93; |= bit;<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">uint8_t bit <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> (held <\/span><span style=\"color: #FF79C6\">&gt;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">40<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">?<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">; <\/span><span style=\"color: #6272A4\">\/\/ if was held for &gt;40us, then its a 1, less than 40us, its a 0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;i <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">8<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">&lt;&lt;=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;i <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">8<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> bit;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">To visualise this, here is the process of writing the bits <code>1<\/code>, <code>0<\/code>, and finally <code>1<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>data&#91;0&#93; &lt;&lt;= 1;       \/\/ --> data&#91;0&#93; = 00000000 &lt;&lt; 1 = 00000000\ndata&#91;0&#93; |= 1;        \/\/ --> data&#91;0&#93; = 00000000 | 00000001 = 00000001\ndata&#91;0&#93; &lt;&lt;= 1;       \/\/ --> data&#91;0&#93; = 00000001 &lt;&lt; 1 = 00000010\ndata&#91;0&#93; |= 0;        \/\/ --> data&#91;0&#93; = 00000010 | 00000000 = 00000010\ndata&#91;0&#93; &lt;&lt;= 1;       \/\/ --> data&#91;0&#93; = 00000010 &lt;&lt; 1 = 00000100\ndata&#91;0&#93; |= 1;        \/\/ --> data&#91;0&#93; = 00000100 | 00000001 = 00000101<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">&lt;&lt;=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\">       \/\/ --&gt; data&#91;0&#93; = 00000000 &lt;&lt; 1 = 00000000<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\">        \/\/ --&gt; data&#91;0&#93; = 00000000 | 00000001 = 00000001<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">&lt;&lt;=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\">       \/\/ --&gt; data&#91;0&#93; = 00000001 &lt;&lt; 1 = 00000010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\">        \/\/ --&gt; data&#91;0&#93; = 00000010 | 00000000 = 00000010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">&lt;&lt;=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\">       \/\/ --&gt; data&#91;0&#93; = 00000010 &lt;&lt; 1 = 00000100<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\">        \/\/ --&gt; data&#91;0&#93; = 00000100 | 00000001 = 00000101<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, we calculate what the checksum is based on the data we received, and compare it with the checksum the DHT11 told us is correct.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the checksum is fine, we know we read the data without corruption, so we assign the read data values to the pointers provided to the function, outputting the readings.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ Checksum byte should be the sum of all data bytes\nuint8_t checksum = data&#91;0&#93; + data&#91;1&#93; + data&#91;2&#93; + data&#91;3&#93;;\nif (checksum != data&#91;4&#93;) return DHT11_ERROR_CHECKSUM;\n\n*humidity_int = data&#91;0&#93;;\n*humidity_dec = data&#91;1&#93;;\n*temperature_int = data&#91;2&#93;;\n*temperature_dec = data&#91;3&#93;;\n\nreturn DHT11_OK; \/\/ Successfully read the DHT11<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6272A4\">\/\/ Checksum byte should be the sum of all data bytes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">uint8_t checksum <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">+<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">+<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">2<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">+<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">3<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (checksum <\/span><span style=\"color: #FF79C6\">!=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">4<\/span><span style=\"color: #F8F8F2\">&#93;) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_CHECKSUM;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">humidity_int <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">humidity_dec <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">temperature_int <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">2<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">temperature_dec <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">3<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_OK; <\/span><span style=\"color: #6272A4\">\/\/ Successfully read the DHT11<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#282A36;color:#efefe1;font-size:12px;line-height:1;position:relative\">C<\/span><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">This whole process is then repeated <code>39<\/code> more times, so we read all <code>40<\/code> bits.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Status Enumeration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As you may have noticed in the reception code, I&#8217;m outputting some &#8220;error codes&#8221;, like <code>DHT11_ERROR_TIMEOUT<\/code> or <code>DHT11_ERROR_CHECKSUM<\/code>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we look in the header file for this driver, I defined an enumeration outlining each status code for the driver. This gives us an easy and human readable way to access how the read went.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is why the datatype of the <code>DHT11_Read<\/code> function is <code>DHT11_Response<\/code>, and its parameters are pointers. It returns a single status code, and modifies variables outside of itself to actually output the readings.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#efefe1\">dht11.h<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>#ifndef DHT11_H\n#define DHT11_H\n\n#include \"stm32g4xx_hal.h\"\n\n\/\/ Emum to describe read status\ntypedef enum {\n\tDHT11_OK = 0,\n\tDHT11_ERROR_TIMEOUT,\n\tDHT11_ERROR_CHECKSUM,\n\tDHT11_ERROR_NO_RESPONSE\n} DHT11_Response;\n\n\/\/ --- Functions ---\n\/\/ Defines the GPIO pin and port for the DHT11\nvoid DHT11_Setup(GPIO_TypeDef* port, uint16_t pin);\n\n\/\/ Initiates and reads a response from the DHT11\nDHT11_Response DHT11_Read(uint8_t* temperature_int, uint8_t* temperature_dec, uint8_t* humidity_int, uint8_t* humidity_dec);\n\n#endif<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">#ifndef<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DHT11_H<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">#define<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DHT11_H<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">#include<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">stm32g4xx_hal.h<\/span><span style=\"color: #E9F284\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Emum to describe read status<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">typedef<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">enum<\/span><span style=\"color: #F8F8F2\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\tDHT11_OK <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\tDHT11_ERROR_TIMEOUT,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\tDHT11_ERROR_CHECKSUM,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\tDHT11_ERROR_NO_RESPONSE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">} DHT11_Response;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Functions ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Defines the GPIO pin and port for the DHT11<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DHT11_Setup<\/span><span style=\"color: #F8F8F2\">(GPIO_TypeDef<\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">port<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint16_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">pin<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Initiates and reads a response from the DHT11<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">DHT11_Response <\/span><span style=\"color: #50FA7B\">DHT11_Read<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">temperature_int<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">temperature_dec<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">humidity_int<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">humidity_dec<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">#endif<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#282A36;color:#efefe1;font-size:12px;line-height:1;position:relative\">C<\/span><\/div>\n\n\n\n<h3 id=\"the-final-driver\" class=\"wp-block-heading\">The Final Driver<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s take a look at the full source file now:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#efefe1\">C<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>#include \"sensors\/dht11.h\"\n\/\/ Sources:\n\/\/ https:\/\/www.engineersgarage.com\/articles-arduino-dht11-humidity-temperature-sensor-interfacing\/\n\/\/ https:\/\/kbiva.wordpress.com\/2013\/03\/25\/microsecond-delay-function-for-stm32\/\n\n\/\/ Variables\nstatic GPIO_TypeDef* DHT11_PORT;\nstatic uint16_t DHT11_PIN;\n\n\/\/ --- Initialise the DWT ---\n\/\/ Initates the DWT (Data Watchpoint and Trace) unit (if not already initiated)\n\/\/ Used for microsecond timing\nstatic void DWT_Init(void) {\n    if (!(DWT->CTRL &amp; DWT_CTRL_CYCCNTENA_Msk)) {\n        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;\n        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;\n    }\n}\n\n\/\/ --- Delay for microseconds ---\nstatic void delay_us(uint32_t us) {\n    uint32_t start = DWT->CYCCNT; \/\/ get the current cycle count\n    uint32_t ticks = us * (SystemCoreClock \/ 1000000); \/\/ calculate how many CPU cycles represent the required us delay\n    while ((DWT->CYCCNT - start) &lt; ticks); \/\/ do nothing (wait) until the required number of ticks for the us delay have been achieved\n}\n\n\/\/ --- Pin Mode Switching ---\nstatic void set_input(void) {\n    GPIO_InitTypeDef GPIO_InitStruct = {0};\n    GPIO_InitStruct.Pin = DHT11_PIN;\n    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;\n    GPIO_InitStruct.Pull = GPIO_NOPULL; \/\/ Works for me without internal or external pull up. External may be required for some models?\n    HAL_GPIO_Init(DHT11_PORT, &amp;GPIO_InitStruct);\n}\n\nstatic void set_output(void) {\n    GPIO_InitTypeDef GPIO_InitStruct = {0};\n    GPIO_InitStruct.Pin = DHT11_PIN;\n    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;\n    GPIO_InitStruct.Pull = GPIO_NOPULL;\n    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;\n    HAL_GPIO_Init(DHT11_PORT, &amp;GPIO_InitStruct);\n}\n\n\/\/ --- Pulse Duration Measurement ---\nstatic uint32_t wait_for_input_state(uint8_t state, uint32_t timeout_us) {\n    uint32_t start = DWT->CYCCNT; \/\/ get current cycle count\n    uint32_t ticks = timeout_us * (SystemCoreClock \/ 1000000); \/\/ get the number of ticks for the timeout\n\n    while ((DWT->CYCCNT - start) &lt; ticks) {\n        if (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == state) {\n            return (DWT->CYCCNT - start) \/ (SystemCoreClock \/ 1000000);\n        }\n    }\n    return 0xFFFFFFFF; \/\/ timeout\n}\n\n\/\/ --- Initiate the DHT11 ---\nstatic void DHT11_Init(void) {\n    DWT_Init();\n    set_output();\n    HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET); \/\/ set pin to HIGH\n}\n\n\/\/ --- SETUP DHT11 ---\n\/**\n * @brief Sets up the GPIO configuration for the DHT11 sensor.\n *\n * This function configures the specified GPIO port and pin for the DHT11 sensor,\n * enabling the clock for the GPIO port if needed. After setup, it initialises the\n * DHT11 sensor.\n *\n * @param port: Pointer to the port where the DHT11 data pin is connected (e.g., GPIOA, GPIOB, GPIOC).\n * @param pin: Pin number of the GPIO port where the DHT11 data pin is connected.\n *\/\nvoid DHT11_Setup(GPIO_TypeDef* port, uint16_t pin) {\n\tDHT11_PORT = port;\n\tDHT11_PIN = pin;\n\n\t\/\/ Enable the ports peripheral clock\n\tif (port == GPIOA) __HAL_RCC_GPIOA_CLK_ENABLE();\n\telse if (port == GPIOB) __HAL_RCC_GPIOB_CLK_ENABLE();\n\telse if (port == GPIOC) __HAL_RCC_GPIOC_CLK_ENABLE();\n\n\tDHT11_Init();\n}\n\n\/\/ --- MAIN READ FUNCTION ---\n\/**\n * @brief Reads temperature and humidity (int and dec) from the DHT11 sensor.\n *\n * This function initiates communication with the DHT11 sensor and reads the temperature and humidity values.\n * It requires a successful setup of the DHT11 sensor through DHT11_Setup() before calling this function.\n *\n * @pre DHT11_Setup(port, pin) must be called before using this function.\n *\n * @param temperature_int: Pointer to store the integer part of the temperature (\u00b0C).\n * @param temperature_dec: Pointer to store the decimal part of the temperature (some DHT11 models will just be 0).\n * @param humidity_int: Pointer to store the integer part of the humidity (%RH).\n * @param humidity_dec: Pointer to store the decimal part of the humidity (some DHT11 models will just be 0).\n *\n * @retval DHT11_OK: If the data was read successfully.\n * @retval DHT11_ERROR_NO_RESPONSE: If the sensor did not respond.\n * @retval DHT11_ERROR_TIMEOUT: If a timeout occurred while reading data.\n * @retval DHT11_ERROR_CHECKSUM: If the checksum does not match.\n *\n *\/\nDHT11_Response DHT11_Read(uint8_t* temperature_int, uint8_t* temperature_dec, uint8_t* humidity_int, uint8_t* humidity_dec) {\n    \/\/ Create the data array to store the bytes\n    uint8_t data&#91;5&#93; = {0}; \/\/ 5 bytes = 40 bits\n\n    \/\/ 1. Send the start signal\n    set_output();\n\n    HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET); \/\/ pull low\n    delay_us(18000); \/\/ for 18 ms\n    HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET); \/\/ pull high\n    delay_us(20); \/\/ short delay\n\n    \/\/ 2. Read response\n    set_input();\n\n    \/\/ Require LOW (54us) then HIGH (80us) (but exact timing doesn't matter, checksum will be there to see if it was successful)\n    if (wait_for_input_state(GPIO_PIN_RESET, 100) == 0xFFFFFFFF) return DHT11_ERROR_NO_RESPONSE; \/\/ require LOW\n    if (wait_for_input_state(GPIO_PIN_SET, 100) == 0xFFFFFFFF) return DHT11_ERROR_NO_RESPONSE; \/\/ require HIGH\n\n    \/\/ Require LOW (the start of data)\n    if (wait_for_input_state(GPIO_PIN_RESET, 100) == 0xFFFFFFFF) return DHT11_ERROR_TIMEOUT; \/\/ require LOW\n\n    \/\/ 3. Read 5 bytes = 40 bits\n    \/\/ Each bit starts with LOW for 54us, then HIGH: 24us is a bit 0, 70us is a bit 1\n    for (int i = 0; i &lt; 40; i++) {\n        if (wait_for_input_state(GPIO_PIN_SET, 70) == 0xFFFFFFFF) return DHT11_ERROR_TIMEOUT; \/\/ Start of bit is LOW, so wait for HIGH (which actually tells us what the bit is)\n        uint32_t held = wait_for_input_state(GPIO_PIN_RESET, 100); \/\/ Now that the pin is HIGH, wait until it goes LOW and count how long it takes for it to do so\n\n        if (held == 0xFFFFFFFF) return DHT11_ERROR_TIMEOUT;\n        uint8_t bit = (held > 40) ? 1 : 0; \/\/ if was held for >40us, then its a 1, less than 40us, its a 0\n\n        data&#91;i \/ 8&#93; &lt;&lt;= 1; \/\/ i is current bit index, i \/ 8 is current byte index (8 bits in 1 byte), &lt;&lt;= 1 shifts the current byte left by 1 to make room for the new byte at LSB\n        data&#91;i \/ 8&#93; |= bit; \/\/ bit is either 0 or 1, |= is bitwise OR assignment operator, inserts new bit into the LSB of the byte\n\n        \/\/ Example for the above bit writing (writing bits 1, 0, and then 1):\n        \/\/ data&#91;0&#93; &lt;&lt;= 1;       --> data&#91;0&#93; = 00000000 &lt;&lt; 1 = 00000000\n        \/\/ data&#91;0&#93; |= 1;        --> data&#91;0&#93; = 00000000 | 00000001 = 00000001\n        \/\/ data&#91;0&#93; &lt;&lt;= 1;       --> data&#91;0&#93; = 00000001 &lt;&lt; 1 = 00000010\n        \/\/ data&#91;0&#93; |= 0;        --> data&#91;0&#93; = 00000010 | 00000000 = 00000010\n        \/\/ data&#91;0&#93; &lt;&lt;= 1;       --> data&#91;0&#93; = 00000010 &lt;&lt; 1 = 00000100\n        \/\/ data&#91;0&#93; |= 1;        --> data&#91;0&#93; = 00000100 | 00000001 = 00000101\n    }\n\n    \/\/ 4. Check the checksum to ensure a valid reading\n    \/\/ Checksum byte should be the sum of all data bytes\n    uint8_t checksum = data&#91;0&#93; + data&#91;1&#93; + data&#91;2&#93; + data&#91;3&#93;;\n    if (checksum != data&#91;4&#93;) return DHT11_ERROR_CHECKSUM;\n\n    *humidity_int = data&#91;0&#93;;\n    *humidity_dec = data&#91;1&#93;;\n    *temperature_int = data&#91;2&#93;;\n    *temperature_dec = data&#91;3&#93;;\n\n    return DHT11_OK; \/\/ Successfully read the DHT11\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">#include<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">sensors\/dht11.h<\/span><span style=\"color: #E9F284\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Sources:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ https:\/\/www.engineersgarage.com\/articles-arduino-dht11-humidity-temperature-sensor-interfacing\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ https:\/\/kbiva.wordpress.com\/2013\/03\/25\/microsecond-delay-function-for-stm32\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Variables<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> GPIO_TypeDef<\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\"> DHT11_PORT;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">uint16_t<\/span><span style=\"color: #F8F8F2\"> DHT11_PIN;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Initialise the DWT ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Initates the DWT (Data Watchpoint and Trace) unit (if not already initiated)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ Used for microsecond timing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DWT_Init<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #FF79C6\">!<\/span><span style=\"color: #F8F8F2\">(DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CTRL <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\"> DWT_CTRL_CYCCNTENA_Msk)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        CoreDebug<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">DEMCR <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> CoreDebug_DEMCR_TRCENA_Msk;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CTRL <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> DWT_CTRL_CYCCNTENA_Msk;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Delay for microseconds ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">delay_us<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">us<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> start <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT;<\/span><span style=\"color: #6272A4\"> \/\/ get the current cycle count<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> ticks <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> us <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\"> (SystemCoreClock <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1000000<\/span><span style=\"color: #F8F8F2\">);<\/span><span style=\"color: #6272A4\"> \/\/ calculate how many CPU cycles represent the required us delay<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">while<\/span><span style=\"color: #F8F8F2\"> ((DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT <\/span><span style=\"color: #FF79C6\">-<\/span><span style=\"color: #F8F8F2\"> start) <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\"> ticks);<\/span><span style=\"color: #6272A4\"> \/\/ do nothing (wait) until the required number of ticks for the us delay have been achieved<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Pin Mode Switching ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">set_input<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitTypeDef GPIO_InitStruct <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> {<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">};<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pin <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DHT11_PIN;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Mode <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_MODE_INPUT;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pull <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_NOPULL;<\/span><span style=\"color: #6272A4\"> \/\/ Works for me without internal or external pull up. External may be required for some models?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">HAL_GPIO_Init<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">GPIO_InitStruct);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">set_output<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitTypeDef GPIO_InitStruct <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> {<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">};<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pin <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DHT11_PIN;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Mode <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_MODE_OUTPUT_PP;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Pull <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_NOPULL;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    GPIO_InitStruct.Speed <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> GPIO_SPEED_FREQ_LOW;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">HAL_GPIO_Init<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">GPIO_InitStruct);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Pulse Duration Measurement ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">uint8_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">state<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">timeout_us<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> start <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT;<\/span><span style=\"color: #6272A4\"> \/\/ get current cycle count<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> ticks <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> timeout_us <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\"> (SystemCoreClock <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1000000<\/span><span style=\"color: #F8F8F2\">);<\/span><span style=\"color: #6272A4\"> \/\/ get the number of ticks for the timeout<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">while<\/span><span style=\"color: #F8F8F2\"> ((DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT <\/span><span style=\"color: #FF79C6\">-<\/span><span style=\"color: #F8F8F2\"> start) <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\"> ticks) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">HAL_GPIO_ReadPin<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, DHT11_PIN) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> state) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">            <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> (DWT<\/span><span style=\"color: #FF79C6\">-&gt;<\/span><span style=\"color: #F8F8F2\">CYCCNT <\/span><span style=\"color: #FF79C6\">-<\/span><span style=\"color: #F8F8F2\"> start) <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> (SystemCoreClock <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1000000<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">0x<\/span><span style=\"color: #BD93F9\">FFFFFFFF<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\"> \/\/ timeout<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- Initiate the DHT11 ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">static<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DHT11_Init<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">DWT_Init<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">set_output<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">HAL_GPIO_WritePin<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET);<\/span><span style=\"color: #6272A4\"> \/\/ set pin to HIGH<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- SETUP DHT11 ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@brief<\/span><span style=\"color: #6272A4\"> Sets up the GPIO configuration for the DHT11 sensor.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * This function configures the specified GPIO port and pin for the DHT11 sensor,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * enabling the clock for the GPIO port if needed. After setup, it initialises the<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * DHT11 sensor.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@param<\/span><span style=\"color: #6272A4\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">port<\/span><span style=\"color: #6272A4\">: Pointer to the port where the DHT11 data pin is connected (e.g., GPIOA, GPIOB, GPIOC).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@param<\/span><span style=\"color: #6272A4\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">pin<\/span><span style=\"color: #6272A4\">: Pin number of the GPIO port where the DHT11 data pin is connected.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">void<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DHT11_Setup<\/span><span style=\"color: #F8F8F2\">(GPIO_TypeDef<\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">port<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint16_t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">pin<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\tDHT11_PORT <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> port;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\tDHT11_PIN <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> pin;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t<\/span><span style=\"color: #6272A4\">\/\/ Enable the ports peripheral clock<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t<\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (port <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> GPIOA) <\/span><span style=\"color: #50FA7B\">__HAL_RCC_GPIOA_CLK_ENABLE<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t<\/span><span style=\"color: #FF79C6\">else<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (port <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> GPIOB) <\/span><span style=\"color: #50FA7B\">__HAL_RCC_GPIOB_CLK_ENABLE<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t<\/span><span style=\"color: #FF79C6\">else<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (port <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> GPIOC) <\/span><span style=\"color: #50FA7B\">__HAL_RCC_GPIOC_CLK_ENABLE<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t<\/span><span style=\"color: #50FA7B\">DHT11_Init<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/\/ --- MAIN READ FUNCTION ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@brief<\/span><span style=\"color: #6272A4\"> Reads temperature and humidity (int and dec) from the DHT11 sensor.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * This function initiates communication with the DHT11 sensor and reads the temperature and humidity values.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * It requires a successful setup of the DHT11 sensor through DHT11_Setup() before calling this function.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@pre<\/span><span style=\"color: #6272A4\"> DHT11_Setup(port, pin) must be called before using this function.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@param<\/span><span style=\"color: #6272A4\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">temperature_int<\/span><span style=\"color: #6272A4\">: Pointer to store the integer part of the temperature (\u00b0C).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@param<\/span><span style=\"color: #6272A4\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">temperature_dec<\/span><span style=\"color: #6272A4\">: Pointer to store the decimal part of the temperature (some DHT11 models will just be 0).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@param<\/span><span style=\"color: #6272A4\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">humidity_int<\/span><span style=\"color: #6272A4\">: Pointer to store the integer part of the humidity (%RH).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@param<\/span><span style=\"color: #6272A4\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">humidity_dec<\/span><span style=\"color: #6272A4\">: Pointer to store the decimal part of the humidity (some DHT11 models will just be 0).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@retval<\/span><span style=\"color: #6272A4\"> DHT11_OK: If the data was read successfully.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@retval<\/span><span style=\"color: #6272A4\"> DHT11_ERROR_NO_RESPONSE: If the sensor did not respond.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@retval<\/span><span style=\"color: #6272A4\"> DHT11_ERROR_TIMEOUT: If a timeout occurred while reading data.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> * <\/span><span style=\"color: #FF79C6\">@retval<\/span><span style=\"color: #6272A4\"> DHT11_ERROR_CHECKSUM: If the checksum does not match.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">DHT11_Response <\/span><span style=\"color: #50FA7B\">DHT11_Read<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">temperature_int<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">temperature_dec<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">humidity_int<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">uint8_t*<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FFB86C; font-style: italic\">humidity_dec<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ Create the data array to store the bytes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint8_t<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">5<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> {<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">};<\/span><span style=\"color: #6272A4\"> \/\/ 5 bytes = 40 bits<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ 1. Send the start signal<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">set_output<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">HAL_GPIO_WritePin<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET);<\/span><span style=\"color: #6272A4\"> \/\/ pull low<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">delay_us<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #BD93F9\">18000<\/span><span style=\"color: #F8F8F2\">);<\/span><span style=\"color: #6272A4\"> \/\/ for 18 ms<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">HAL_GPIO_WritePin<\/span><span style=\"color: #F8F8F2\">(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET);<\/span><span style=\"color: #6272A4\"> \/\/ pull high<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">delay_us<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #BD93F9\">20<\/span><span style=\"color: #F8F8F2\">);<\/span><span style=\"color: #6272A4\"> \/\/ short delay<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ 2. Read response<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #50FA7B\">set_input<\/span><span style=\"color: #F8F8F2\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ Require LOW (54us) then HIGH (80us) (but exact timing doesn&#39;t matter, checksum will be there to see if it was successful)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_RESET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">0x<\/span><span style=\"color: #BD93F9\">FFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_NO_RESPONSE;<\/span><span style=\"color: #6272A4\"> \/\/ require LOW<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_SET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">0x<\/span><span style=\"color: #BD93F9\">FFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_NO_RESPONSE;<\/span><span style=\"color: #6272A4\"> \/\/ require HIGH<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ Require LOW (the start of data)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_RESET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">0x<\/span><span style=\"color: #BD93F9\">FFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_TIMEOUT;<\/span><span style=\"color: #6272A4\"> \/\/ require LOW<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ 3. Read 5 bytes = 40 bits<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ Each bit starts with LOW for 54us, then HIGH: 24us is a bit 0, 70us is a bit 1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">for<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #FF79C6\">int<\/span><span style=\"color: #F8F8F2\"> i <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">; i <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">40<\/span><span style=\"color: #F8F8F2\">; i<\/span><span style=\"color: #FF79C6\">++<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_SET, <\/span><span style=\"color: #BD93F9\">70<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">0x<\/span><span style=\"color: #BD93F9\">FFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_TIMEOUT;<\/span><span style=\"color: #6272A4\"> \/\/ Start of bit is LOW, so wait for HIGH (which actually tells us what the bit is)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #FF79C6\">uint32_t<\/span><span style=\"color: #F8F8F2\"> held <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">wait_for_input_state<\/span><span style=\"color: #F8F8F2\">(GPIO_PIN_RESET, <\/span><span style=\"color: #BD93F9\">100<\/span><span style=\"color: #F8F8F2\">);<\/span><span style=\"color: #6272A4\"> \/\/ Now that the pin is HIGH, wait until it goes LOW and count how long it takes for it to do so<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (held <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">0x<\/span><span style=\"color: #BD93F9\">FFFFFFFF<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_TIMEOUT;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #FF79C6\">uint8_t<\/span><span style=\"color: #F8F8F2\"> bit <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> (held <\/span><span style=\"color: #FF79C6\">&gt;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">40<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">?<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\"> \/\/ if was held for &gt;40us, then its a 1, less than 40us, its a 0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        data&#91;i <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">8<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">&lt;&lt;=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">;<\/span><span style=\"color: #6272A4\"> \/\/ i is current bit index, i \/ 8 is current byte index (8 bits in 1 byte), &lt;&lt;= 1 shifts the current byte left by 1 to make room for the new byte at LSB<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        data&#91;i <\/span><span style=\"color: #FF79C6\">\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">8<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">|=<\/span><span style=\"color: #F8F8F2\"> bit;<\/span><span style=\"color: #6272A4\"> \/\/ bit is either 0 or 1, |= is bitwise OR assignment operator, inserts new bit into the LSB of the byte<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #6272A4\">\/\/ Example for the above bit writing (writing bits 1, 0, and then 1):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #6272A4\">\/\/ data&#91;0&#93; &lt;&lt;= 1;       --&gt; data&#91;0&#93; = 00000000 &lt;&lt; 1 = 00000000<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #6272A4\">\/\/ data&#91;0&#93; |= 1;        --&gt; data&#91;0&#93; = 00000000 | 00000001 = 00000001<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #6272A4\">\/\/ data&#91;0&#93; &lt;&lt;= 1;       --&gt; data&#91;0&#93; = 00000001 &lt;&lt; 1 = 00000010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #6272A4\">\/\/ data&#91;0&#93; |= 0;        --&gt; data&#91;0&#93; = 00000010 | 00000000 = 00000010<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #6272A4\">\/\/ data&#91;0&#93; &lt;&lt;= 1;       --&gt; data&#91;0&#93; = 00000010 &lt;&lt; 1 = 00000100<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #6272A4\">\/\/ data&#91;0&#93; |= 1;        --&gt; data&#91;0&#93; = 00000100 | 00000001 = 00000101<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ 4. Check the checksum to ensure a valid reading<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #6272A4\">\/\/ Checksum byte should be the sum of all data bytes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">uint8_t<\/span><span style=\"color: #F8F8F2\"> checksum <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">+<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">+<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">2<\/span><span style=\"color: #F8F8F2\">&#93; <\/span><span style=\"color: #FF79C6\">+<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">3<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (checksum <\/span><span style=\"color: #FF79C6\">!=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">4<\/span><span style=\"color: #F8F8F2\">&#93;) <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_CHECKSUM;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">humidity_int <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">humidity_dec <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">temperature_int <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">2<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">*<\/span><span style=\"color: #F8F8F2\">temperature_dec <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> data&#91;<\/span><span style=\"color: #BD93F9\">3<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">return<\/span><span style=\"color: #F8F8F2\"> DHT11_OK;<\/span><span style=\"color: #6272A4\"> \/\/ Successfully read the DHT11<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span><\/code><\/pre><span style=\"display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#282A36;color:#efefe1;font-size:12px;line-height:1;position:relative\">C<\/span><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Testing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s test it out. I modified <code>main.c<\/code> to read the DHT11 every 2 seconds, and output its read value over USB serial. I implemented a <code>println<\/code> function in the <code>usb_serial<\/code> module as well.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>#include \"sensors\/dht11.h\"<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">#include<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">sensors\/dht11.h<\/span><span style=\"color: #E9F284\">&quot;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/* USER CODE BEGIN Init *\/\nDHT11_Setup(GPIOB, GPIO_PIN_0); \/\/ setup DHT11 on pin B0\n\/* USER CODE END Init *\/<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6272A4\">\/* USER CODE BEGIN Init *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">DHT11_Setup<\/span><span style=\"color: #F8F8F2\">(GPIOB, GPIO_PIN_0);<\/span><span style=\"color: #6272A4\"> \/\/ setup DHT11 on pin B0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/* USER CODE END Init *\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/* USER CODE BEGIN WHILE *\/\nuint8_t temp_int = 0, temp_dec = 0, hum_int = 0, hum_dec = 0;\n\nwhile(1) {\n\t  char msg&#91;64&#93;;\n\n\t  DHT11_Response response = DHT11_Read(&amp;temp_int, &amp;temp_dec, &amp;hum_int, &amp;hum_dec);\n\t  if (response == DHT11_OK) {\n\t\t  sprintf(msg, \"Temp: %d.%dC, Humidity: %d.%d%\", temp_int, temp_dec, hum_int, hum_dec);\n\t  } else if (response == DHT11_ERROR_TIMEOUT) {\n\t\t  sprintf(msg, \"DHT11_ERROR_TIMEOUT\");\n\t  } else if (response == DHT11_ERROR_CHECKSUM) {\n\t\t  sprintf(msg, \"DHT11_ERROR_CHECKSUM\");\n\t  } else if (response == DHT11_ERROR_NO_RESPONSE) {\n\t\t  sprintf(msg, \"DHT11_ERROR_NO_RESPONSE\");\n\t  }\n\t  usb_serial_println(msg); \/\/ Custom wrapper function\n\n\t  HAL_Delay(2000);\n}\n\/* USER CODE END WHILE *\/<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6272A4\">\/* USER CODE BEGIN WHILE *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">uint8_t<\/span><span style=\"color: #F8F8F2\"> temp_int <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">, temp_dec <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">, hum_int <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">, hum_dec <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">0<\/span><span style=\"color: #F8F8F2\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">while<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  <\/span><span style=\"color: #FF79C6\">char<\/span><span style=\"color: #F8F8F2\"> msg&#91;<\/span><span style=\"color: #BD93F9\">64<\/span><span style=\"color: #F8F8F2\">&#93;;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  DHT11_Response response <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">DHT11_Read<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">temp_int, <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">temp_dec, <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">hum_int, <\/span><span style=\"color: #FF79C6\">&amp;<\/span><span style=\"color: #F8F8F2\">hum_dec);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (response <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> DHT11_OK) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t\t  <\/span><span style=\"color: #50FA7B\">sprintf<\/span><span style=\"color: #F8F8F2\">(msg, <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">Temp: <\/span><span style=\"color: #BD93F9\">%d<\/span><span style=\"color: #F1FA8C\">.<\/span><span style=\"color: #BD93F9\">%d<\/span><span style=\"color: #F1FA8C\">C, Humidity: <\/span><span style=\"color: #BD93F9\">%d<\/span><span style=\"color: #F1FA8C\">.<\/span><span style=\"color: #BD93F9\">%d<\/span><span style=\"color: #FF5555; font-style: italic; text-decoration: underline\">%<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">, temp_int, temp_dec, hum_int, hum_dec);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  } <\/span><span style=\"color: #FF79C6\">else<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (response <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_TIMEOUT) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t\t  <\/span><span style=\"color: #50FA7B\">sprintf<\/span><span style=\"color: #F8F8F2\">(msg, <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">DHT11_ERROR_TIMEOUT<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  } <\/span><span style=\"color: #FF79C6\">else<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (response <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_CHECKSUM) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t\t  <\/span><span style=\"color: #50FA7B\">sprintf<\/span><span style=\"color: #F8F8F2\">(msg, <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">DHT11_ERROR_CHECKSUM<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  } <\/span><span style=\"color: #FF79C6\">else<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> (response <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> DHT11_ERROR_NO_RESPONSE) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t\t  <\/span><span style=\"color: #50FA7B\">sprintf<\/span><span style=\"color: #F8F8F2\">(msg, <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">DHT11_ERROR_NO_RESPONSE<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  <\/span><span style=\"color: #50FA7B\">usb_serial_println<\/span><span style=\"color: #F8F8F2\">(msg);<\/span><span style=\"color: #6272A4\"> \/\/ Custom wrapper function<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">\t  <\/span><span style=\"color: #50FA7B\">HAL_Delay<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #BD93F9\">2000<\/span><span style=\"color: #F8F8F2\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6272A4\">\/* USER CODE END WHILE *\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">After building the project and uploading it to the dev board, we get the following output after establishing a serial connection over USB with the microcontroller:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"825\" height=\"521\" src=\"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/image-26.png\" alt=\"\" class=\"wp-image-594\" style=\"width:667px;height:auto\" srcset=\"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/image-26.png 825w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/image-26-300x189.png 300w, https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/image-26-768x485.png 768w\" sizes=\"auto, (max-width: 825px) 100vw, 825px\" \/><figcaption class=\"wp-element-caption\"><strong>Figure 4<\/strong>. Serial output of DHT11 values from STM32 &#8211; heat gun applied briefly to the sensor<\/figcaption><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\">References<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"reference-1\">[1] &#8220;DHT11 basic temperature-humidity sensor + extras,&#8221; <em>Adafruit. <\/em><a href=\"https:\/\/www.adafruit.com\/product\/386\">https:\/\/www.adafruit.com\/product\/386<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"reference-2\">[2] &#8220;Arduino compatible coding 15: Reading sensor data from DHT-11 without using a library&#8221;, <em><a href=\"https:\/\/www.engineersgarage.com\/author\/nikhil-agnihotri\/\">Nikhil Agnihotr<\/a> &#8211; Engineers Garage.<\/em> <a href=\"https:\/\/www.engineersgarage.com\/articles-arduino-dht11-humidity-temperature-sensor-interfacing\/\">https:\/\/www.engineersgarage.com\/articles-arduino-dht11-humidity-temperature-sensor-interfacing\/<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"reference-3\">[3] &#8220;Microsecond delay function for&nbsp;STM32,&#8221; <em>KBIVA.<\/em> <a href=\"https:\/\/kbiva.wordpress.com\/2013\/03\/25\/microsecond-delay-function-for-stm32\/\">https:\/\/kbiva.wordpress.com\/2013\/03\/25\/microsecond-delay-function-for-stm32\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wrote a DHT11 sensor driver for the STM32 at the bit level with microsecond timing and bitwise operations. <\/p>\n","protected":false},"author":1,"featured_media":587,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"[]"},"categories":[20],"tags":[35,9,13,32],"class_list":["post-581","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-electronics","tag-computer-science","tag-electronics","tag-microcontrollers","tag-stm32"],"featured_image_src":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg","author_info":{"display_name":"Darcy","author_link":"https:\/\/darcyjprojects.xyz\/index.php\/author\/darcy\/"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL) - DarcyJProjects<\/title>\n<meta name=\"description\" content=\"I wrote a DHT11 sensor driver for the STM32 at the bit level with microsecond timing and bitwise operations. Source code included.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL) - DarcyJProjects\" \/>\n<meta property=\"og:description\" content=\"I wrote a DHT11 sensor driver for the STM32 at the bit level with microsecond timing and bitwise operations. Source code included.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/\" \/>\n<meta property=\"og:site_name\" content=\"DarcyJProjects\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-21T03:29:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-28T06:34:37+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"970\" \/>\n\t<meta property=\"og:image:height\" content=\"728\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Darcy\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Darcy\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/\"},\"author\":{\"name\":\"Darcy\",\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/#\\\/schema\\\/person\\\/306f478e105fad9940b45593ae5fb6e2\"},\"headline\":\"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL)\",\"datePublished\":\"2025-04-21T03:29:00+00:00\",\"dateModified\":\"2026-05-28T06:34:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/\"},\"wordCount\":1419,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/#\\\/schema\\\/person\\\/306f478e105fad9940b45593ae5fb6e2\"},\"image\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/386-02.jpg\",\"keywords\":[\"Computer Science\",\"Electronics\",\"Microcontrollers\",\"STM32\"],\"articleSection\":[\"Electronics\"],\"inLanguage\":\"en-AU\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/\",\"url\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/\",\"name\":\"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL) - DarcyJProjects\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/386-02.jpg\",\"datePublished\":\"2025-04-21T03:29:00+00:00\",\"dateModified\":\"2026-05-28T06:34:37+00:00\",\"description\":\"I wrote a DHT11 sensor driver for the STM32 at the bit level with microsecond timing and bitwise operations. Source code included.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#breadcrumb\"},\"inLanguage\":\"en-AU\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-AU\",\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#primaryimage\",\"url\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/386-02.jpg\",\"contentUrl\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/386-02.jpg\",\"width\":970,\"height\":728,\"caption\":\"A DHT11 inserted into a small breadboard.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/2025\\\/04\\\/21\\\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/darcyjprojects.xyz\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/#website\",\"url\":\"https:\\\/\\\/darcyjprojects.xyz\\\/\",\"name\":\"DarcyJProjects\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/#\\\/schema\\\/person\\\/306f478e105fad9940b45593ae5fb6e2\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/darcyjprojects.xyz\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-AU\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/#\\\/schema\\\/person\\\/306f478e105fad9940b45593ae5fb6e2\",\"name\":\"Darcy\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-AU\",\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/cropped-logo-5.png\",\"url\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/cropped-logo-5.png\",\"contentUrl\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/cropped-logo-5.png\",\"width\":512,\"height\":512,\"caption\":\"Darcy\"},\"logo\":{\"@id\":\"https:\\\/\\\/darcyjprojects.xyz\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/cropped-logo-5.png\"},\"sameAs\":[\"https:\\\/\\\/www.darcyjprojects.xyz\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/darcywdjohnson\\\/\",\"https:\\\/\\\/youtube.com\\\/@darcyjprojects\"],\"url\":\"https:\\\/\\\/darcyjprojects.xyz\\\/index.php\\\/author\\\/darcy\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL) - DarcyJProjects","description":"I wrote a DHT11 sensor driver for the STM32 at the bit level with microsecond timing and bitwise operations. Source code included.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/","og_locale":"en_US","og_type":"article","og_title":"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL) - DarcyJProjects","og_description":"I wrote a DHT11 sensor driver for the STM32 at the bit level with microsecond timing and bitwise operations. Source code included.","og_url":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/","og_site_name":"DarcyJProjects","article_published_time":"2025-04-21T03:29:00+00:00","article_modified_time":"2026-05-28T06:34:37+00:00","og_image":[{"width":970,"height":728,"url":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg","type":"image\/jpeg"}],"author":"Darcy","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Darcy","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#article","isPartOf":{"@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/"},"author":{"name":"Darcy","@id":"https:\/\/darcyjprojects.xyz\/#\/schema\/person\/306f478e105fad9940b45593ae5fb6e2"},"headline":"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL)","datePublished":"2025-04-21T03:29:00+00:00","dateModified":"2026-05-28T06:34:37+00:00","mainEntityOfPage":{"@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/"},"wordCount":1419,"commentCount":0,"publisher":{"@id":"https:\/\/darcyjprojects.xyz\/#\/schema\/person\/306f478e105fad9940b45593ae5fb6e2"},"image":{"@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#primaryimage"},"thumbnailUrl":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg","keywords":["Computer Science","Electronics","Microcontrollers","STM32"],"articleSection":["Electronics"],"inLanguage":"en-AU","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/","url":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/","name":"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL) - DarcyJProjects","isPartOf":{"@id":"https:\/\/darcyjprojects.xyz\/#website"},"primaryImageOfPage":{"@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#primaryimage"},"image":{"@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#primaryimage"},"thumbnailUrl":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg","datePublished":"2025-04-21T03:29:00+00:00","dateModified":"2026-05-28T06:34:37+00:00","description":"I wrote a DHT11 sensor driver for the STM32 at the bit level with microsecond timing and bitwise operations. Source code included.","breadcrumb":{"@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#breadcrumb"},"inLanguage":"en-AU","potentialAction":[{"@type":"ReadAction","target":["https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/"]}]},{"@type":"ImageObject","inLanguage":"en-AU","@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#primaryimage","url":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg","contentUrl":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/386-02.jpg","width":970,"height":728,"caption":"A DHT11 inserted into a small breadboard."},{"@type":"BreadcrumbList","@id":"https:\/\/darcyjprojects.xyz\/index.php\/2025\/04\/21\/developing-a-bit-banged-dht-11-driver-from-scratch-stm32-hal\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/darcyjprojects.xyz\/"},{"@type":"ListItem","position":2,"name":"Developing a Bit-Banged DHT-11 Driver from Scratch (STM32 HAL)"}]},{"@type":"WebSite","@id":"https:\/\/darcyjprojects.xyz\/#website","url":"https:\/\/darcyjprojects.xyz\/","name":"DarcyJProjects","description":"","publisher":{"@id":"https:\/\/darcyjprojects.xyz\/#\/schema\/person\/306f478e105fad9940b45593ae5fb6e2"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/darcyjprojects.xyz\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-AU"},{"@type":["Person","Organization"],"@id":"https:\/\/darcyjprojects.xyz\/#\/schema\/person\/306f478e105fad9940b45593ae5fb6e2","name":"Darcy","image":{"@type":"ImageObject","inLanguage":"en-AU","@id":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/cropped-logo-5.png","url":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/cropped-logo-5.png","contentUrl":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/cropped-logo-5.png","width":512,"height":512,"caption":"Darcy"},"logo":{"@id":"https:\/\/darcyjprojects.xyz\/wp-content\/uploads\/2025\/04\/cropped-logo-5.png"},"sameAs":["https:\/\/www.darcyjprojects.xyz","https:\/\/www.linkedin.com\/in\/darcywdjohnson\/","https:\/\/youtube.com\/@darcyjprojects"],"url":"https:\/\/darcyjprojects.xyz\/index.php\/author\/darcy\/"}]}},"_links":{"self":[{"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/posts\/581","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/comments?post=581"}],"version-history":[{"count":10,"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/posts\/581\/revisions"}],"predecessor-version":[{"id":671,"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/posts\/581\/revisions\/671"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/media\/587"}],"wp:attachment":[{"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/media?parent=581"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/categories?post=581"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/darcyjprojects.xyz\/index.php\/wp-json\/wp\/v2\/tags?post=581"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}