使用f031的SPI单引脚(MOSI)+DMA实现WS2812B三色灯的级联控制
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三色灯的级联控制相关推荐
- [SPI+DMA] 驱动WS2812B显示时钟
[SPI+DMA] 驱动WS2812B显示时钟 实现原理 本人一个大学萌新,偶然间发现RGB时钟这神奇的玩意,就想试试.目前初步实现时钟显示,第一次写博客,只是为了记录自己的学习成果方便以后查看,大家 ...
- SPI 2分频MOSI实现
SPI 2分频MOSI实现 module spi_25M( input clk, input rst_n, output reg sdin, output reg sclk, output reg c ...
- STM32F427库函数PWM+DMA控制ws2812b灯带
STM32F427IIHx库函数PWM+DMA控制ws2812b灯带 一.参考资料 查看ws2812b用户手册可知: 二.代码部分 添加文件ws2812b.c,ws2812b.h 配置的F427IIH ...
- TLE5012B ESP32驱动程序、硬件电路设计、4线SPI通信,驱动完美兼容4线SPI不用改MOSI开漏推挽输出
一.TLE5012B 简介 TLE5012B 是一种款高分辨率旋转位置传感器,用于在整个 360 度范围内进行角度测量. 它通过使用单片集成 巨磁阻 (iGMR) 元件,来测量正弦和余弦角分量,这些原 ...
- STM32 SPI NSS 引脚为不能拉高问题
使用过 STM32 的SPI 的朋友可能都会发现一个问题,那就是其NSS引脚 在硬件模式下无法自动拉高,可能也因为这个原因致使 .大部分朋友在使用SPI时候都是优先选用软件 控制NSS引脚的工作模式 ...
- STM32L431之SPI从模式使用DMA时数据偏移3个字节
环境: 将SPI3配置成从模式,并且使用DMA来传输数据,在初始化完SPI3后,就立即配置DMA,将待传输的数据准备好. 主机还未读取时,就重新更新数据,更新数据的方法为直接调用Spi3TxDmaSt ...
- S12X的spi通信引脚复用
- 沁恒CH579M使用PWM+DMA驱动WS2812B程序
TMR1,TMR2 的强大功能: 首先咱们看看CH579M规格书,只有TMR1和TMR2支持DMA中断 先定义一个数组把数组的初始RAM地址和结束地址放在寄存器里,当前缓冲地址不管 DMA可以循环和不 ...
- STM32 HAL库 PWM+DMA 驱动WS2812B彩灯(STM32F030F4P6)
谁不想拥有炫酷的小彩灯呢?WS2812B可以给你机会...... 博主使用STM32驱动WS2812B主要参考了这位佬的文章,因为需求问题,采用了Cortex-M0的stm32f030f4p6(16k ...
最新文章
- go语言 rlock() defer runlock()_Go并发编程之美-读写锁
- 中文输入法切换ubuntu_切换到 Linux 工作,体验暴增 100 倍!
- 普通程序员如何用1年时间获取3年成长?
- vsftpd的配置文件路径,是在哪里指定的?
- HTML+CSS+JS实现 ❤️3D奥运五环图形特效❤️
- (计算机组成原理题目题型总结)第二章:数据的表示和运算
- hibernate VS mybatis
- php format tool,iFormatTool
- Android实现仿IOS带清空功能的文本输入框
- cad插件苹果系统_CAD看图软件mac版|CAD迷你看图 for Mac下载 v4.0.0 官方版_最火软件站...
- NOI Linux 2.0的安装
- 保持健康和快乐的20种方法
- 2014蓝桥杯--史丰收速算(C++)
- 福州到横店嘉兴三日游(仅供参考)
- 基于Kinect 2.0深度图像的快速体积测量
- ngx-markdown 安装和使用
- InputStream和FileInputStream
- vscode写php高亮,写了一个Hy的vscode语法高亮插件
- IC设计工程师的职业规划
- 妙味课堂实战功能开发视频教程 3D翻转焦点图/瀑布流/拖拽购物车/模块化开发等实战教程