之前一篇文章写了使用IO控制WS2812b操作原理,但是由于IO的输出比较慢,所以现在改用了硬件SPI控制WS2812b灯条

把SPI的mosi线接到ws2812b的数据线,SPI的速率可达十几Mbit/s,如此高的传输速率,我们可以使用一个(uint8_t)类型的数据代表一个码1或者码0;

也就是说,本来控制一个灯珠的数据由3个Byte(24位)变成了24Byte,每个bit转换成一个Byte;

具体看时钟如何配置的。

SPI配置:



在上一篇文章可以看到控制一个码的周期在1.25us±300ns之间,现在把时钟配成9Mbit/s,这个的话每个码的周期大概就在889ns,和LED的周期略有误差;

从规格书上可以看到码1和码0的占空比是大致分配一下1个byte的8个bit;

我这里分配的是

码1:0xF8;

码0:0xE0;

可以根据自己的具体情况取修改码0和码1的分配

ws2812b.h[[]()]()

#ifndef __WS2812B_H__
#define __WS2812B_H__ #include <stdint.h> // 编码 0 : 11100000
#define CODE_0 0xE0
// 编码 1 : 11111000
#define CODE_1 0xF8
/*ws2812b灯珠数量*/
#define WS2812B_AMOUNT 8 typedef struct
{
uint8_t R;
uint8_t G;
uint8_t B;
} tWs2812bCache_TypeDef; void WS2812b_Set(uint16_t Ws2b812b_NUM, uint8_t r,uint8_t g,uint8_t b);
void WS2812B_Task(void); #endif

ws2812b.c

#include "ws2812b.h"
#include "spi.h" //灯条显存SPI数据缓存
uint8_t gWs2812bDat_SPI[WS2812B_AMOUNT * 24] = {0};
//灯条显存
tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT] = {
//R G B
0X0F, 0X0F, 0X0F, //0
0X0F, 0X0F, 0X0F, //1
0X0F, 0X0F, 0X0F, //2
0X0F, 0X0F, 0X0F, //3
0X0F, 0X0F, 0X0F, //4
0X0F, 0X0F, 0X0F, //5
0X0F, 0X0F, 0X0F, //6
0X0F, 0X0F, 0X0F, //7
}; void WS2812b_Set(uint16_t Ws2b812b_NUM, uint8_t r,uint8_t g,uint8_t b)
{
uint8_t *pR = &gWs2812bDat_SPI[(Ws2b812b_NUM) * 24 + 8];
uint8_t *pG = &gWs2812bDat_SPI[(Ws2b812b_NUM) * 24];
uint8_t *pB = &gWs2812bDat_SPI[(Ws2b812b_NUM) * 24 + 16]; for(uint8_t i = 0; i < 8; i++) {
if(g & 0x80) {
*pG = CODE_1;
}
else {
*pG = CODE_0;
}
if(r & 0x80) {
*pR = CODE_1;
}
else {
*pR = CODE_0;
}
if(b & 0x80) {
*pB = CODE_1;
}
else {
*pB = CODE_0;
}
r <<= 1;
g <<= 1;
b <<= 1;
pR++;
pG++;
pB++;
}
}
void WS2812B_Task(void)
{
uint8_t dat = 0; //将gWs2812bDat数据解析成SPI数据
for(uint8_t iLED = 0; iLED < WS2812B_AMOUNT; iLED++)
{
WS2812b_Set(iLED, gWs2812bDat[iLED].R, gWs2812bDat[iLED].G, gWs2812bDat[iLED].B);
}
//总线输出数据
HAL_SPI_Transmit(&hspi1, gWs2812bDat_SPI, sizeof(gWs2812bDat_SPI), 100);
//使总线输出低电平
HAL_SPI_Transmit(&hspi1, &dat, 1, 100);
//帧信号:一个大于50us的低电平
HAL_Delay(1);
}

直接在main()里面调用WS2812B_Task()就可以驱动灯条,另外直接修改数组gWs2812bDat就可改变灯条的颜色。

