ARM嵌入式学习笔记(10)SPI通信

ARM嵌入式学习笔记(10)SPI通信

SPI简介

SPI 协议是摩托罗拉公司开发的一种高速的,全双工,同步的通信总线,使用四根线进行通信,具有简单易用,通讯速度高的特点。SPI 总线上可以挂载多个设备,这些设备被区分成主设备(Master)和从设备(Slave),主设备通过时钟线和片选线对从设备进行控制。
SPI 协议所使用到的引脚及其功能见下表
在这里插入图片描述
SPI 是一种全双工的通信协议,主设备和从设备通信时,两端的收发是同步进行的,即主设备和从设备在向对方发送数据的同时,也在接收对方发来的数据。
SPI 的通信过程如下:

  1. 主设备将要进行通讯的从设备的 SS/CS 片选拉低,
  2. 主设备通过 SCK 向从设备提供同步通讯所需要的时钟信号。
  3. 主设备通过 MOSI 向从设备发送 8 位数据,同时通过 MISO 接收从设备发来的 8 位数
    据。
  4. 通信结束,主设备拉高 SS/CS 片选。

SPI在CubeMX中的配置

这里我们只驱动WS2812,所以选择主机发送模式即可在这里插入图片描述
在这里插入图片描述

WS2812代码

//ws2812.h
#ifndef __WS2812_H__
#define __WS2812_H__

#include <stdint.h>

//            编码 0 : 11000000
#define CODE_0		0xC0
//            编码 1 : 11111000
#define CODE_1		0xF8
/*ws2812b灯珠数量*/
#define WS2812B_AMOUNT		9

typedef struct
{
    uint8_t R;
    uint8_t G;
    uint8_t B;
} tWs2812bCache_TypeDef;

/**
 * @brief HSV颜色空间
*/
typedef struct {
    float h;    // 色调H(hue)  0~360° {R(0°),G(120°),B(240°)}
    float s;    // 饱和度S(saturation)  0~1.0
    float v;    // 明度V(value)  0~1.0
}color_hsv_t;

typedef struct {
    unsigned char r;    // 0-255
    unsigned char g;    // 0-255
    unsigned char b;    // 0-255
    unsigned int color; // 0x000000 ~ 0xffffff
}color_rgb_t;


extern tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT];


/**
 * @brief   RGB颜色空间 转  HSV颜色空间
 * @param   rgb:RGB颜色空间参数
 * @param   hsv:HSV颜色空间参数
 * @return  none
*/
void rgb2hsv(color_rgb_t *rgb, color_hsv_t *hsv);

/**
 * @brief   HSV颜色空间 转 RGB颜色空间
 * @param   hsv:HSV颜色空间参数
 * @param   rgb:RGB颜色空间参数
 * @return  none
*/
void hsv2rgb(color_hsv_t *hsv, color_rgb_t *rgb);
void WS2812b_Set(uint16_t Ws2b812b_NUM, uint8_t r,uint8_t g,uint8_t b);
void WS2812B_Task(void);

#endif
//ws2812.c
#include "ws2812.h"
#include "spi.h"


//灯条显存SPI数据缓存
uint8_t gWs2812bDat_SPI[WS2812B_AMOUNT * 24] = {0};
//灯条显存
tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT] = {

//R    G      B
        0XFF, 0X00, 0X00,	//0
        0X00, 0XFF, 0X00,	//1
        0X00, 0X00, 0XFF,	//2
        0X00, 0XFF, 0XFF,	//3
        0XFF, 0X00, 0XFF,	//4
        0XFF, 0XFF, 0X00,	//5
        0XFF, 0XFF, 0XFF,	//6
        0X00, 0X00, 0X00,	//7
        0XFF, 0X00, 0X00,	//8
};

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),0XFFFF);
    //使总线输出低电平
    HAL_SPI_Transmit(&hspi1, &dat, 1,0XFFFF);
    //帧信号:一个大于50us的低电平
    HAL_Delay(1);
}

只要滚动刷新显存内容就可以实现多灯串联,如果想要调色可以使用hsv通道转换到rgb通道,这样控制亮度和颜色会比较方便。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值