{"id":4251,"date":"2020-06-24T20:00:13","date_gmt":"2020-06-24T18:00:13","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4251"},"modified":"2025-12-27T17:24:09","modified_gmt":"2025-12-27T16:24:09","slug":"radio-communication-using-nrf24l01-modules-part-3","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/radio-communication-using-nrf24l01-modules-part-3\/","title":{"rendered":"Radio communication using nRF24L01+ modules, part 3"},"content":{"rendered":"\n<p>So far I\u2019ve shown you how to use <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24L01<\/a> with polling and I\u2019ve already started doing something with interrupts. More precisely, I used the data-receive interrupt so that incoming data is read from the chip instead of constantly polling the chip to see whether something has arrived. It may not seem like much, but it was still some wasted time on communicating with the chip. What if we used the full potential of interrupts?<\/p>\n\n\n\n<!--more-->\n\n\n\n<p><strong>I\u2019d also like to remind you that you can <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product\/&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">buy nRF24 modules directly from me<\/a> while supporting me at the same time.<\/strong><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product\/&amp;utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=nrf24&amp;utm_content=nrf24\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"400\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner.jpg\" alt=\"\" class=\"wp-image-1528\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner.jpg 1200w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner-768x256.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner-24x8.jpg 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner-36x12.jpg 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/05\/nRF24L01-baner-160x53.jpg 160w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>The whole series about<a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\"> nRF24L01+<\/a>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/msalamon.pl\/komunikacja-radiowa-z-uzyciem-modulow-nrf24l01-cz-1\/\">Part 1<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/komunikacja-radiowa-z-uzyciem-modulow-nrf24l01-cz-2\/\">Part 2<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/komunikacja-radiowa-z-uzyciem-modulow-nrf24l01-cz-3\/\">Part 3<\/a><\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Interrupts in nRF24<\/h1>\n\n\n\n<p>In our chip we have 3 interrupt sources available:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>data reception completed \u2013 RX_DR<\/li>\n\n\n\n<li>transfer (sending) completed \u2013 TX_DS<\/li>\n\n\n\n<li>maximum number of retransmits exceeded during transmission \u2013 MAX_RT<\/li>\n<\/ul>\n\n\n\n<p>I won\u2019t be dealing with the number of retransmits. Everyone may have their own idea for how to handle it. Whether that\u2019s throwing an error or continuing retransmission attempts. In the library I leave room (a callback) to implement handling of this interrupt.<\/p>\n\n\n\n<p>So we\u2019re left with two. One for data reception, which I already partially implemented. Partially, because I\u2019m going to change the overall handling concept a bit.<\/p>\n\n\n\n<p>The second one is for end of transmission. This interrupt will help us avoid waiting unnecessarily for the end of transfer via <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a>. Thanks to it I\u2019ll free the MCU for other tasks. This will be very useful when I want to send more than 32 bytes \u201cat once\u201d and need to split the message into packets that fit in the nRF\u2019s Payload.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to handle interrupts better?<\/h2>\n\n\n\n<p>First of all, I had to better organize interrupt handling. <strong>Przemys\u0142aw (dambo) rightly pointed out to me that I can have a conflict of interests when it comes to SPI access.<\/strong> Thank you so much for that, because I completely forgot about it!<\/p>\n\n\n\n<p>The conflict would be that an interrupt could come in while SPI is \u201coccupied\u201d in the main program loop. In that interrupt I also needed access to SPI, so there\u2019s a clash because two places in the code want the same SPI \u201cat once\u201d. There are at least two solutions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create a \u201cmutex\u201d for the SPI resource<\/li>\n\n\n\n<li>Handle the interrupt in main<\/li>\n<\/ul>\n\n\n\n<p>I chose option number two. How? In the EXTI interrupt handler I only set a flag that such an interrupt occurred.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void nRF24_IRQ_Handler(void)\n{\n\tNrf24InterruptFlag = 1;\n}<\/pre>\n\n\n\n<p>And that\u2019s it. Thanks to this flag, only in the event from <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a> do I read from the chip\u2019s registers which interrupt occurred and set another flag \u2013 now a specific one for the interrupt type.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void nRF24_IRQ_Read(void)\n{\n\tif(Nrf24InterruptFlag == 1)\n\t{\n\t\tNrf24InterruptFlag = 0;\n\n\t\tuint8_t status = nRF24_ReadStatus();\n\t\tuint8_t ClearIrq = 0;\n\t\t\/\/ RX FIFO Interrupt\n\t\tif ((status &amp;amp; (1 &amp;lt;&amp;lt; NRF24_RX_DR)))\n\t\t{\n\t\t\tnrf24_rx_flag = 1;\n\t\t\tClearIrq |= (1&amp;lt;&amp;lt;NRF24_RX_DR); \/\/ Interrupt flag clear\n\t\t}\n\t\t\/\/ TX Data Sent interrupt\n\t\tif ((status &amp;amp; (1 &amp;lt;&amp;lt; NRF24_TX_DS)))\n\t\t{\n\t\t\tnrf24_tx_flag = 1;\n\t\t\tClearIrq |= (1&amp;lt;&amp;lt;NRF24_TX_DS); \/\/ Interrupt flag clear\n\t\t}\n\t\t\/\/ Max Retransmits interrupt\n\t\tif ((status &amp;amp; (1 &amp;lt;&amp;lt; NRF24_MAX_RT)))\n\t\t{\n\t\t\tnrf24_mr_flag = 1;\n\t\t\tClearIrq |= (1&amp;lt;&amp;lt;NRF24_MAX_RT); \/\/ Interrupt flag clear\n\t\t}\n\n\t\tnRF24_WriteStatus(ClearIrq);\n\t}\n}<\/pre>\n\n\n\n<p><strong>This way I\u2019m sure that SPI will be free.<\/strong> Well, almost, because it could still be occupied by another chip via DMA&#8230; However, when using DMA, in my opinion it\u2019s worth taking the entire interface exclusively for a single chip, so others won\u2019t be able to squeeze in then \ud83d\ude42<\/p>\n\n\n\n<p>Now in the nRF24_Event function I can take care of these flags. At this stage it looks like this.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void nRF24_Event(void)\n{\n\tnRF24_IRQ_Read(); \/\/ Check if there was any interrupt\n\n\tif(nrf24_rx_flag)\n\t{\n\t\tnRF24_EventRxCallback();\n\t\tnrf24_rx_flag = 0;\n\t}\n\n\tif(nrf24_tx_flag)\n\t{\n\t\tnRF24_EventTxCallback();\n\t\tnrf24_tx_flag = 0;\n\t}\n\n\tif(nrf24_mr_flag)\n\t{\n\t\tnRF24_EventMrCallback();\n\t\tnrf24_mr_flag = 0;\n\t}\n}<\/pre>\n\n\n\n<p>We have interrupt reading and reactions to them through callbacks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Data management<\/h2>\n\n\n\n<p>You can now implement all handling in callbacks, but I\u2019ll keep them as an additional layer. <a href=\"http:\/\/msalamon.pl\/zycie-danych-kolem-sie-toczy-czyli-bufor-kolowy\/\">In the previous blog post I introduced you to the idea of a circular buffer.<\/a> I wrote that I want to use it for <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a> transmission. And that\u2019s what I did.<\/p>\n\n\n\n<p>I created <strong>two buffers \u2013 a receive buffer and a transmit buffer<\/strong>. From the names you can already guess what they\u2019re for.<\/p>\n\n\n\n<p>In the receive buffer, data will appear right after it is received, i.e. after the RX_DR interrupt occurs.<\/p>\n\n\n\n<p>In the transmit buffer, on the other hand, we will write what we want to send. The library, or rather the event function, will check whether there is something to send and if the radio is free it will send what is in the buffer.<\/p>\n\n\n\n<p>Thanks to such a solution, we don\u2019t care what <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24L01<\/a> is doing at the moment. We push data into and pull data out of the buffers whenever it\u2019s convenient for us. What\u2019s more! I\u2019ll show you that you don\u2019t have to worry about the 32-byte Payload limit! You can handle it automatically.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ring buffers<\/h2>\n\n\n\n<p>I slightly modified the buffer I described previously. The educational implementation was very simple. Here I need something more advanced, but not necessarily full of unnecessary functions.<\/p>\n\n\n\n<p>First, I dealt with buffer size. <strong>Instead of a fixed size for each buffer, I allowed myself to use something that in the C99 standard is called a <em>Flexible array member<\/em><\/strong>. In short, the last element in a data structure can be a dynamic array. That will be my data buffer. Thanks to this I can have a small transmit buffer and a large receive buffer if needed.<\/p>\n\n\n\n<p>Using FAM means the objects must be created dynamically using malloc. The structure definition looks like this.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">typedef struct\n{\n\tuint8_t Size;\n\tuint8_t Head;\n\tuint8_t Tail;\n\tuint8_t Elements;\n\tuint8_t Buffer[];\t\/\/ Flexible Array Member\n} RingBuffer;<\/pre>\n\n\n\n<p>As you can see, the last element is a pointer to an array. Interestingly, <strong>if you do sizeof(RingBuffer), it will return the value 4 as if that array wasn\u2019t there at all<\/strong> \ud83d\ude42<\/p>\n\n\n\n<p>How do you create such a buffer now?<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">RB_Status RB_CreateBuffer(RingBuffer **Buffer, uint8_t Size)\n{\n\t*Buffer = malloc(sizeof(RingBuffer) + (sizeof(uint8_t) * Size));\n\n\tif(Buffer == NULL)\n\t{\n\t\treturn RB_NOTCREATED;\n\t}\n\n\t(*Buffer)-&amp;gt;Size = Size;\n\t(*Buffer)-&amp;gt;Head = 0;\n\t(*Buffer)-&amp;gt;Tail = 0;\n\t(*Buffer)-&amp;gt;Elements = 0;\n\n\treturn RB_OK;\n}<\/pre>\n\n\n\n<p>In malloc you provide the size of the structure plus the number of elements in the array. That\u2019s it.<\/p>\n\n\n\n<p>As you can see, in the structure I created a <em>Size<\/em> field. Now you have to remember what size the buffer is, because each one can be different. The <em>Elements<\/em> field will tell us how much data is currently stored.<\/p>\n\n\n\n<p>For working with <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a> I also created a function that returns exactly how many elements the buffer holds.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">uint8_t RB_ElementsAvailable(RingBuffer *Buffer)\n{\n\treturn Buffer-&amp;gt;Elements;\n}<\/pre>\n\n\n\n<p>Buffers are created during <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a> initialization and are visible only within its library.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Receiving data<\/h2>\n\n\n\n<p>Data reception happens when the <em>nrf24_rx_flag<\/em> flag is set. It is implemented similarly to the <a href=\"http:\/\/msalamon.pl\/komunikacja-radiowa-z-uzyciem-modulow-nrf24l01-cz-2\/\">previous post<\/a>, with the difference that I write the data into the internal ring buffer.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void nRF24_ReceiveData(void)\n{\n\tuint8_t i, DataCounter;\n\tuint8_t RXPacket[32];\n\tdo\n\t{\n\t\tnRF24_ReceivePacket(RXPacket, &amp;amp;DataCounter);\n\n\t\tfor(i = 0; i &amp;lt; DataCounter; i++)\n\t\t{\n\t\t\tRB_WriteToBuffer(RXBuffer, RXPacket[i]);\n\t\t}\n\n\t}while(!nRF24_IsRxEmpty());\n}<\/pre>\n\n\n\n<p>Now, to use this data, it\u2019s enough to \u201cread\u201d it from <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a>. If the returned amount of data equals zero, it means nothing arrived.&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">nRF24_ReadData(Message, &amp;amp;MessageLength);\nif(MessageLength &amp;gt; 0)\n{\n\tHAL_UART_Transmit(&amp;amp;huart2, Message, MessageLength, 1000);\n}<\/pre>\n\n\n\n<p>The function returns as much as there is available data in the buffer \u2013 there is no Payload-related limitation.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">nRF24_RX_Status nRF24_ReadData(uint8_t *Data, uint8_t *Size)\n{\n\tuint8_t i = 0;\n\t*Size = 0;\n\n\t  if(nRF24_RXAvailable())\n\t  {\n\t\twhile(RB_OK == RB_ReadFromBuffer(RXBuffer, &amp;amp;Data[i]))\n\t\t{\n\t\t\ti++;\n\t\t}\n\t\t*Size = i;\n\t  }\n\tif(*Size == 0)\n\t{\n\t\treturn NRF24_NO_RECEIVED_PACKET;\n\t}\n\n\treturn NRF24_RECEIVED_PACKET;\n}<\/pre>\n\n\n\n<p>Meanwhile, checking whether there is something to read in the ring-buffer version is simply checking whether there is something in the buffer.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">uint8_t nRF24_RXAvailable(void)\n{\n\treturn nRF24_IsSomtehingToRead();\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Transmitting data<\/h2>\n\n\n\n<p>Now we operate the other way around. We write to the buffer, and the library checks whether there is something to send and sends it.<\/p>\n\n\n\n<p>Writing to the nRF buffer happens \u2013 you could say \u2013 \u201cnormally\u201d.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">MessageLength = sprintf(Message, \"abcdefghijklmnopqrstuwxyz1234567890\\n\\r\" );\nnRF24_SendData(Message, MessageLength);<\/pre>\n\n\n\n<p>This gets put into the transmit buffer.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">nRF24_TX_Status nRF24_SendData(uint8_t* Data, uint8_t Size)\n{\n\tuint8_t i = 0;\n\n\twhile(Size &amp;gt; 0)\n\t{\n\t\tif(RB_OK == RB_WriteToBuffer(TXBuffer, Data[i++]))\n\t\t{\n\t\t\tSize--;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn NRF24_NO_TRANSMITTED_PACKET;\n\t\t}\n\t}\n\treturn NRF24_TRANSMITTED_PACKET;\n}<\/pre>\n\n\n\n<p>Then, when the <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a> event comes, the library checks whether there is something to transmit. The radio must also be free, so I created another flag \u2013 <em>Nrf24TXFreeFlag<\/em>.<\/p>\n\n\n\n<p>This flag is cleared according to its name, so zeroed means the radio is currently not free<em>.<\/em> Next I retrieve the number of bytes to send. <strong>If it\u2019s larger than the maximum possible Payload, I cap it at 32 bytes.<\/strong> I read the required amount of data and send it to the chip.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void nRF24_CheckTXAndSend(void)\n{\n\tuint8_t i, DataCounter;\n\tuint8_t TXPacket[32];\n\n\tif(nRF24_IsSomtehingToSend() &amp;amp;&amp;amp; Nrf24TXFreeFlag)\n\t{\n\t\tnRF24_TX_Mode();\n\n\t\tNrf24TXFreeFlag = 0;\n\t\tDataCounter = RB_ElementsAvailable(TXBuffer);\n\t\tif(DataCounter &amp;gt; 32)\n\t\t{\n\t\t\tDataCounter = 32; \/\/ Max Payload\n\t\t}\n\n\t\tfor(i = 0; i &amp;lt; DataCounter; i++)\n\t\t{\n\t\t\tRB_ReadFromBuffer(TXBuffer, &amp;amp;TXPacket[i]);\n\t\t}\n\n\t\tnRF24_SendPacket(TXPacket, DataCounter);\n\t\tNRF24_CE_HIGH;\n\t\tnRF24_Delay_ms(1);\n\t\tNRF24_CE_LOW;\n\t}\n}<\/pre>\n\n\n\n<p>You may notice there is one Delay here. In fact, it should last about 130 \u00b5s, because that\u2019s how long the transition between <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24<\/a> states takes, but the delay resolution in HAL is 1 ms. It\u2019s a fairly small one, but you can insist on removing it. The idea for removing it came to me only while writing this text.<\/p>\n\n\n\n<p>Ok, we sent data to the chip, and what next? After all, we have the <em>Nrf24TXFreeFlag<\/em> flag cleared, and to send more data we need to set it.<\/p>\n\n\n\n<p><strong>This is where the TX_DS interrupt rides in on a white horse, telling us that the radio transmission has finished. <\/strong>In the event, when the TX_DS flag appears, I set <em>Nrf24TXFreeFlag<\/em>, which means the next data can be sent. <strong>This may be the next part of a message if it was longer than 32 bytes.<\/strong><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/?utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=nrf24&amp;utm_content=nucleo\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"400\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg\" alt=\"\" class=\"wp-image-1593\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg 1200w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-768x256.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How the library works and what it looks like<\/h2>\n\n\n\n<p>The current shape of the library is quite complex and unfortunately not very readable&#8230; All because I insisted that one set of files should handle three cases:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Polling<\/li>\n\n\n\n<li>Receive on interrupt, send on polling<\/li>\n\n\n\n<li>Everything on interrupt<\/li>\n<\/ol>\n\n\n\n<p>Several defines are used to configure the entire library<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/\n\/\/\tConfiguration\n\/\/\n#define NRF24_USE_INTERRUPT\t\t1\n#if (NRF24_USE_INTERRUPT == 1)\n#define NRF24_USE_RINGBUFFER\t1\n#endif\n\n\n#define NRF24_DYNAMIC_PAYLOAD\t1\n\n#if (NRF24_USE_RINGBUFFER == 1)\n#define NRF24_RX_BUFFER_SIZE 32\n#define NRF24_TX_BUFFER_SIZE 32\n#endif<\/pre>\n\n\n\n<p>I think it\u2019s easy to guess what they switch. In the article I omitted these different options in the functions for the sake of better readability of the ring-buffer part itself.<\/p>\n\n\n\n<p>I wrote it all so that in all modes you use exactly the same functions for receiving and transmitting, so the final use of the library is quite simple. It always boils down to initialization and three basic functions.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#if (NRF24_USE_INTERRUPT == 1)\n\/\/\n\/\/\tMain event for whole communication\n\/\/\tPut it in main while(1) loop\n\/\/\nvoid nRF24_Event(void);\n#endif\n\n\/\/\n\/\/ TRANSMITTING DATA\n\/\/\nnRF24_TX_Status nRF24_SendData(uint8_t *Data, uint8_t Size);\nnRF24_RX_Status nRF24_ReadData(uint8_t *Data, uint8_t *Size);<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>At this moment, in my opinion the library is finished. There are still a few minor things to improve, like that small delay during transmission, but it\u2019s not that necessary. I tested transmitting and receiving quite \u201cstressfully\u201d by trying to send multiples of the Payload at once. On both the transmitter and receiver side everything worked perfectly, so I consider my library a success.<\/p>\n\n\n\n<p>I\u2019d be happy to hear your opinion about my code and suggestions for possible fixes or improvements. I\u2019m open to discussion \ud83d\ude42<\/p>\n\n\n\n<p>For now, that\u2019s all about <a href=\"https:\/\/sklep.msalamon.pl\/?s=nrf24&amp;post_type=product&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">nRF24L01+<\/a>. In the future I\u2019ll come back with range testing, but I have to build a measurement setup. Maybe we\u2019ll do it together on a LIVE? \ud83d\ude42<\/p>\n\n\n\n<p>The whole series:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/msalamon.pl\/komunikacja-radiowa-z-uzyciem-modulow-nrf24l01-cz-1\/\">Part 1<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/komunikacja-radiowa-z-uzyciem-modulow-nrf24l01-cz-2\/\">Part 2<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/komunikacja-radiowa-z-uzyciem-modulow-nrf24l01-cz-3\/\">Part 3<\/a><\/li>\n<\/ul>\n\n\n\n<p>If you enjoyed the article, you can support me by buying something from me \ud83d\ude42 <a href=\"https:\/\/sklep.msalamon.pl\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=nrf24&amp;utm_content=Text\">https:\/\/sklep.msalamon.pl\/<\/a><\/p>\n\n\n\n<p>The full project along with the library can be found, as usual, on my GitHub: <a href=\"https:\/\/github.com\/lamik\/nRF24L01_Transmitter\" target=\"_blank\" rel=\"noopener\">TRANSMITTER<\/a>, <a href=\"https:\/\/github.com\/lamik\/nRF24L01_Receiver\/\" target=\"_blank\" rel=\"noopener\">RECEIVER<\/a><\/p>\n\n\n\n<p><span>If you noticed an error, disagree with something, would like to add something important, or simply feel like you\u2019d like to discuss this topic, write a comment. Remember that the discussion should be polite and in accordance with the rules of the Polish language.<\/span><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;4251&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;0&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 - (0 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Radio communication using nRF24L01+ modules, part 3&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>So far I\u2019ve shown you how to use nRF24L01 with polling and I\u2019ve already started doing something with interrupts. More precisely, I used the data-receive interrupt so that incoming data is read from the chip instead of constantly polling the chip to see whether something has arrived. It may not [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3452,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[175,176,174],"class_list":["post-4251","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-electronics","tag-programming","tag-stm32"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4251","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/comments?post=4251"}],"version-history":[{"count":3,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4251\/revisions"}],"predecessor-version":[{"id":4368,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4251\/revisions\/4368"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/3452"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4251"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4251"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4251"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}