{"id":2207,"date":"2023-12-24T05:21:45","date_gmt":"2023-12-24T05:21:45","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=2207"},"modified":"2023-12-24T05:21:47","modified_gmt":"2023-12-24T05:21:47","slug":"revisedworking-with-stm32-and-spi-send-bytes-using-dma","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=2207","title":{"rendered":"[Revised]Working with STM32 and SPI : Send bytes 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\/12\/AdobeStock_122425803-2048x1365-1-1024x683.jpeg\" alt=\"\" class=\"wp-image-2208\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-1024x683.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-300x200.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-768x512.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-1536x1024.jpeg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-1150x766.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-750x500.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-400x267.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1-250x167.jpeg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/AdobeStock_122425803-2048x1365-1.jpeg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In this revised version of SPI TX with DMA, we shall see how to transmit data over SPI using DMA.<\/p>\n\n\n\n<p>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=466\" target=\"_blank\">here<\/a>), we discussed how to send a single character using SPI in polling mode. This method will decrease the CPU performance since the CPU has to wait for each time before sending the character. In this guide, we shall introduce DMA to send number of byte without blocking the operation of the CPU.<\/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>SPI Pins initialization.<\/li><li>SPI configuration.<\/li><li>DMA configuration.<\/li><li>SPI Interrupt handler<\/li><li>SPI DMA send function.<\/li><li>Header file.<\/li><li>Main code.<\/li><li>Results.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. SPI initialization:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Create new source and header file with name of SPI.c and SPI.h respectively.<\/p>\n\n\n\n<p>Within the source file:<\/p>\n\n\n\n<p>Include the following header file:<\/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\n#include &quot;stm32f4xx.h&quot;<\/pre><\/div>\n\n\n\n<p>next, define a macros that will hold the alternate function number as mentioned <a href=\"https:\/\/blog.embeddedexpert.io\/?p=466\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=466\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\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;}\">#define AF_SPI1 0x05<\/pre><\/div>\n\n\n\n<p>Declare the SPI pins initialization 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 SPI1_Pins_Init(void)<\/pre><\/div>\n\n\n\n<p>Within the function:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Enable clock access to GPIOA.<\/li><li>Set PA5, PA6 and PA7 to alternate function.<\/li><li>Select which alternate function to use.<\/li><\/ul>\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 SPI1_Pins_Init(void)\n{\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable clock for GPIOA\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1; \/\/set PA5, PA6 and PA7 to alternate function mode\n\tGPIOA-&gt;MODER &amp;=~(GPIO_MODER_MODE5_0|GPIO_MODER_MODE6_0|GPIO_MODER_MODE7_0);\n\n\tGPIOA-&gt;AFR[0]|=(AF_SPI1&lt;&lt;GPIO_AFRL_AFSEL5_Pos)|(AF_SPI1&lt;&lt;GPIO_AFRL_AFSEL6_Pos)|(AF_SPI1&lt;&lt;GPIO_AFRL_AFSEL7_Pos);\n}<\/pre><\/div>\n\n\n\n<p>Now declare the following function which will initialize the 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;}\">void SPI1_Init(void)<\/pre><\/div>\n\n\n\n<p>The SPI configuration as following:<\/p>\n\n\n\n<p>In Control Register 1 (CR1):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Enable Clock access to SPI<\/li><li>Baud to be Fclk\/8 (according to your application).<\/li><li>CPOL and CPHA to 0 (according to your application also).<\/li><li>Full duplex mode.<\/li><li>Master Mode.<\/li><li>Software slave management.<\/li><li>8-bit data mode.<\/li><\/ul>\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\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-1024x254.png\" alt=\"\" class=\"wp-image-2209\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-1024x254.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-300x74.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-768x191.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-1536x381.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-2048x508.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-1150x285.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-750x186.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-400x99.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.45.00\u202fAM-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\/*Enable clock access to SPI1 module*\/\n\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\n\t\/*Set clock to fPCLK\/8*\/\n\tSPI1-&gt;CR1 |=(SPI_CR1_BR_1);\n\n\t\/*Set CPOL to 0 and CPHA to 0*\/\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_CPOL;\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_CPHA;\n\n\t\/*Enable full duplex*\/\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_RXONLY;\n\n\t\/*Set MSB first*\/\n\tSPI1-&gt;CR1 &amp;= ~SPI_CR1_LSBFIRST;\n\n\t\/*Set mode to MASTER*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_MSTR;\n\n\t\/*Set 8 bit data mode*\/\n\tSPI1-&gt;CR1 &amp;= ~SPI_CR1_DFF;\n\n\t\/*Select software slave management by\n\t* setting SSM=1 and SSI=1*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SSI;\n\tSPI1-&gt;CR1 |= SPI_CR1_SSM;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In Control Register 2 (CR2):<\/p>\n\n\n\n<p>Enable Tx buffer DMA enable:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"224\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-1024x224.png\" alt=\"\" class=\"wp-image-2210\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-1024x224.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-300x66.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-768x168.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-1536x336.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-2048x448.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-1150x252.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-750x164.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-400x88.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-7.51.52\u202fAM-250x55.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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 SPI TX with DMA*\/\n\tSPI1-&gt;CR2|=SPI_CR2_TXDMAEN;<\/pre><\/div>\n\n\n\n<p>Enable SPI interrupt 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 SPI1 Interrupt in NVIC*\/\n\tNVIC_EnableIRQ(SPI1_IRQn);<\/pre><\/div>\n\n\n\n<p>Finally Enable SPI peripheral:<\/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 SPI module*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SPE;<\/pre><\/div>\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 the Initializing, we need to know which Stream and Channel is Connected to SPI_TX<\/p>\n\n\n\n<p>According the figure below, we have two options, either Stream 5 or Stream 3 and both on Channel 3.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"504\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-1024x504.png\" alt=\"\" class=\"wp-image-2211\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-1024x504.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-300x148.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-768x378.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-1536x756.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-1150x566.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-750x369.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-400x197.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1-250x123.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screen-Shot-2021-10-04-at-8.37.23-AM-2048x1008-1.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In our case, we shall use Stream 3.<\/p>\n\n\n\n<p>Declare the following function will enable clock access to DMA2:<\/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 DMA2_CLK_Init(void)\n{\n\t\/*Enable Clock access to DMA2*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_DMA2EN;\n}<\/pre><\/div>\n\n\n\n<p>For the DMA2_Stream3 configuration:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Channel number is 3.<\/li><li>Direction is Memory to peripheral.<\/li><li>Memory increment mode.<\/li><li>Enable Transfer Complete Interrupt.<\/li><li>Enable DMA2_Stream3 Interrupt in NVIC.<\/li><\/ul>\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 DMA2_Stream3_CH2_Config(void)\n{\n\t\/*Disable the Stream and make sure it is disabled*\/\n\tDMA2_Stream3-&gt;CR&amp;=~DMA_SxCR_EN;\n\n\twhile((DMA2_Stream3-&gt;CR)&amp;DMA_SxCR_EN){;}\n\n\t\/*Configure the DMA with the following parameters\n\t *\n\t * CH -&gt; channel 3.\n\t * Memory increment mode.\n\t * Enable Transfer Complete interrupt\n\t * *\/\n  #define ch3\t\t(0x03&lt;&lt;25)\n\tDMA2_Stream3-&gt;CR=ch3|DMA_SxCR_MINC|DMA_SxCR_DIR_0|DMA_SxCR_TCIE;\n\n\t\/*Enable DMA2_Stream3 interrupt in NVIC*\/\n\tNVIC_EnableIRQ(DMA2_Stream3_IRQn);\n\n}\n<\/pre><\/div>\n\n\n\n<p>For DMA2_Stream3 Interrupt handler:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Check if the source transfer complete, if it is, enable Tx Buffer empty interrupt for SPI1.<\/li><li>Clear the pending flag.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"224\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-1024x224.png\" alt=\"\" class=\"wp-image-2212\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-1024x224.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-300x66.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-768x168.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-1536x336.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-2048x448.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-1150x252.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-750x164.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-400x88.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-24-at-8.00.16\u202fAM-250x55.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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 DMA2_Stream3_IRQHandler(void)\n{\n\tif(DMA2-&gt;LISR&amp;(DMA_LISR_TCIF3))\n\t{\n\t\t\/*Enable SPI Tx buffer empty interrupt *\/\n\n\t\tSPI1-&gt;CR2|=SPI_CR2_TXEIE;\n\n\t\t\/*Clear pending flag*\/\n\t\tDMA2-&gt;LIFCR |=DMA_LIFCR_CTCIF3;\n\t}\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. SPI Interrupt Handler:<\/h2>\n\n\n\n<p>For the SPI interrupt handler:<\/p>\n\n\n\n<p>Check if the source of the interrupt is Tx buffer is empty and the bus is not busy, it those two condition met:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Call SPI_TX_Finished.<\/li><li>Disable Tx buffer is empty interrupt.<\/li><\/ul>\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;}\">__WEAK void SPI_TX_Finished(void)\n{\n\t\/*Override with user code*\/\n}\n\nvoid SPI1_IRQHandler(void)\n{\n\tif ((SPI1-&gt;SR &amp; SPI_SR_TXE) &amp;&amp; ((SPI1-&gt;SR &amp; SPI_SR_BSY)==0))\n\t{\n\t\t\/*Set finished to 1*\/\n\t\tSPI_TX_Finished();\n\n\t\t\/*Disable SPI Tx Buffer empty interrupt*\/\n\t\tSPI1-&gt;CR2&amp;=~SPI_CR2_TXEIE;\n\n\n\n\n\t}\n}<\/pre><\/div>\n\n\n\n<p>Note: SPI_TX_Finished is defined as weak function and can be overridden by the user.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. SPI DMA Send function:<\/h2>\n\n\n\n<p>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 SPI1_TX_DMA(uint8_t *data,uint16_t len)<\/pre><\/div>\n\n\n\n<p>This function will send data using DMA over SPI and it takes two parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Pointer to the data to be sent.<\/li><li>Length of the data.<\/li><\/ul>\n\n\n\n<p>Within the function:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Clear transfer completed interrupt flag.<\/li><li>Set the peripheral address to be SPI1-&gt;DR.<\/li><li>Set the memory address to be the address of the data buffer.<\/li><li>Number of transfer to be the length of the data.<\/li><li>Enable the stream.<\/li><\/ul>\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 SPI1_TX_DMA(uint8_t *data,uint16_t len)\n{\n\tDMA2-&gt;LIFCR |=DMA_LIFCR_CTCIF3;\n\tDMA2_Stream3-&gt;PAR= (uint32_t)&amp;SPI1-&gt;DR;\n\tDMA2_Stream3-&gt;M0AR=(uint32_t)data;\n\tDMA2_Stream3-&gt;NDTR=len;\n\tDMA2_Stream3-&gt;CR|=DMA_SxCR_EN;\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the entire source code 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;}\">#include &quot;spi.h&quot;\n\n#include &quot;stm32f4xx.h&quot;\n\n#define AF_SPI1 0x05\n#define ch3\t\t(0x03&lt;&lt;25)\n\n\n\nvoid SPI1_Pins_Init(void)\n{\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable clock for GPIOA\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1; \/\/set PA5, PA6 and PA7 to alternate function mode\n\tGPIOA-&gt;MODER &amp;=~(GPIO_MODER_MODE5_0|GPIO_MODER_MODE6_0|GPIO_MODER_MODE7_0);\n\n\tGPIOA-&gt;AFR[0]|=(AF_SPI1&lt;&lt;GPIO_AFRL_AFSEL5_Pos)|(AF_SPI1&lt;&lt;GPIO_AFRL_AFSEL6_Pos)|(AF_SPI1&lt;&lt;GPIO_AFRL_AFSEL7_Pos);\n}\n\nvoid SPI1_Init(void)\n{\n\t\/*Enable clock access to SPI1 module*\/\n\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\n\t\/*Set clock to fPCLK\/8*\/\n\tSPI1-&gt;CR1 |=(SPI_CR1_BR_1);\n\n\t\/*Set CPOL to 0 and CPHA to 0*\/\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_CPOL;\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_CPHA;\n\n\t\/*Enable full duplex*\/\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_RXONLY;\n\n\t\/*Set MSB first*\/\n\tSPI1-&gt;CR1 &amp;= ~SPI_CR1_LSBFIRST;\n\n\t\/*Set mode to MASTER*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_MSTR;\n\n\t\/*Set 8 bit data mode*\/\n\tSPI1-&gt;CR1 &amp;= ~SPI_CR1_DFF;\n\n\t\/*Select software slave management by\n\t* setting SSM=1 and SSI=1*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SSI;\n\tSPI1-&gt;CR1 |= SPI_CR1_SSM;\n\n\t\/*Enable SPI TX with DMA*\/\n\tSPI1-&gt;CR2|=SPI_CR2_TXDMAEN;\n\n\t\/*Enable SPI1 Interrupt in NVIC*\/\n\tNVIC_EnableIRQ(SPI1_IRQn);\n\n\t\/*Enable SPI module*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SPE;\n}\n\nvoid spi1_transmit(uint8_t *data,uint32_t size)\n{\n\tuint32_t i=0;\n\n\twhile(i&lt;size)\n\t{\n\t\t\/*Wait until TXE is set*\/\n\t\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\t\/*Write the data to the data register*\/\n\t\tSPI1-&gt;DR = data[i];\n\t\ti++;\n\t}\n\t\/*Wait until TXE is set*\/\n\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\/*Wait for BUSY flag to reset*\/\n\twhile((SPI1-&gt;SR &amp; (SPI_SR_BSY))){}\n\n\t\/*Clear OVR flag*\/\n\t(void)SPI1-&gt;DR;\n\t(void)SPI1-&gt;SR;\n}\n\nvoid spi1_receive(uint8_t *data,uint32_t size)\n{\n\twhile(size)\n\t{\n\t\t\/*Send dummy data*\/\n\t\tSPI1-&gt;DR =0;\n\n\t\t\/*Wait for RXNE flag to be set*\/\n\t\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_RXNE))){}\n\n\t\t\/*Read data from data register*\/\n\t\t*data++ = (SPI1-&gt;DR);\n\t\tsize--;\n\t}\n}\n\n\nvoid DMA2_CLK_Init(void)\n{\n\t\/*Enable Clock access to DMA2*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_DMA2EN;\n}\n\nvoid DMA2_Stream3_CH2_Config(void)\n{\n\t\/*Disable the Stream and make sure it is disabled*\/\n\tDMA2_Stream3-&gt;CR&amp;=~DMA_SxCR_EN;\n\n\twhile((DMA2_Stream3-&gt;CR)&amp;DMA_SxCR_EN){;}\n\n\t\/*Configure the DMA with the following parameters\n\t *\n\t * CH -&gt; channel 3.\n\t * Memory increment mode.\n\t * Enable Transfer Complete interrupt\n\t * *\/\n\tDMA2_Stream3-&gt;CR=ch3|DMA_SxCR_MINC|DMA_SxCR_DIR_0|DMA_SxCR_TCIE;\n\n\t\/*Enable DMA2_Stream3 interrupt in NVIC*\/\n\tNVIC_EnableIRQ(DMA2_Stream3_IRQn);\n\n}\n\n\nvoid SPI1_TX_DMA(uint8_t *data,uint16_t len)\n{\n\tDMA2-&gt;LIFCR |=DMA_LIFCR_CTCIF3;\n\tDMA2_Stream3-&gt;PAR= (uint32_t)&amp;SPI1-&gt;DR;\n\tDMA2_Stream3-&gt;M0AR=(uint32_t)data;\n\tDMA2_Stream3-&gt;NDTR=len;\n\tDMA2_Stream3-&gt;CR|=DMA_SxCR_EN;\n}\n\nvoid DMA2_Stream3_IRQHandler(void)\n{\n\tif(DMA2-&gt;LISR&amp;(DMA_LISR_TCIF3))\n\t{\n\t\t\n\t\t\/*Enable SPI Tx buffer empty interrupt *\/\n\t\tSPI1-&gt;CR2|=SPI_CR2_TXEIE;\n\n\t\t\/*Clear pending flag*\/\n\t\tDMA2-&gt;LIFCR |=DMA_LIFCR_CTCIF3;\n\t}\n}\n\n\n\n__WEAK void SPI_TX_Finished(void)\n{\n\t\/*Override with user code*\/\n}\n\nvoid SPI1_IRQHandler(void)\n{\n\tif ((SPI1-&gt;SR &amp; SPI_SR_TXE) &amp;&amp; ((SPI1-&gt;SR &amp; SPI_SR_BSY)==0))\n\t{\n\t\t\/*Set finished to 1*\/\n\t\tSPI_TX_Finished();\n\n\t\t\/*Disable SPI Tx Buffer empty interrupt*\/\n\t\tSPI1-&gt;CR2&amp;=~SPI_CR2_TXEIE;\n\n\n\n\n\t}\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Header File:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>The 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\n\nvoid SPI1_Pins_Init(void);\n\nvoid SPI1_Init(void);\n\nvoid DMA2_CLK_Init(void);\n\nvoid DMA2_Stream3_CH2_Config(void);\n\nvoid SPI1_TX_DMA(uint8_t *data,uint16_t len);\n\n\n\n#endif \/* SPI_H_ *\/\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6.  Main Code:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>In main.c:<\/p>\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;}\">#include &quot;spi.h&quot;\n#include &quot;stm32f4xx.h&quot;\n\n#define size_of_data 10\n\nuint8_t data[size_of_data];\n\nuint8_t finished_transfer=0;\n\nint main(void)\n{\n\tSPI1_Pins_Init();\n\tSPI1_Init();\n\tDMA2_CLK_Init();\n\tDMA2_Stream3_CH2_Config();\n\n\t\/*Configure PA0 to act as CS pin*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE0_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE0_1;\n\n\tGPIOA-&gt;BSRR=GPIO_BSRR_BS0;\n\n\t\/*Fill the array with data from 0 to 9 for testing*\/\n\tfor (int i=0;i&lt;size_of_data;i++)\n\t{\n\t\tdata[i]=i;\n\t}\n\n\twhile(1)\n\t{\n\t\t\/*Set PA0 to low *\/\n\t\tGPIOA-&gt;BSRR=GPIO_BSRR_BR0;\n\n\t\t\/*Send the data*\/\n\t\tSPI1_TX_DMA(&amp;data,size_of_data);\n\n\t\t\/*Wait until the data have been transfer*\/\n\t\twhile(finished_transfer==0);\n\n\t\t\/*Set PA0 to high*\/\n\t\tGPIOA-&gt;BSRR=GPIO_BSRR_BS0;\n\n\t\t\/*Reset the variable*\/\n\t\tfinished_transfer=0;\n\n\t}\n\n}\n\nvoid SPI_TX_Finished(void)\n{\n\tfinished_transfer=1;\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Results:<\/h2>\n\n\n\n<p>After flashing the code to your STM32F4xx, connect logic analyzer to pins PA5, PA7 and PA0 and decode the SPI data, you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"551\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM-1024x551.png\" alt=\"\" class=\"wp-image-2213\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM-1024x551.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM-300x161.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM-768x413.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM-750x404.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM-400x215.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM-250x135.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-23-at-12.08.13\u202fPM.png 1122w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude09 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this revised version of SPI TX with DMA, we shall see how to transmit data over SPI using DMA. In the previous guide (here), we discussed how to send a single character using SPI in polling mode. This method will decrease the CPU performance since the CPU has to wait for each time before [&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-2207","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\/2207"}],"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=2207"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2207\/revisions"}],"predecessor-version":[{"id":2214,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2207\/revisions\/2214"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2207"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}