ws2812系列灯条,是一种可寻址的RGB  LED彩灯,可以自定义颜色、点灯速度等。只需要一个IO就可以控制多个灯。ws2812系列有三根线,分别为VCC、GND、信号控制线。作为优化升级版的ws2813系列,更是具有断点续传功能,比如说有个灯坏了,但是它与后面的信号线没有断,信号可以正常传到后面去。

作为Arduino爱好者,这里推荐两个好用的库hastLed和Neopixel。

这里想和大家分享一下stm32连接ws2812~  用的单片机是stm32f103zet6,这部分代码换成stm32f103c8t6照样跑的通。

一、添加ws2812.c和ws2812.h文件

直接使用正点原子模板向HARDWARE文件夹下,新建一个文件夹命名为ws2812,然后新建ws2812.c和ws2812.h。

然后把一下文件分别复制到对应c和h文件

1、ws2812.h

#ifndef __WS2812_H
#define __WS2812_H#include "stm32f10x.h"#define PIXEL_NUM 60//硬件spi模拟ws2811时序(用spi的8位数据模拟ws281x的一位数据)
//要将系统时钟设置为56M,分频数设置为8,则SPI的通信频率为7M,传输一位数据的时间约为143纳秒(ns)
//3*143 = 429ns   5*143 = 715ns  符合WS281X芯片的通信时序。
//  _____
// |     |___|   11111000  high level
//  ___
// |   |_____|   11100000  low level#define WS_HIGH 0XF8
#define WS_LOW  0XE0void ws281x_init(void);
void ws281x_closeAll(void);
void ws281x_rainbowCycle(uint8_t wait);
uint32_t ws281x_color(uint8_t red, uint8_t green, uint8_t blue);
void ws281x_setPixelColor(uint16_t n ,uint32_t GRBcolor);
void ws281x_show(void);void ws281x_theaterChase(uint32_t c, uint8_t wait);
void ws281x_colorWipe(uint32_t c, uint8_t wait);
void ws281x_rainbow(uint8_t wait);
void ws281x_theaterChaseRainbow(uint8_t wait);#endif /* __WS2812_H */

2、ws2812.c

