WS2812B是一种集成了电流控制芯片的低功耗的RGB三色灯,
关于这个灯的一些硬件分析我就不多说,百度一堆一堆的;
今天主要讲讲使用SPI的MOSI+DMA实现控制的方式;
主MCU:灵动微的 MMF031,关于这个MCU就是直接仿造的ST同系列的,可直接百度吧;
主频:#define SYSCLK_HSI_48MHz 48000000
思路:利用SPI发送不同的byte实现WS2812B规格书需求的高低电平;
基础实现高低电平如下:

void LED_SPI_SendBits(uint8_t bits)
{int zero = 0X1F00;//0x0700;   //0001 1111 0000 0000int one = 0XFFC0;//0x07E0;    //1111 1111 1100 0000int i = 0x00;for (i = 0x80; i >= 0x01; i >>= 1){LED_SPI_WriteByte((bits & i) ? one : zero);}
}

实现RGB三个字段共计24BIT的代码如下(这里需要定义一个结构体实现数据转存):

struct Pixel {uint8_t red;uint8_t green;uint8_t blue;
};
void LED_SPI_SendPixel(struct Pixel pixel)
{LED_SPI_SendBits(pixel.green);LED_SPI_SendBits(pixel.red);LED_SPI_SendBits(pixel.blue);
}

需要一个实现发送的代码,传参length 是WS2812级联的个数:

ErrorStatus LED_SPI_Update(struct Pixel buffer[], uint32_t length)
{uint8_t i = 0;uint16_t delay_break = 0 ;if(DMA_GetCurrDataCounter(DMA1_Channel3) == 0)//检查DMA是否完成传输任务{for (i = 0; i < length; i++){LED_SPI_SendPixel(buffer[i]);///一个buffer 一个灯}PixelPointer = 0;DMA1_Channel3->CNDTR = TX_RX_LEN;DMA1_Channel3->CMAR = (uint32_t)PixelBuffer;DMA_ClearFlag(DMA1_FLAG_TC3);//清除通道3数据传输完成标志位 SPI_DMACmd(SPI1,SPI_DMAReq_EN,ENABLE);//使能SPI DMA   DMA_Cmd(DMA1_Channel3, ENABLE);  //使能SPI TX DMA1 所指示的通道 SPI_Cmd(SPI1, ENABLE);      //Enables the specified SPI peripheral SPI使能、主机模式 8位数据模式 SPI 的波特率   while(!DMA_GetFlagStatus(DMA1_FLAG_TC3))  {//通道3数据发送传输完成标志位delay_break ++ ;if(delay_break >2000)break ;}DMA_ClearFlag(DMA1_FLAG_TC3);//清除通道3数据传输完成标志位 return SUCCESS;}else{return ERROR;}
}

这里一个例子是5个数据的代码(实现2+2+1的亮法)可根据实际应用更改了:

void PixelRound_color(u8 left_r ,u8 left_g ,u8 left_b ,u8 right_r,u8 right_g,u8 right_b, u8 front_r,u8 front_g,u8 front_b )//RGB????
{LEDPixel[0].red = left_r;///红LEDPixel[0].blue = left_g;  LEDPixel[0].green = left_b;    LEDPixel[1].red = left_r;LEDPixel[1].blue= left_g;    LEDPixel[1].green = left_b;//绿     LEDPixel[2].red = right_r;//蓝LEDPixel[2].blue= right_g;   LEDPixel[2].green = right_b;   LEDPixel[3].red = right_r;///黄LEDPixel[3].blue= right_g;  LEDPixel[3].green = right_b;   LEDPixel[4].red = front_r;///青LEDPixel[4].blue= front_g;  LEDPixel[4].green = front_b;   LEDPixel[5].red = 0;///紫LEDPixel[5].blue= 0;  LEDPixel[5].green = 0; LED_SPI_Update(LEDPixel,5);
}

配置代码(有点混乱,没有时间整理,直接发出来了):