STM32F103C8T6使用SPI接口驱动WS2812b灯条的更多相关文章

  1. STM32F103C8T6驱动WS2812b灯条

    STM32F103C8T6驱动WS2812b灯条 几天小朋友到别人家玩,看上了人家的金鱼,人家就给了她一条小金鱼,有了小金鱼,怕它没氧气挂掉,买了一个氧气泵,没有东西喂它也不行,又买了一包鱼料,又因为 ...

  2. linux驱动基础系列--Linux下Spi接口Wifi驱动分析

    前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...

  3. NUC980 运行 RT-Thread 驱动 SPI 接口 OLED 播放 badapple

    badapple 是什么,上网随便查了下,没看出个究竟,不过有个关于这个挺火的标签或者主题 < 有屏幕的地方就有 badapple >,网上有很多人用很多方式播放 badapple 动画, ...

  4. linux内核SPI总线驱动分析(一)(转)

    linux内核SPI总线驱动分析(一)(转) 下面有两个大的模块: 一个是SPI总线驱动的分析            (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) ...

  5. Linux内核中SPI总线驱动分析

    本文主要有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程): 另一个是SPI总线驱动的编写(不用研究具体的实现过程). 1 SPI概述 SPI是英语Serial Peripheral ...

  6. SPI接口扫盲 SPI定义/SPI时序(CPHA CPOL)

    SPI接口扫盲   douqingl@gmail.com   为何要写这篇文档?百度上找出来的SPI接口中文描述都说的太过简略,没有一篇文档能够详尽的将SPI介绍清楚的.wikipedia英文版[注释 ...

  7. 嵌入式物联网之SPI接口原理与配置

    本实验采用W25Q64芯片 W25Q64是华邦公司推出的大容量SPI FLASH产品,其容量为64Mb.该25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件.W25Q64将8M字节的容量分为 ...

  8. usb驱动开发24之接口驱动

    从第一节我们已经知道,usb_generic_driver在自己的生命线里,以一己之力将设备的各个接口送给了linux的设备模型,让usb总线的match函数,也就是usb_device_match, ...

  9. 高通APQ8074 spi 接口配置

    高通APQ8074 spi 接口配置 8074 平台含有两个BLSP(BAM Low-Speed Peripheral) , 每一个BLSP含有两个QUP, 每一个QUP可以被配置为I2C, SPI, ...

随机推荐

  1. python中两种拷贝目录方法的比较

    首先是用python自己的api: shutil.copytree('./build/tested/doc', './build/tested/build/doc') 优点是改变平台时不需要修改代码, ...

  2. 【网络编程】TCPIP_3_地址族与数据序列

    目录 前言 3. 地址族与数据序列 3.1 分配给套接字的 IP 地址与端口号 3.2 参数 IP 地址 3.2.1 IPV4 地址的结构体 3.2.2 地址族(Address Family) 3.2 ...

  3. Java中Lambda表达式基础及使用详解

    概述 Lambda 是JDK 8 的重要新特性.它允许把函数作为一个方法的参数(函数作为参数传递进方法中),使用 Lambda 表达式可以使代码变的更加简洁紧凑,使Java代码更加优雅. 标准格式 三 ...

  4. SQL 练习26

    查询 1990 年出生的学生名单 --方式1 SELECT * FROM Student WHERE Sage BETWEEN '1990-01-01' AND '1990-12-31' --方式2 ...

  5. websocket在慕课网中的应用

    网上资料都是介绍概念,我们来看看实际网站怎么使用websocket的吧.限于自身水平解读并不深入,慕课网上的websocket某些字段不知何用. 是什么 是一种应用层协议,有html5而推出,是一种全 ...

  6. noip23

    T1 好吧,题目很sb,描述告诉你序列无限长,输入格式里告诉你m为序列长度,我:????,选择了相信后者.然后连暴力都挂分,可恶 这题一看就是个毒瘤数据结构题,思索了一下,发现就是个线段树,但我又想到 ...

  7. ReentrantLock中的Condition(等待和唤醒)

    Condition 类的 awiat 方法和 Object 类的 wait 方法等效 Condition 类的 signal 方法和 Object 类的 notify 方法等效 Condition 类 ...

  8. 【微服务技术专题】Netflix动态化配置服务-微服务配置组件变色龙Archaius

    前提介绍 如果要设计开发一套微服务基础架构,参数化配置是一个非常重要的点,而Netflix也开源了一个叫变色龙Archaius的配置中心客户端,而且Archaius可以说是比其他客户端具备更多生产级特 ...

  9. Object 类中的主要结构

    == 操作符与equals 方法 == 操作符  equals 方法  重写equals() 方法的 toString()  方法

  10. CrackMe-CrackHead

    转载自:OllyDbg入门教程 现在进入第三篇,这一篇我们重点讲解怎样使用 OllyDBG 中的函数参考(即名称参考)功能.仍然选择 crackmes.cjb.net 镜像打包中的一个名称为 Crac ...