{"id":2257,"date":"2024-01-06T14:35:36","date_gmt":"2024-01-06T14:35:36","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=2257"},"modified":"2024-01-06T14:35:38","modified_gmt":"2024-01-06T14:35:38","slug":"working-with-stm32f7-and-spi-send-data-using-dma","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=2257","title":{"rendered":"Working with STM32F7 and SPI: Send data 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\/2024\/01\/AdobeStock_122425803-2048x1365-1-1024x683.jpeg\" alt=\"\" class=\"wp-image-2258\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-1024x683.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-300x200.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-768x512.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-1536x1024.jpeg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-1150x766.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-750x500.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-400x267.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1-250x167.jpeg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/AdobeStock_122425803-2048x1365-1.jpeg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In this guide, we shall send data over SPI bus using DMA.<\/p>\n\n\n\n<p>In the previous guide (<a href=\"https:\/\/blog.embeddedexpert.io\/?p=739\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=739\" target=\"_blank\" rel=\"noreferrer noopener\">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>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>DMA 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<h2 class=\"wp-block-heading\">1. SPI initialization:<\/h2>\n\n\n\n<p>Create new source and header file with name of SPI1_DMA.c and SPI1_DMA.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<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;stm32f7xx.h&quot;\n\n#include &quot;SPI1_DMA.h&quot;<\/pre><\/div>\n\n\n\n<p>Declare the following two macros:<\/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 AF05 0x05\n\n#define CH3 0x03<\/pre><\/div>\n\n\n\n<p>First one for alternate function number for the GPIO.<\/p>\n\n\n\n<p>The second one is for the DMA channel selection.<\/p>\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;}\">\t\/\/enable clock for GPIOA\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\n\t\/\/set PA5, PA6 and PA7 to alternate function mode\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODER5_1|GPIO_MODER_MODER6_1|GPIO_MODER_MODER7_1;\n\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODER5_0|GPIO_MODER_MODER6_0|GPIO_MODER_MODER7_0);\n\n\tGPIOA-&gt;AFR[0]|=(AF05&lt;&lt;GPIO_AFRL_AFRL5_Pos)|(AF05&lt;&lt;GPIO_AFRL_AFRL6_Pos)|(AF05&lt;&lt;GPIO_AFRL_AFRL7_Pos);<\/pre><\/div>\n\n\n\n<p>Now declare the following function which will initialize the SPI in DMA mode:<\/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;}\">void SPI1_DMA_Init(void)<\/pre><\/div>\n\n\n\n<p>The SPI configuration as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"257\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-1024x257.png\" alt=\"\" class=\"wp-image-2259\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-1024x257.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-300x75.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-768x193.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-1536x385.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-2048x513.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-1150x288.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-750x188.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-400x100.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.21.15\u202fPM-250x63.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\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><\/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;}\">\t\/\/enable clock access to SPI1\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_SPI1EN;\n\n\t\/\/software slave management\n\tSPI1-&gt;CR1|=SPI_CR1_SSM|SPI_CR1_SSI;\n\n\t\/*Set clock to fPCLK\/8*\/\n\tSPI1-&gt;CR1 |=(SPI_CR1_BR_1);\n\n\t\/\/ set SPI as master mode\n\tSPI1-&gt;CR1|=SPI_CR1_MSTR;\n\t\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;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In Control Register 2 (CR2):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Enable TXDMA.<\/li><li>Set data size to 8-bit.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"245\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-1024x245.png\" alt=\"\" class=\"wp-image-2260\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-1024x245.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-300x72.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-768x183.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-1536x367.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-2048x489.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-1150x275.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-750x179.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-400x96.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/Screenshot-2024-01-06-at-5.23.14\u202fPM-250x60.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 data size to 8-bit*\/\n\tSPI1-&gt;CR2&amp;=~(SPI_CR2_DS_Msk);\n\tSPI1-&gt;CR2|=(0x07&lt;&lt;SPI_CR2_DS_Pos);\n\n\t\/*Enable TXDMA*\/\n\tSPI1-&gt;CR2|=SPI_CR2_TXDMAEN;<\/pre><\/div>\n\n\n\n<p>Enable SPI global interrupt:<\/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 global interrupt*\/\n\n\tNVIC_EnableIRQ(SPI1_IRQn);<\/pre><\/div>\n\n\n\n<p>Enable 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;}\">\t\/*Enable SPI peripheral*\/\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\"><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><\/p>\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<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 DMA2*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_DMA2EN;\n\n\t\/*Disable the Stream*\/\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\n\tDMA2_Stream3-&gt;CR=(CH3&lt;&lt;DMA_SxCR_CHSEL_Pos)|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);<\/pre><\/div>\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><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. DMA Interrupt Handler:<\/h2>\n\n\n\n<p>Within the interrupt handler:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>If the interrupt source is transfer completed, Enable SPI TX buffer is empty and clear the flag.<\/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_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}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. 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\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}\n<\/pre><\/div>\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;stm32f7xx.h&quot;\n\n#include &quot;SPI1_DMA.h&quot;\n\n#define AF05 0x05\n\n#define CH3 0x03\n\n\nvoid SPI1_Pins_Init(void)\n{\n\t\/\/enable clock for GPIOA\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\n\t\/\/set PA5, PA6 and PA7 to alternate function mode\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODER5_1|GPIO_MODER_MODER6_1|GPIO_MODER_MODER7_1;\n\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODER5_0|GPIO_MODER_MODER6_0|GPIO_MODER_MODER7_0);\n\n\tGPIOA-&gt;AFR[0]|=(AF05&lt;&lt;GPIO_AFRL_AFRL5_Pos)|(AF05&lt;&lt;GPIO_AFRL_AFRL6_Pos)|(AF05&lt;&lt;GPIO_AFRL_AFRL7_Pos);\n\n\n}\n\n\nvoid SPI1_DMA_Init(void)\n{\n\t\/\/enable clock access to SPI1\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_SPI1EN;\n\n\t\/\/software slave management\n\tSPI1-&gt;CR1|=SPI_CR1_SSM|SPI_CR1_SSI;\n\n\t\/*Set clock to fPCLK\/8*\/\n\tSPI1-&gt;CR1 |=(SPI_CR1_BR_1);\n\n\t\/\/ set SPI as master mode\n\tSPI1-&gt;CR1|=SPI_CR1_MSTR;\n\t\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\/*Set data size to 8-bit*\/\n\tSPI1-&gt;CR2&amp;=~(SPI_CR2_DS_Msk);\n\tSPI1-&gt;CR2|=(0x07&lt;&lt;SPI_CR2_DS_Pos);\n\n\t\/*Enable TXDMA*\/\n\tSPI1-&gt;CR2|=SPI_CR2_TXDMAEN;\n\n\t\/*Enable SPI global interrupt*\/\n\n\tNVIC_EnableIRQ(SPI1_IRQn);\n\n\t\/*Enable SPI peripheral*\/\n\tSPI1-&gt;CR1|=SPI_CR1_SPE;\n\n\t\/*Enable Clock Access to DMA2*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_DMA2EN;\n\n\t\/*Disable the Stream*\/\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\n\tDMA2_Stream3-&gt;CR=(CH3&lt;&lt;DMA_SxCR_CHSEL_Pos)|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\n\n\n\n\n\n\n\n\nvoid SPI1_TX_DMA(uint8_t *data,uint16_t len)\n{\n\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}\n\n\n__WEAK void SPI_TX_Finished(void)\n{\n\t\/*Override with user code*\/\n}\n\n\nvoid 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\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\">6. Header File:<\/h2>\n\n\n\n<p>The entire 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;}\">#ifndef SPI1_DMA_H_\n#define SPI1_DMA_H_\n\n\n#include &quot;stdint.h&quot;\n\nvoid SPI1_Pins_Init(void);\nvoid SPI1_DMA_Init(void);\nvoid SPI1_TX_DMA(uint8_t *data,uint16_t len);\n\n\n\n#endif \/* SPI1_DMA_H_ *\/\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Main Code:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>main.c 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;stm32f7xx.h&quot;\n#include &quot;SPI1_DMA.h&quot;\n\n#define size_of_data 10\n\nuint8_t data[size_of_data];\n\nvolatile uint8_t finished_transfer=0;\n\nint main(void)\n{\n\tSPI1_Pins_Init();\n\tSPI1_DMA_Init();\n\n\t\/*Configure PA3 to act as CS pin*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODER3_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODER3_1;\n\n\tGPIOA-&gt;BSRR=GPIO_BSRR_BS3;\n\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 PA3 to low *\/\n\t\tGPIOA-&gt;BSRR=GPIO_BSRR_BR3;\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_BS3;\n\n\t\t\/*Reset the variable*\/\n\t\tfinished_transfer=0;\n\t}\n\n\n}\n\n void SPI_TX_Finished(void)\n{\n\t finished_transfer=1;\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">8. 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\"><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>Happy coding &#x1f609;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, we shall send data over SPI bus 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 sending the character. In this guide, we shall [&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-2257","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\/2257"}],"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=2257"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2257\/revisions"}],"predecessor-version":[{"id":2261,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2257\/revisions\/2261"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}