/********************************************************************************************************
**函数信息 :SPIM_Init(unsigned short spi_baud_div)
**功能描述 :可修改参数初始化SPI
**输入参数 :spi_baud_div
**输出参数 :无
********************************************************************************************************/
void SPIM_Init(SPI_TypeDef* SPIx,unsigned short spi_baud_div)
{// SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);  //SPI1 clk enableSPIM_CSHigh(SPIx);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB|RCC_AHBPeriph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_5;   //spi1_mosi PA7     //spi1_sck  PA5 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_AF_PP;  // 推免复用输出GPIO_Init(GPIOB, &GPIO_InitStructure);//   GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4;     //spi1_cs   PA4
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//
//  GPIO_Init(GPIOA, &GPIO_InitStructure);
//
//  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;         //spi1_miso  PA6
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      //上拉输入
//  GPIO_Init(GPIOA, &GPIO_InitStructure);//  SPIM_CSHigh(SPI1);  //CS highGPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_0);           //开复用时钟
//  GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_0);
//  GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_0);SPI1->GCTL|=SPI_GCTL_MM;//主机模式SPI1->CCTL|=SPI_CCTL_SPILEN;//8位数据宽度//  SPI1->GCTL|=    SPI_GCTL_DATA_SEL;//32 bit 有效SPI1->CCTL&=~SPI_CCTL_CPOL;//SPI_CPOL_Low    // //spi MODE0  CLK 空闲低电平  上升沿采样下降沿送数据SPI1->CCTL|=SPI_CCTL_CPHA;//SPI_CPHA_1EdgeSPI1->GCTL&=~SPI_GCTL_NSS_SEL; //软件控制NSSSPI1->CCTL |=0x10;             //开启高速模式SPI1->SPBRG =spi_baud_div;//4分频,波特率应该为72M/4=18M
//  SPI1->CCTL&=~SPI_CCTL_LSBFE;//MSBSPIx->CCTL|=SPI_CCTL_LSBFE;    //LSB
//      SPI1->EXTCTL = 0x10;               //16bit 数据长度SPIM_TXEn(SPI1);//SPI发送使能    SPIM_RXEn(SPI1);//SPI接收使能       //  SPI_Cmd(SPI1, ENABLE);          //Enables the specified SPI peripheral SPI使能、从机模式 8位数据模式 SPI 的波特率}/********************************************************************************************************
**函数信息 :SPI_DMA_TX_Init
**功能描述 : SPI发送DMA初始化
**输入参数 :
**输出参数 :无
********************************************************************************************************/
void SPI_DMA_TX_Init(u16 *TX_buffer)
{DMA_InitTypeDef  DMA_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA传输DMA_DeInit(DMA1_Channel3);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->TXREG);//SPI发送数据寄存器DMA_InitStructure.DMA_MemoryBaseAddr =(uint32_t)&(*TX_buffer);DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//数据从memory到外设DMA_InitStructure.DMA_BufferSize = TX_RX_LEN;//发送数据个数DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不改变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//memory地址递增开启DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//DMA_PeripheralDataSize_Byte;/内存地址增量(变化)DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//DMA_MemoryDataSize_Byte;/外设传输宽度(字节)DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//普通模式DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel3, &DMA_InitStructure);//SPI TX为DMA通道3
}

工程代码过几天附上。

