一、实现思路
😊前面已经进行过一个RGB灯的实现,今天通过SPI的优化,也可以实现,具体的思路就是通过SPI发送一个字节的时间来计算,下面先来看下原理图:
✌注意看,RGB的需要发送0码和1码的时间符合上面手册给的时间范围才可以亮起来,所以我们只需要计算发送需要的时间就行,
😈GRB灯--SPI实现的计算方式
F40的芯片-----APB1的时钟为42MHZ
42MHZ--发送一个字节--我们要发一个字所以--42/8=5.25MHZ则数一次需要的时间为1/5.25=1.9*10负7次方,换算为ns *1000000=190ns发一个位
发送0码---高电平时间为220ns~380ns.低电平时间为580ns~1μs
发送1码---低电平时间为220ns~380ns.高电平时间为580ns~1μs所以发0码--1100 0000--0xc0---只要在那个范围就行
发送1码--1111 1100--0xFC🙅注意:我这里用的是F4的APB1的时钟,,F103的或者其他芯片的型号都不一样,需要自己去查看手册,计算具体的时间
二、接线
😫这里我用的开发板接的是PB15,映射的是SPI2,想用SPI实现就得接到有SPI的IO口上,不然会没效果,上面也写了计算的方法,然后我们来看代码:
注意:使能GPIO的时钟和SPI2的时钟----重点
三、程序实现
😌上面介绍了初始化的实现,,下面解释关于SPI的发送函数和封装RGB了数据传送的函数
//SPI2发送接收函数 uint8_t SPI2_sendByte(uint8_t data) { while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==0){}//等待发送完成 SPI_I2S_SendData(SPI2,data); while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==0){}//等待可以接收 return SPI_I2S_ReceiveData(SPI2); }
♓这个就没什么好说的了,SPI的发送和接收是一起的,并且是一个字节的发送和接收,下面是RGB的数据传输函数---------------------------------------有两种方案,一种是24位一起发,因为一个颜色占据8位,G-绿R-红B-蓝===三个颜色一起发,就是24位 ,也可以8位8位一起发,我们就用24位一起发的模式来讲解,末尾有全部的代码:
🙋第二种方案就是8位8位发
同样的计算方式,只是发送的位数不同而已,想发送三个颜色,必须再写一个函数配套用
编辑实例:
四、代码
WS2812.C
#include "WS2812.h"
#include "delay.h"
void Grb_Init(void)
{
//PB 15 推挽输出
GPIO_InitTypeDef GPIO_InitStruct={0};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//使能PC时钟
//GPIO配置
GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF; //复用模式
GPIO_InitStruct.GPIO_OType =GPIO_OType_PP;//设置输出模式推挽
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//设置无上下拉。GPIO初始化默认是低电平
GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed;//速度设置
GPIO_Init(GPIOB,&GPIO_InitStruct);//GPIO初始化
GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
//SPI2参数配置
SPI_InitTypeDef SPI_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;//波特率预分频值
SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;//串行时钟进行偶次采样
SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;//时钟空闲为高电平---模式3-上升沿采集数据
SPI_InitStructure.SPI_CRCPolynomial=7;//CRC值计算多项式--7--复位值
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//SPI双向全双工
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//8位数据帧
SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//数据高位在前
SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//SPI主模式
SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//NSS信号由软件管理
SPI_Init(SPI2,&SPI_InitStructure);
SPI_Cmd(SPI2,ENABLE);
RGB_to_GRB(RGB_BLACK);
RGB_to_GRB(RGB_BLACK);
RGB_to_GRB(RGB_BLACK);
RGB_to_GRB(RGB_BLACK);
GRB_RESET();//复位
}
//SPI2发送接收函数
uint8_t SPI2_sendByte(uint8_t data)
{
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==0){}//等待发送完成
SPI_I2S_SendData(SPI2,data);
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==0){}//等待可以接收
return SPI_I2S_ReceiveData(SPI2);
}
void GRB_RESET(void)//复位
{
GRB_Data = 0;
delay_ms(5);
}
void RGB_Write(u8 data)//发送一个颜色
{
int i;
for(i=0;i<8;i++)//一个颜色八个位
{
if(data & 1<<(7-i))//高位先发
{
//发送数据1
SPI2_sendByte(0xFc);
}
else
{
//发送数据0
SPI2_sendByte(0xc0);
}
}
}
//怎么把颜色发送给芯片 通过PB15 24位色 转2进制 从高位发
void RGB_Write2(u32 data)//发送24位颜色
{
int i;
for(i=0;i<24;i++)//一个颜色八个位
{
if(data & 1<<(23-i))//高位先发
{
//发送数据1
SPI2_sendByte(0xFc);
}
else
{
//发送数据0
SPI2_sendByte(0xc0);
}
}
}
//RGB G 8--15 0xff00 00
void RGB_to_GRB(u32 color)
{
RGB_Write((color>>8)&0XFF);//发送绿色
RGB_Write((color>>16)&0XFF);//发送红色
RGB_Write((color)&0XFF);//发送蓝色
}
WS2812.h
#ifndef __WS2812_H_
#define __WS2812_H_
#include "io_bit.h"
#define GRB_Data PBout(15)
void Grb_Init(void);
void GRB_RESET(void);
void RGB_Write(u8 data);
void RGB_to_GRB(u32 color);
void RGB_Write2(u32 data);
#define RGB_RED 0XFF0000
#define RGB_GREEN 0X00FF00
#define RGB_BLUE 0X0000FF
#define RGB_BLACK 0X000000
#define RGB_YELLOW 0XFFFF00
#define RGB_WHITE 0XFFFFFF
#endif
main.c
#include "stm32f4xx.h"
#include "delay.h"
#include "LED.h"
#include "exti.h"
#include "key.h"
#include "WS2812.h"
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组2
delay_Init();//延时初始化
Exti_Init();//外部中断初始化
LED_Init();//LED初始化
Grb_Init();
while(1)
{
if(button1)
{
RGB_Write2(RGB_RED);
RGB_Write2(RGB_GREEN);
RGB_Write2(RGB_BLUE);
RGB_Write2(RGB_WHITE);
button1=0;
}
if(button2)
{
RGB_to_GRB(RGB_BLACK);
RGB_to_GRB(RGB_BLACK);
RGB_to_GRB(RGB_BLACK);
RGB_to_GRB(RGB_BLACK);
button2=0;
}
}
}