#include "ws2812.h"
#include "usart.h"
#include "delay.h"uint8_t pixelBuffer[PIXEL_NUM][24] ;void ws281x_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef  SPI_InitStructure;DMA_InitTypeDef DMA_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //PORTA时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //SPI1时钟使能     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA传输/* PA7  SPI1_MOSI */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PA7复用推挽输出 SPIGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOASPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;     //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;     //串行同步时钟的空闲状态为低电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;   //串行同步时钟的第2个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;      //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;        //定义波特率预分频的值:波特率预分频值为16SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;   //CRC值计算的多项式SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器SPI_Cmd(SPI1, ENABLE); //使能SPI外设SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);DMA_DeInit(DMA1_Channel3);   //将DMA的通道1寄存器重设为缺省值DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI1 -> DR); //cpar;  //DMA外设ADC基地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pixelBuffer; //cmar;  //DMA内存基地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设DMA_InitStructure.DMA_BufferSize = PIXEL_NUM * 24; //cndtr;  //DMA通道的DMA缓存的大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常缓存模式DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输DMA_Init(DMA1_Channel3, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器 ws281x_closeAll();  //关闭全部的灯delay_ms(100); //关闭全部的灯需要一定的时间
}void ws281x_closeAll(void)
{uint16_t i;uint8_t j;for(i = 0; i < PIXEL_NUM; ++i){for(j = 0; j < 24; ++j){pixelBuffer[i][j] = WS_LOW;}}ws281x_show();
}uint32_t ws281x_color(uint8_t red, uint8_t green, uint8_t blue)
{return green << 16 | red << 8 | blue;
}void ws281x_setPixelColor(uint16_t n ,uint32_t GRBcolor)
{uint8_t i;if(n < PIXEL_NUM){for(i = 0; i < 24; ++i){pixelBuffer[n][i] = (((GRBcolor << i) & 0X800000) ? WS_HIGH : WS_LOW);}}
}void ws281x_setPixelRGB(uint16_t n ,uint8_t red, uint8_t green, uint8_t blue)
{uint8_t i;if(n < PIXEL_NUM){for(i = 0; i < 24; ++i){pixelBuffer[n][i] = (((ws281x_color(red,green,blue) << i) & 0X800000) ? WS_HIGH : WS_LOW);}}
}void ws281x_show(void)
{DMA_Cmd(DMA1_Channel3, DISABLE );  //关闭USART1 TX DMA1 所指示的通道 DMA_ClearFlag(DMA1_FLAG_TC3);    DMA_SetCurrDataCounter(DMA1_Channel3,24 * PIXEL_NUM );//DMA通道的DMA缓存的大小DMA_Cmd(DMA1_Channel3, ENABLE);  //使能USART1 TX DMA1 所指示的通道
}// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t ws281x_wheel(uint8_t wheelPos) {wheelPos = 255 - wheelPos;if(wheelPos < 85) {return ws281x_color(255 - wheelPos * 3, 0, wheelPos * 3);}if(wheelPos < 170) {wheelPos -= 85;return ws281x_color(0, wheelPos * 3, 255 - wheelPos * 3);}wheelPos -= 170;return ws281x_color(wheelPos * 3, 255 - wheelPos * 3, 0);
}// Fill the dots one after the other with a color
void ws281x_colorWipe(uint32_t c, uint8_t wait) {for(uint16_t i=0; i<PIXEL_NUM; i++) {ws281x_setPixelColor(i, c);ws281x_show();delay_ms(wait);}
}void ws281x_rainbow(uint8_t wait) {uint16_t i, j;for(j=0; j<256; j++) {for(i=0; i<PIXEL_NUM; i++) {ws281x_setPixelColor(i, ws281x_wheel((i+j) & 255));}ws281x_show();delay_ms(wait);}
}// Slightly different, this makes the rainbow equally distributed throughout
void ws281x_rainbowCycle(uint8_t wait) {uint16_t i, j;for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheelfor(i=0; i< PIXEL_NUM; i++) {ws281x_setPixelColor(i,ws281x_wheel(((i * 256 / PIXEL_NUM) + j) & 255));}ws281x_show();delay_ms(wait);}
}//Theatre-style crawling lights.
void ws281x_theaterChase(uint32_t c, uint8_t wait) {for (int j=0; j<10; j++) {  //do 10 cycles of chasingfor (int q=0; q < 3; q++) {for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, c);    //turn every third pixel on}ws281x_show();delay_ms(wait);for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, 0);        //turn every third pixel off}}}
}//Theatre-style crawling lights with rainbow effect
void ws281x_theaterChaseRainbow(uint8_t wait) {for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheelfor (int q=0; q < 3; q++) {for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, ws281x_wheel( (i+j) % 255));    //turn every third pixel on}ws281x_show();delay_ms(wait);for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, 0);        //turn every third pixel off}}}
}

这两部简单地复制粘贴大家可以跟上的吧,接下来添加库到keil。

3、keil添加库

4、改mian.c代码

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "ws2812.h"int8_t i;
void Delay(u32 count)
{u32 i = 0;for(; i < count; i++);
}int main(void)
{uart_init(115200);delay_init();ws281x_init();while(1){ws281x_colorWipe(ws281x_color(255, 0, 0), 50); // Redws281x_colorWipe(ws281x_color(0, 255, 0), 50); // Greenws281x_colorWipe(ws281x_color(200, 255, 0), 50); //黄色ws281x_colorWipe(ws281x_color(100, 255, 50), 50); //冰蓝ws281x_colorWipe(ws281x_color(155, 255, 0), 50); //嫩绿色}
}

复制完代码编译一下,这时候你会发现报错了!!!

不要方,这是由于我们没有添加stm32spi和dma文件。

添加进去,完美解决。鼓掌

上传代码到单片机,VCC、GND正常接,信号线接到PA7。

工程代码如下

qq-hh/qq-hh-My_Project_stm32 (github.com)

ws2812+stm32视频

STM32+ws2812灯条,点灯升级版相关推荐

  1. ESP32使用外设RMT控制WS2812灯条

    目录 一.简介 二.所需材料 三.官方例程 四.使用方法 4.1 RMT初始化 4.2 WS2812初始化 4.3 点亮WS2812 五.LED颜色渐变 5.1 第一种实现方法 5.2 第二种实现方法 ...

  2. 自制小爱音箱控制氛围灯(小爱音箱+Arduino+RGB灯条+点灯科技)

    硬件准备 1 .wemos d1 mini (ESP8266) 2.灯条应该是ws2813吧 3.小爱音箱 查看资料 点灯科技接入小爱流程 https://diandeng.tech/doc/xiao ...

  3. STM32使用PWM+DMA方式驱动WS2812灯珠

    一. 关于WS2812 WS2812 内部集成了处理芯片和3颗不同颜色的led灯(红,绿,蓝),通过单总线协议分别控制三个灯的亮度强弱,达到全彩的效果. WS2812B Datasheet 二. WS ...

  4. ESP32 驱动WS2812B 灯条

    //WS2812 灯条 #include <Arduino.h> #include <Adafruit_NeoPixel.h>//关键是这个库 #define WS_PIN   ...

  5. WS2812灯珠(三)-- STM32 PWM+DMA方式驱动

    WS2812灯珠(三)-- STM32 PWM+DMA方式驱动 文章目录 WS2812灯珠(三)-- STM32 PWM+DMA方式驱动 一.理论 二.代码实践 一.理论 PWM输出就是对外输出脉宽( ...

  6. arduinows2812灯条程序_Arduino 控制WS2812 LED灯条

    传统的LED限制总是很多,比如需要很多的引脚.所以有一种很好的解决方案是用灯条.理论上这种灯条可以通过通讯,用一根数据总线可以控制达到无上限个数的RGB-LED灯珠,并且在数量在1024以下时,延迟是 ...

  7. ## STM32——闪烁灯程序

    STM32--闪烁灯程序 单片机的闪烁灯是继点灯后的一个简单的程序,这也是每一个初学者的必经路程,也并没有我们想象的那么难,我们要相信自己.人生难得几回搏,此时不搏待何时. --至每一个为自己的理想而 ...

  8. Arduino控制WS2812灯带(灯环)

    设计者:STCode(公众号同名) Arduino控制WS2812灯带(灯环) 1) WS2812灯 WS2812灯带 WS2812灯环 WS2812是一个集控制电路与发光电路于一体的智能外空LED光 ...

  9. 秒上手!使用Arduino控制基于WS2812B的LED灯条

    使用Arduino控制基于WS2812B的LED灯条 一.材料准备 硬件部分 1. Arduino UNO R3 开发板 2. 基于WS2812B的LED灯条 3. 杜邦线若干 软件部分 1. Ard ...

最新文章

  1. ceph 部署单机集群
  2. java.utilDate和java.sql.Date
  3. 某同学正为自己安装不上sqlserver数据库而愁眉苦脸,使用朋友给的方法顿时喜笑颜开,那么朋友到底出了个什么样的方法呢?...
  4. 多项新政催生本年度购房最佳“窗口期”
  5. Matlab与OpenCV对应函数
  6. typecho插件库 TeStore 方便监控插件版本
  7. 第八届开源操作系统年度技术会议(OS2ATC)在京召开, 百位科技菁英到场共鉴“开源协作”
  8. rsync 安装 配置 实例
  9. springBoot 2.2.6 项目中html页面样式效果丢失
  10. c++整人小程序(附源码)
  11. VisualStudio2017密钥(key)
  12. java 全局钩子_[原]在全局鼠标钩子中模拟鼠标右键单击
  13. iRightMouse 1.2.0 中文版 (超赞的Mac右键菜单扩展)
  14. 从链家爬取北京各区二手房房价进行分析并实现数据可视化
  15. 车牌识别、证件识别、汽车VIN识别在汽车服务门店中的实际应用
  16. 蓝牙GATT和GAP层
  17. 在英文版的remix部署,拿到部署地址在中文版的remix 中 合约地址中输入地址,再部署可以实现调用 java调用智能合约Unmatched arguments from index 2
  18. 四种主要网络IO虚拟化模型
  19. 通过C++类方法地址调用类的虚方法
  20. Vue项目配置本地访问地址和IP访问地址

热门文章

  1. 91免费视频Redis+Lua解决高并发场景在线秒杀问题
  2. 转一次排障经历以供学习
  3. python数据分析岗位_python拉勾数据职位分析
  4. marathon错误记录
  5. 案例:谷歌人工智能算法Dropout申请专利
  6. 15.全文检索-ElasticSearch
  7. DM8数据库备份与恢复 DMRMAN
  8. 麦肯锡并不神秘,方法论铸就传奇,《金字塔原则》96页PPT,转发
  9. linux中more是什么命令,linux系统more命令
  10. 笔记本onenote绘画快捷键_onenote快捷键