{"id":1839,"date":"2023-06-20T14:12:49","date_gmt":"2023-06-20T14:12:49","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1839"},"modified":"2023-06-20T14:12:52","modified_gmt":"2023-06-20T14:12:52","slug":"getting-started-with-stm32f103-spi-full-duplex-using-dma","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1839","title":{"rendered":"Getting Started with STM32F103: SPI Full Duplex using DMA"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-1024x683.jpeg\" alt=\"\" class=\"wp-image-1840\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-1024x683.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-300x200.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-768x512.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-1536x1024.jpeg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-1150x766.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-750x500.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-400x267.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1-250x167.jpeg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/AdobeStock_122425803-2048x1365-1.jpeg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=1659\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=1659\" target=\"_blank\">here<\/a>), we took a look how to transmit data over SPI bus using DMA. In this guide, we shall use DMA with SPI in full duplex to transmit and receive at the same time. This will free the CPU to do something else (not covered in this guide).<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Enable DMA RX for SPI.<\/li><li>DMA configuration.<\/li><li>Receive data over DMA<\/li><li>MPU9250 Connection.<\/li><li>Code modification.<\/li><li>Code.<\/li><li>Results.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Enable DMA RX for SPI:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Open spi.h header and declare the following two enums:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">typedef enum\n{\n\tTx_Done=1,\n\tTX_Inprogress=0\n\n}SPI_TXStatus;\n\ntypedef enum\n{\n\tRx_Done=1,\n\tRX_Inprogress=0\n\n}SPI_RXStatus;<\/pre><\/div>\n\n\n\n<p>Include these two new function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void reset_finished();\nuint8_t finished_receive();\nvoid SPI_DMA_Receive(uint8_t *data,uint32_t size);<\/pre><\/div>\n\n\n\n<p>Hence, the entire header file as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#ifndef SPI_H_\n#define SPI_H_\n\n#include &quot;stdint.h&quot;\n\n\nvoid spi_DMA_Init(void);\nvoid SPI_DMA_Transmit(uint8_t *data,uint32_t size);\nuint8_t finished_transfer();\nvoid reset_finished();\nuint8_t finished_receive();\nvoid SPI_DMA_Receive(uint8_t *data,uint32_t size);\nvoid spi_transmit(uint8_t *data,uint32_t size);\n\n\nvoid cs_low();\nvoid cs_high();\n\n\ntypedef enum\n{\n\tTx_Done=1,\n\tTX_Inprogress=0\n\n}SPI_TXStatus;\n\ntypedef enum\n{\n\tRx_Done=1,\n\tRX_Inprogress=0\n\n}SPI_RXStatus;\n\n\n#endif \/* SPI_H_ *\/\n<\/pre><\/div>\n\n\n\n<p>In order to configure SPI to receive data using DMA, we need to enable RXDMA bit in CR2 register:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"254\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-1024x254.png\" alt=\"\" class=\"wp-image-1841\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-1024x254.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-300x74.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-768x191.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-1536x381.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-2048x508.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-1150x285.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-750x186.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-400x99.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.43.53-PM-250x62.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Set RXDMA bit in CR2*\/\n\tSPI1-&gt;CR2|=SPI_CR2_RXDMAEN;<\/pre><\/div>\n\n\n\n<p>Thats all for SPI section.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. DMA Configuration:<\/h2>\n\n\n\n<p>Before we configure the DMA, we need to which channel is responsible for SPI1 RX:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"455\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-1024x455.png\" alt=\"\" class=\"wp-image-1842\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-1024x455.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-300x133.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-768x341.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-1536x683.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-2048x910.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-1150x511.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-750x333.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-400x178.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.46.15-PM-250x111.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>From DMA1 request map, we can see that DMA1 Channel2 is responsible for SPI RX:<\/p>\n\n\n\n<p>The DMA configuration as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Memory Increment mode.<\/li><li>Read from peripheral.<\/li><li>Transfer complete interrupt.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"368\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-1024x368.png\" alt=\"\" class=\"wp-image-1843\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-1024x368.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-300x108.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-768x276.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-1536x552.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-2048x736.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-1150x413.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-750x269.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-400x144.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.49.01-PM-250x90.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tDMA1_Channel2-&gt;CCR|=DMA_CCR_MINC|DMA_CCR_TCIE;<\/pre><\/div>\n\n\n\n<p>Set peripheral to be SPI1-&gt;DR:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Set Peripheral Address to be SPI1-&gt;DR*\/\n\tDMA1_Channel2-&gt;CPAR=(uint32_t)&amp; SPI1-&gt;DR;<\/pre><\/div>\n\n\n\n<p>Enable Interrupt of DMA1_Channel2 in NVIC:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Enable DMA1_Channel3 interrupt in NVIC*\/\n\n\tNVIC_EnableIRQ(DMA1_Channel2_IRQn);<\/pre><\/div>\n\n\n\n<p>Since we are using interrupt, we need to declare a variable to indicate that receiving data is finished:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">volatile uint8_t SPI_Transfer_RX_Finished=0;<\/pre><\/div>\n\n\n\n<p>We shall also check if all data has been received:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t finished_receive()\n{\n\treturn SPI_Transfer_RX_Finished;\n}<\/pre><\/div>\n\n\n\n<p>Clear flags:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void reset_finished()\n{\n\tSPI_Transfer_TX_Finished=0;\n\tSPI_Transfer_RX_Finished=0;\n}\n<\/pre><\/div>\n\n\n\n<p>Interrupt handler for DAM1_Channel2:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void DMA1_Channel2_IRQHandler (void)\n{\n\t\/*Check if the source is transfer complete*\/\n\n\tif((DMA1-&gt;ISR &amp; DMA_ISR_TCIF2) == DMA_ISR_TCIF2)\n\t{\n\t\t\/*Set flag to 1*\/\n\t\tSPI_Transfer_RX_Finished=1;\n\n\t\t\/*Disable DMA *\/\n\t\tDMA1_Channel2-&gt;CCR &amp;= ~DMA_CCR_EN;\n\n\t\t\/*Clear pending flag*\/\n\t\tDMA1-&gt;IFCR = DMA_IFCR_CTCIF2;\n\t}\n}<\/pre><\/div>\n\n\n\n<p>The function will check if the source is transfer complete and do the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Set RX flag to 1.<\/li><li>Disable the DMA channel.<\/li><li>Clear the pending flag.<\/li><\/ul>\n\n\n\n<p>That all for DMA configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Receive Data using DMA:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>We shall declare the following function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void SPI_DMA_Receive(uint8_t *data,uint32_t size)<\/pre><\/div>\n\n\n\n<p>The function takes two arguments:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Pointer to buffer to be filled.<\/li><li>Size of the buffer.<\/li><\/ul>\n\n\n\n<p>Within the function:<\/p>\n\n\n\n<p>Clear the pending flag:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\/*Clear pending flag*\/\n\tDMA1-&gt;IFCR = DMA_IFCR_CTCIF2;<\/pre><\/div>\n\n\n\n<p>Set the peripheral address to be SPI1-&gt;DR:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Set Peripheral Address to be SPI1-&gt;DR*\/\n\tDMA1_Channel2-&gt;CPAR=(uint32_t)&amp; SPI1-&gt;DR;<\/pre><\/div>\n\n\n\n<p>Set the memory address to be the buffer passed by the user:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">DMA1_Channel2-&gt;CMAR=(uint32_t)data;<\/pre><\/div>\n\n\n\n<p>Set the number of transfer to be size of the buffer:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\tDMA1_Channel2-&gt;CNDTR=size;<\/pre><\/div>\n\n\n\n<p>Launch the DMA Channel:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\/*Launch DMA*\/\n\tDMA1_Channel2-&gt;CCR |= DMA_CCR_EN;<\/pre><\/div>\n\n\n\n<p>Hence, the function as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void SPI_DMA_Receive(uint8_t *data,uint32_t size)\n{\n\t\/*Clear pending flag*\/\n\tDMA1-&gt;IFCR = DMA_IFCR_CTCIF2;\n\n\t\/*Set Peripheral Address to be SPI1-&gt;DR*\/\n\tDMA1_Channel2-&gt;CPAR=(uint32_t)&amp; SPI1-&gt;DR;\n\n\tDMA1_Channel2-&gt;CMAR=(uint32_t)data;\n\n\tDMA1_Channel2-&gt;CNDTR=size;\n\n\t\/*Launch DMA*\/\n\tDMA1_Channel2-&gt;CCR |= DMA_CCR_EN;\n\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. MPU9250 Connection:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"777\" height=\"894\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Untitled-Sketch_bb.png\" alt=\"\" class=\"wp-image-1844\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Untitled-Sketch_bb.png 777w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Untitled-Sketch_bb-261x300.png 261w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Untitled-Sketch_bb-768x884.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Untitled-Sketch_bb-750x863.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Untitled-Sketch_bb-400x460.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Untitled-Sketch_bb-250x288.png 250w\" sizes=\"(max-width: 777px) 100vw, 777px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The connection as following:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>MPU9250<\/td><td>STM32F103<\/td><\/tr><tr><td>Vcc<\/td><td>3V3<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><\/tr><tr><td>SCL<\/td><td>PA5<\/td><\/tr><tr><td>SDA<\/td><td>PA7<\/td><\/tr><tr><td>AD0<\/td><td>PA6<\/td><\/tr><tr><td>NCS<\/td><td>PA0<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Also, FTDI RX pin is connected to PA2 of STM32F103.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Code modification:<\/h2>\n\n\n\n<p>In order to read from MPU9250 using SPI:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t MPU9250_accelUpdate(void)\n{\n\tuint8_t data[6]={0x3B|READ_FLAG,0xFF,0xFF,0xFF,0xFF,0xFF};\n\tcs_low();\n\tSPI_DMA_Receive(accelBuf, 6);\n\tSPI_DMA_Transmit(data, 6);\n\twhile(finished_receive()==RX_Inprogress);\n\treset_finished();\n\tcs_high();\n\treturn 0;\n \n}<\/pre><\/div>\n\n\n\n<p>Declare a buffer which will hold 6 bytes where first byte is the address to be read with read flag and 5 bytes of dummy data to keep the clock generated.<\/p>\n\n\n\n<p>Set the cs pin to low.<\/p>\n\n\n\n<p>start SPI_RX_DMA.<\/p>\n\n\n\n<p>transfer the address to be send with dummy data.<\/p>\n\n\n\n<p>wait until rx finished transfer.<\/p>\n\n\n\n<p>Set CS to high.<\/p>\n\n\n\n<p>Same thing goes to gyroscope:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t MPU9250_gyroUpdate(void)\n{\n\tuint8_t data[6]={0x43|READ_FLAG,0xFF,0xFF,0xFF,0xFF,0xFF};\n\tcs_low();\n\tSPI_DMA_Receive(gyroBuf,6);\n\tSPI_DMA_Transmit(data, 6);\n\twhile(finished_receive()==RX_Inprogress);\n\tcs_high();\n\treset_finished();\n\treturn 0;\n}<\/pre><\/div>\n\n\n\n<p>In main.c:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;spi.h&quot;\n#include &quot;uart.h&quot;\n#include &quot;MPU9250.h&quot;\n\nint main(void)\n{\n\n\tspi_DMA_Init();\n\n\tuart2_init();\n\n\tMPU9250_beginAccel(ACC_FULL_SCALE_16_G);\n\n\tMPU9250_beginGyro(GYRO_FULL_SCALE_2000_DPS);\n\n\twhile(1)\n\t{\n\t\tMPU9250_accelUpdate();\n\t\tMPU9250_gyroUpdate();\n\t\tprintf(&quot;---------------------------------------------\\r\\n&quot;);\n\t\tprintf(&quot;Acceleration data %0.3f %0.3f %0.3f \\r\\n&quot;,MPU9250_accelX(),MPU9250_accelY(),MPU9250_accelZ());\n\t\tprintf(&quot;Gyroscope data %0.3f %0.3f %0.3f \\r\\n&quot;,MPU9250_gyroX(),MPU9250_gyroY(),MPU9250_gyroZ());\n\t\tprintf(&quot;---------------------------------------------\\r\\n&quot;);\n\t\tfor (int i=0;i&lt;100000;i++);\n\t}\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Code:<\/h2>\n\n\n\n<p>You may download the full code from here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/SPI_Full_Duplex_DMA.zip\">SPI_Full_Duplex_DMA<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/SPI_Full_Duplex_DMA.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Results:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Upload the code and open serial terminal and set baud rate to 115200 and you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1010\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-1010x1024.png\" alt=\"\" class=\"wp-image-1846\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-1010x1024.png 1010w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-296x300.png 296w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-768x779.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-1150x1166.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-750x760.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-400x405.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM-250x253.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/06\/Screenshot-2023-06-20-at-4.14.54-PM.png 1170w\" sizes=\"(max-width: 1010px) 100vw, 1010px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we took a look how to transmit data over SPI bus using DMA. In this guide, we shall use DMA with SPI in full duplex to transmit and receive at the same time. This will free the CPU to do something else (not covered in this guide). In this guide, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-1839","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1839"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1839"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1839\/revisions"}],"predecessor-version":[{"id":1847,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1839\/revisions\/1847"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1839"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1839"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}