{"id":2202,"date":"2023-12-21T06:02:32","date_gmt":"2023-12-21T06:02:32","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=2202"},"modified":"2023-12-21T06:02:35","modified_gmt":"2023-12-21T06:02:35","slug":"ws2812-with-stm32-in-spi-mode","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=2202","title":{"rendered":"WS2812 With STM32 in SPI Mode"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00.jpg\" alt=\"\" class=\"wp-image-2203\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00-300x300.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00-150x150.jpg 150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00-768x768.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00-750x750.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00-400x400.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/F68DRVWHOSC3N00-250x250.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In the previous version of WS2812 Addressable LED, we used PWM with DMA to send the data to the addressable LED. In this guide, we shall use SPI to send the data.<\/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>Timing Calculation.<\/li><li>Change Core Frequency.<\/li><li>Delay function.<\/li><li>Configure the SPI.<\/li><li>WS2812 connection with STM32F4xx.<\/li><li>WS2812 Driver.<\/li><li>Main code.<\/li><li>Code.<\/li><li>Results.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Timing Calculation:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>The idea is very simple. If we set the SPI baud rate at 2.5Mbits\/s, each bit would represent a pulse of 0.4us.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/controllerstech.com\/wp-content\/uploads\/2023\/09\/ws2812_spi_1.webp\" alt=\"\" class=\"wp-image-127943\" \/><\/figure><\/div>\n\n\n\n<p>According to the datasheet of the WS2812, a bit is considered as 0 if the signal remains&nbsp;<strong>HIGH for 0.35us<\/strong>&nbsp;and&nbsp;<strong>LOW for 0.8us<\/strong>. And for a bit to be considered as a 1, the signal remains&nbsp;<strong>HIGH for 0.7us<\/strong>&nbsp;and&nbsp;<strong>LOW for 0.6us<\/strong>. Of course this is flexible with an error up to \u00b1150ns.<br>Also the&nbsp;<strong>reset signal<\/strong>&nbsp;is supplied by pulling the data line low for more than 50us.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"https:\/\/controllerstech.com\/wp-content\/uploads\/2023\/09\/ws2812_2_1.webp\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" src=\"https:\/\/controllerstech.com\/wp-content\/uploads\/2023\/09\/ws2812_2_1-1024x667.webp\" alt=\"\" class=\"wp-image-127934\" \/><\/a><\/figure><\/div>\n\n\n\n<p>We will use 3 SPI bits to represent a single bit for the WS2812. The 3 SPI bits will have the time period of 1.2us (0.4*3).&nbsp;<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/controllerstech.com\/wp-content\/uploads\/2023\/09\/ws2812_spi_2.webp\" alt=\"\" class=\"wp-image-127952\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Change the Core Frequency:<\/h2>\n\n\n\n<p>In order to achieve 2.5Mbps for the SPI, we need to set the core to be running at 80MHz. This with SPI clock divider of 32 will give us 2.5Mbps buadrate.<\/p>\n\n\n\n<p>Create new source file with name sys_init.c:<\/p>\n\n\n\n<p>Within the source code:<\/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;stm32f4xx.h&quot;\n\nvoid SystemInit (void)\n{\n\t#define PLL_M      4\n\t#define PLL_N      80\n\t#define PLL_P      2\n\t#define PLL_Q      9\n\n\t__IO uint32_t StartUpCounter = 0, HSEStatus = 0;\n\n\n\t  RCC-&gt;CR |= ((uint32_t)RCC_CR_HSEON);\n\n\n\t  do\n\t  {\n\t\tHSEStatus = RCC-&gt;CR &amp; RCC_CR_HSERDY;\n\t\tStartUpCounter++;\n\t  } while((HSEStatus == 0) &amp;&amp; (StartUpCounter != 3000));\n\n\t  if ((RCC-&gt;CR &amp; RCC_CR_HSERDY) != RESET)\n\t  {\n\t\tHSEStatus = (uint32_t)0x01;\n\t  }\n\t  else\n\t  {\n\t\tHSEStatus = (uint32_t)0x00;\n\t  }\n\n\t  if (HSEStatus == (uint32_t)0x01)\n\t  {\n\n\t\tRCC-&gt;APB1ENR |= RCC_APB1ENR_PWREN;\n\t\tPWR-&gt;CR &amp;= (uint32_t)~(PWR_CR_VOS);\n\n\n\t\tRCC-&gt;CFGR |= RCC_CFGR_HPRE_DIV1;\n\n\n\t\tRCC-&gt;CFGR |= RCC_CFGR_PPRE2_DIV1;\n\n\n\t\tRCC-&gt;CFGR |= RCC_CFGR_PPRE1_DIV2;\n\n\n\t\tRCC-&gt;PLLCFGR = PLL_M | (PLL_N &lt;&lt; 6) | (((PLL_P &gt;&gt; 1) -1) &lt;&lt; 16) |\n\t\t\t\t\t   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q &lt;&lt; 24);\n\n\n\t\tRCC-&gt;CR |= RCC_CR_PLLON;\n\n\n\t\twhile((RCC-&gt;CR &amp; RCC_CR_PLLRDY) == 0)\n\t\t{\n\t\t}\n\n\t\t\/* Configure Flash prefetch, Instruction cache, Data cache and wait state *\/\n\t\tFLASH-&gt;ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_7WS;\n\n\n\t\t\/* Select the main PLL as system clock source *\/\n\t\tRCC-&gt;CFGR &amp;= (uint32_t)((uint32_t)~(RCC_CFGR_SW));\n\t\tRCC-&gt;CFGR |= RCC_CFGR_SW_PLL;\n\n\t\t\/* Wait till the main PLL is used as system clock source *\/\n\t\twhile ((RCC-&gt;CFGR &amp; (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL)\n\t\t{;}\n\t  }\n\t  else\n\t  { \/* If HSE fails to start-up, the application will have wrong clock\n\t\t\t configuration. User can add here some code to deal with this error *\/\n\t  }\n\n\t\/*Enable float point hardware*\/\n\tSCB-&gt;CPACR |= ((3UL &lt;&lt; 10*2)|(3UL &lt;&lt; 11*2));\n\n\t\/*Enable cell compensation*\/\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_SYSCFGEN ;\n\tSYSCFG-&gt;CMPCR|=SYSCFG_CMPCR_CMP_PD;\n\twhile(!((SYSCFG-&gt;CMPCR)&amp;(SYSCFG_CMPCR_READY))){;}\n\n}\n\n<\/pre><\/div>\n\n\n\n<p>Note: this will be called during startup, no need to be called in the main function.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Delay Function:<\/h2>\n\n\n\n<p>Create new source and header file with name of delay.c and delay.h respectively.<\/p>\n\n\n\n<p>Within the 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 __delay__H__\n#define __delay__H__\n\n#include &quot;stdint.h&quot;\n\n\/*\n * @brief This function will initialize SysTick\n * to generate 1ms interrupt.\n * @param freq source frequency of SysTick.\n * @return nothing.\n * @see Generic ARM CortexM4 user guide.\n * *\/\n\nvoid delay_init(uint32_t freq);\n\n\/*\n * @brief This function will return the current millis.\n *\n * @param nothing.\n * @return current millis.\n * *\/\nuint64_t millis();\n\n\n\/*\n * @brief This function will spin lock the CPU to delay for the required\n * amount\n * @param time to be delayed in milliseconds.\n * @return nothing.\n * *\/\nvoid delay(uint32_t time);\n\n\n#endif<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Within the source 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;delay.h&quot;\n#include &quot;stm32f4xx.h&quot;\n\n\n#define\tCTRL_ENABLE\t\t\t\t\t(1U&lt;&lt;0) \/*Enable SysTick Timer*\/\n#define CTRL_CLKSRC\t\t\t\t\t(1U&lt;&lt;2) \/*Clock source selection*\/\n#define CTRL_COUNTFLAG\t\t\t\t(1U&lt;&lt;16) \/*Count flag bit*\/\n#define CTRL_TICKINT\t\t\t\t(1U&lt;&lt;1) \/*Interrupt enable bit*\/\n\n\nvolatile uint64_t mil; \/*volatile variable to hold the ms counter*\/\n\nvoid delay_init(uint32_t freq)\n{\n\n\t\/*Set period to be 1ms*\/\n\tSysTick-&gt;LOAD  = (freq\/1000) - 1;\n\n\t\/*Clear systick current value register *\/\n\tSysTick-&gt;VAL = 0;\n\n\t\/*Enable systick and select internal clk src*\/\n\tSysTick-&gt;CTRL = CTRL_ENABLE | CTRL_CLKSRC ;\n\n\t\/*Enable systick interrupt*\/\n\tSysTick-&gt;CTRL  |= CTRL_TICKINT;\n\n}\n\n\n\nuint64_t millis()\n\t{\n\n\t__disable_irq(); \/*Disable global interrupt*\/\n\n\tuint64_t ml=mil; \/*Get the current millis values and store in ml*\/\n\n\t__enable_irq(); \/*Enable global interrupt*\/\n\n\treturn ml;\t\t\/*Return the stored value*\/\n\t}\n\n\n\/*Spin lock the CPU to delay*\/\nvoid delay(uint32_t time)\n{\n\n\tuint64_t start=millis();\n\twhile((millis() - start) &lt; (time+1));\n}\n\n\/*Interrupt handler of SysTick*\/\nvoid SysTick_Handler(void)\n{\n\t\/*Increment the counter with every interrupt*\/\n\tmil++;\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Configure SPI:<\/h2>\n\n\n\n<p>Since we need only the MOSI (Master Out Slave In) pin of the SPI, that means we need only to configure PA7 to work  as SPI pin.<\/p>\n\n\n\n<p>The parameters of the SPI as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Master Mode.<\/li><li>Fclk\/32.<\/li><li>Software slave management.<\/li><li>MSB first.<\/li><li>SPI Mode 0 (CPOL and CPHA are 0).<\/li><\/ul>\n\n\n\n<p>Create new source file and header file with name of SPI1.c and SPI1,h respectively.<\/p>\n\n\n\n<p>Within the 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_H_\n#define SPI1_H_\n\n#include &quot;stdint.h&quot;\n\n\n\/*\n * @brief This function will initialize SPI1 related pins.\n * @return nothing.\n * @see Pinout of datasheet for SPI pins.\n * *\/\nvoid SPI1_Pins_Init(void);\n\n\n\/*\n * @brief This function will initialize SPI1\n * and configure it.\n * @return nothing.\n * @see reference manual SPI section.\n * *\/\nvoid SPI1_Config(void);\n\n\/*\n * @brief This function will transmit data over SPI bus.\n * @param *data pointer to the data to be written.\n * @param size  size of the data to be written.\n * @return nothing.\n * *\/\nvoid SPI1_Transmit(uint8_t *data,uint32_t size);\n\n\n\n#endif \/* SPI1_H_ *\/<\/pre><\/div>\n\n\n\n<p>The source 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 &lt;SPI1.h&gt;\n#include &quot;stm32f4xx.h&quot;\n\n\nvoid SPI1_Pins_Init(void)\n{\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable clock for GPIOA\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE7_1; \/\/ PA7 to alternate function mode\n\tGPIOA-&gt;MODER &amp;=~(GPIO_MODER_MODE7_0);\n\n\tGPIOA-&gt;OSPEEDR|=GPIO_OSPEEDER_OSPEEDR7;\n\n\tGPIOA-&gt;AFR[0]|=(0x05&lt;&lt;28);\n}\n\n\n\nvoid SPI1_Config(void)\n{\n\t\/*Enable clock access to SPI1 module*\/\n\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\n\t\/*Set clock to fPCLK\/2*\/\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_BR_0;\n\tSPI1-&gt;CR1 &amp;=~SPI_CR1_BR_1;\n\tSPI1-&gt;CR1 |=SPI_CR1_BR_2;\n\n\t\/*Set CPOL to 0 and CPHA to 0 (MODE0)*\/\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_SSM);\n\tSPI1-&gt;CR1 |= (SPI_CR1_SSI);\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<\/pre><\/div>\n\n\n\n<p>As you can see, we only configure the PA7 to work as SPI, the rest is left as default state.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. WS2812B Connection with STM32F4xx:<\/h2>\n\n\n\n<p>The connection as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"971\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-971x1024.png\" alt=\"\" class=\"wp-image-2204\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-971x1024.png 971w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-285x300.png 285w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-768x810.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-1457x1536.png 1457w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-1150x1213.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-750x791.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-400x422.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM-250x264.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/Screenshot-2023-12-21-at-8.16.58\u202fAM.png 1652w\" sizes=\"(max-width: 971px) 100vw, 971px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. WS2812 Driver:<\/h2>\n\n\n\n<p>Create new header file with name of <strong><em>WS2812.h<\/em><\/strong>.<\/p>\n\n\n\n<p>Within the header file, include the header guard 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 WS2812_H_\n#define WS2812_H_\n\n\n\n\n\n\n#endif \/* WS2812_H_ *\/<\/pre><\/div>\n\n\n\n<p>Within the header guard, include stdint library 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;stdint.h&quot;<\/pre><\/div>\n\n\n\n<p>Declare number of the LEDs as following (change according to number of LEDs in your setup):<\/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;}\">\/*Set number of LED in the string*\/\n#define NUM_OF_LEDs 24<\/pre><\/div>\n\n\n\n<p>Declare set brightness 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;}\">\/*\n * @brief This function will set the LED Brightness.\n * @param brightness value.\n * @return nothing.\n * *\/\nvoid WS2812_Set_Brightness(uint8_t value);<\/pre><\/div>\n\n\n\n<p>This function will set the LED brightness and takes value as argument and return nothing.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Declare set color of the LED 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;}\">\/*\n * @brief This function will set the LED colors value.\n * @param led: LED Number.\n * @param RED: Red color value.\n * @param GREEN: Green color value.\n * @param BLUE: Blue color value.\n * @retun nothing\n * *\/\nvoid WS2812_Set_LED_Color (int led, int RED, int GREEN, int BLUE);<\/pre><\/div>\n\n\n\n<p>This function will set specific LED to the desired color. The function take the following four arguments:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>led which is led number.<\/li><li>Red, Green and blue values.<\/li><\/ul>\n\n\n\n<p>The function will return nothing.<\/p>\n\n\n\n<p>Declare set LED 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;}\">\/*\n * @brief This function will write the data to the LED string.\n * @param nothing.\n * @return nothing\n * *\/\nvoid WS2812_Set (void);<\/pre><\/div>\n\n\n\n<p>This function will write the new data to the LED string and it takes no argument and returns nothing.<\/p>\n\n\n\n<p><\/p>\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 WS2812_H_\n#define WS2812_H_\n\n#include &quot;stdint.h&quot;\n\n\/*Set number of LED in the string*\/\n#define NUM_OF_LEDs 24\n\n\/*\n * @brief This function will set the LED Brightness.\n * @param brightness value.\n * @return nothing.\n * *\/\nvoid WS2812_Set_Brightness(uint8_t value);\n\n\/*\n * @brief This function will set the LED colors value.\n * @param led: LED Number.\n * @param RED: Red color value.\n * @param GREEN: Green color value.\n * @param BLUE: Blue color value.\n * @retun nothing\n * *\/\nvoid WS2812_Set_LED_Color (int led, int RED, int GREEN, int BLUE);\n\n\/*\n * @brief This function will write the data to the LED string.\n * @param nothing.\n * @return nothing\n * *\/\nvoid WS2812_Set (void);\n\n\n\n#endif \/* WS2812_H_ *\/\n<\/pre><\/div>\n\n\n\n<p>Create new source file with name of <strong><em>WS2812.<\/em><\/strong>c.<\/p>\n\n\n\n<p>Within the source file, include the 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;WS2812.h&quot;\n#include &quot;SPI1.h&quot;\n#include &quot;delay.h&quot;<\/pre><\/div>\n\n\n\n<p>declare brightness variable with initial value of 100 for maximum brightness:<\/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 brightness=100;<\/pre><\/div>\n\n\n\n<p>Create two dimensional array 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;}\">uint8_t LED_Data[NUM_OF_LEDs][4];<\/pre><\/div>\n\n\n\n<p>For set brightness 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 WS2812_Set_Brightness(uint8_t value)\n{\n\tif(value&gt;100)value=100;\n\tbrightness=value;\n}<\/pre><\/div>\n\n\n\n<p>Simply, check if the value bigger than 100, set it to 100.<\/p>\n\n\n\n<p>For set LED color:<\/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 WS2812_Set_LED_Color (int led, int RED, int GREEN, int BLUE)\n{\n\tLED_Data[led][0] = led;\n\tLED_Data[led][1] = GREEN;\n\tLED_Data[led][2] = RED;\n\tLED_Data[led][3] = BLUE;\n}\n<\/pre><\/div>\n\n\n\n<p>Since the have 24 arrays and each array has 4 elements, we set the first element to the number of the LED, second, third and fourth element to the color red, green and blue respectively.<\/p>\n\n\n\n<p>The following declare function as static which can be only used within this source:<\/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;}\">static void ws2812_spi (int GREEN, int RED, int BLUE)\n{\n\n\tGREEN = GREEN*brightness\/100;\n\tRED = RED*brightness\/100;\n\tBLUE = BLUE*brightness\/100;\n\n\tuint32_t color = GREEN&lt;&lt;16 | RED&lt;&lt;8 | BLUE;\n\tuint8_t sendData[24];\n\tint indx = 0;\n\n\tfor (int i=23; i&gt;=0; i--)\n\t{\n\t\tif (((color&gt;&gt;i)&amp;0x01) == 1) sendData[indx++] = 0b110;  \/\/ store 1\n\t\telse sendData[indx++] = 0b100;  \/\/ store 0\n\t}\n\n\tSPI1_Transmit( sendData, 24);\n}\n<\/pre><\/div>\n\n\n\n<p>First, we calculate the brightness of the LED by simply multiplying the ratio of the brightness to the desired value.<\/p>\n\n\n\n<p>Declare local uint32_t variable to hold the color value which is 24-bit in length, hence, the variable size is 32-bit.<\/p>\n\n\n\n<p>declare local 24 byte size buffer to hold the data to be send and index to track the data.<\/p>\n\n\n\n<p>Store the color of the LED as mentioned in the calculation section.<\/p>\n\n\n\n<p>Finally, transmit the data.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Finally, LED set 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 WS2812_Set (void)\n{\n\tfor (int i=0; i&lt;NUM_OF_LEDs; i++)\n\t{\n\t\tws2812_spi(LED_Data[i][1], LED_Data[i][2], LED_Data[i][3]);\n\t}\n\tdelay (1);\n}<\/pre><\/div>\n\n\n\n<p>It is as simple as sending the color of the pixel from the main array.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the 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;WS2812.h&quot;\n#include &quot;SPI1.h&quot;\n#include &quot;delay.h&quot;\n\nuint8_t brightness=100;\n\nuint8_t LED_Data[NUM_OF_LEDs][4];\n\nvoid WS2812_Set_Brightness(uint8_t value)\n{\n\tif(value&gt;100)value=100;\n\tbrightness=value;\n}\n\nvoid WS2812_Set_LED_Color (int led, int RED, int GREEN, int BLUE)\n{\n\tLED_Data[led][0] = led;\n\tLED_Data[led][1] = GREEN;\n\tLED_Data[led][2] = RED;\n\tLED_Data[led][3] = BLUE;\n}\n\n\nstatic void ws2812_spi (int GREEN, int RED, int BLUE)\n{\n\n\tGREEN = GREEN*brightness\/100;\n\tRED = RED*brightness\/100;\n\tBLUE = BLUE*brightness\/100;\n\n\tuint32_t color = GREEN&lt;&lt;16 | RED&lt;&lt;8 | BLUE;\n\tuint8_t sendData[24];\n\tint indx = 0;\n\n\tfor (int i=23; i&gt;=0; i--)\n\t{\n\t\tif (((color&gt;&gt;i)&amp;0x01) == 1) sendData[indx++] = 0b110;  \/\/ store 1\n\t\telse sendData[indx++] = 0b100;  \/\/ store 0\n\t}\n\n\tSPI1_Transmit( sendData, 24);\n}\n\nvoid WS2812_Set (void)\n{\n\tfor (int i=0; i&lt;NUM_OF_LEDs; i++)\n\t{\n\t\tws2812_spi(LED_Data[i][1], LED_Data[i][2], LED_Data[i][3]);\n\t}\n\tdelay (1);\n}\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>In main.c code:<\/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;delay.h&quot;\n#include &quot;SPI1.h&quot;\n#include &quot;stdlib.h&quot;\n#include &quot;WS2812.h&quot;\n\n\nint main(void)\n{\n\tdelay_init(80000000);\n\tSPI1_Pins_Init();\n\tSPI1_Config();\n\tWS2812_Set_Brightness(100);\n\n\twhile(1)\n\t{\n\t\tfor (int i=0;i&lt;NUM_OF_LEDs;i++)\n\t\t{\n\t\t\tsrand(millis());\n\t\t\tWS2812_Set_LED_Color(i,random()%256,random()%256,random()%256);\n\n\t\t\tWS2812_Set();\n\t\t\tdelay(random()%100);\n\t\t}\n\t\tdelay(200);\n\n\t\tfor (int i=NUM_OF_LEDs;i&gt;=0;i--)\n\t\t{\n\t\t\tsrand(millis());\n\t\t\tWS2812_Set_LED_Color(i,0,0,0);\n\n\t\t\tWS2812_Set();\n\t\t\tdelay(random()%100);\n\t\t}\n\t\tdelay(200);\n\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">8. Code:<\/h2>\n\n\n\n<p>You may download the code from here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/WS2812_SPI.zip\">WS2812_SPI<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/12\/WS2812_SPI.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">9. Results:<\/h2>\n\n\n\n<p>Once you compiled and run the code on your board, you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"WS2812 Demo on STM32F4\" width=\"1170\" height=\"658\" src=\"https:\/\/www.youtube.com\/embed\/H6uuAXsfLwQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous version of WS2812 Addressable LED, we used PWM with DMA to send the data to the addressable LED. In this guide, we shall use SPI to send the data. In this guide, we shall cover the following: Timing Calculation. Change Core Frequency. Delay function. Configure the SPI. WS2812 connection with STM32F4xx. WS2812 [&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-2202","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\/2202"}],"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=2202"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2202\/revisions"}],"predecessor-version":[{"id":2206,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2202\/revisions\/2206"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}