使用f031的SPI单引脚(MOSI)+DMA实现WS2812B三色灯的级联控制相关推荐

  1. [SPI+DMA] 驱动WS2812B显示时钟

    [SPI+DMA] 驱动WS2812B显示时钟 实现原理 本人一个大学萌新,偶然间发现RGB时钟这神奇的玩意,就想试试.目前初步实现时钟显示,第一次写博客,只是为了记录自己的学习成果方便以后查看,大家 ...

  2. SPI 2分频MOSI实现

    SPI 2分频MOSI实现 module spi_25M( input clk, input rst_n, output reg sdin, output reg sclk, output reg c ...

  3. STM32F427库函数PWM+DMA控制ws2812b灯带

    STM32F427IIHx库函数PWM+DMA控制ws2812b灯带 一.参考资料 查看ws2812b用户手册可知: 二.代码部分 添加文件ws2812b.c,ws2812b.h 配置的F427IIH ...

  4. TLE5012B ESP32驱动程序、硬件电路设计、4线SPI通信,驱动完美兼容4线SPI不用改MOSI开漏推挽输出

    一.TLE5012B 简介 TLE5012B 是一种款高分辨率旋转位置传感器,用于在整个 360 度范围内进行角度测量. 它通过使用单片集成 巨磁阻 (iGMR) 元件,来测量正弦和余弦角分量,这些原 ...

  5. STM32 SPI NSS 引脚为不能拉高问题

    使用过 STM32 的SPI 的朋友可能都会发现一个问题,那就是其NSS引脚 在硬件模式下无法自动拉高,可能也因为这个原因致使  .大部分朋友在使用SPI时候都是优先选用软件 控制NSS引脚的工作模式 ...

  6. STM32L431之SPI从模式使用DMA时数据偏移3个字节

    环境: 将SPI3配置成从模式,并且使用DMA来传输数据,在初始化完SPI3后,就立即配置DMA,将待传输的数据准备好. 主机还未读取时,就重新更新数据,更新数据的方法为直接调用Spi3TxDmaSt ...

  7. S12X的spi通信引脚复用

  8. 沁恒CH579M使用PWM+DMA驱动WS2812B程序

    TMR1,TMR2 的强大功能: 首先咱们看看CH579M规格书,只有TMR1和TMR2支持DMA中断 先定义一个数组把数组的初始RAM地址和结束地址放在寄存器里,当前缓冲地址不管 DMA可以循环和不 ...

  9. STM32 HAL库 PWM+DMA 驱动WS2812B彩灯(STM32F030F4P6)

    谁不想拥有炫酷的小彩灯呢?WS2812B可以给你机会...... 博主使用STM32驱动WS2812B主要参考了这位佬的文章,因为需求问题,采用了Cortex-M0的stm32f030f4p6(16k ...

最新文章

  1. go语言 rlock() defer runlock()_Go并发编程之美-读写锁
  2. 中文输入法切换ubuntu_切换到 Linux 工作,体验暴增 100 倍!
  3. 普通程序员如何用1年时间获取3年成长?
  4. vsftpd的配置文件路径,是在哪里指定的?
  5. HTML+CSS+JS实现 ❤️3D奥运五环图形特效❤️
  6. (计算机组成原理题目题型总结)第二章:数据的表示和运算
  7. hibernate VS mybatis
  8. php format tool,iFormatTool
  9. Android实现仿IOS带清空功能的文本输入框
  10. cad插件苹果系统_CAD看图软件mac版|CAD迷你看图 for Mac下载 v4.0.0 官方版_最火软件站...
  11. NOI Linux 2.0的安装
  12. 保持健康和快乐的20种方法
  13. 2014蓝桥杯--史丰收速算(C++)
  14. 福州到横店嘉兴三日游(仅供参考)
  15. 基于Kinect 2.0深度图像的快速体积测量
  16. ngx-markdown 安装和使用
  17. InputStream和FileInputStream
  18. vscode写php高亮,写了一个Hy的vscode语法高亮插件
  19. IC设计工程师的职业规划
  20. 妙味课堂实战功能开发视频教程 3D翻转焦点图/瀑布流/拖拽购物车/模块化开发等实战教程

热门文章

  1. 微型计算机字,小型微型计算机系统
  2. CSU 1598 KMP
  3. Sniffer报文放送
  4. QT开发中常用的快捷键(Windows+QT)
  5. 学生学习时长统计--python程序设计
  6. android 浏览器源码分析,android webview 简单浏览器实现代码
  7. 三步完整实现运放负反馈电路稳定性设计
  8. 数值分析18 - 通过直接方法得到函数积分近似 数值方法(左、右、中、梯形矩形积分公式、Simpson积分公式)
  9. MySql数据类型-读书笔记
  10. 记一次 controller manager and scheduler 重复重启问题分析