瑞萨e2studio(28)----SPI 驱动WS2812灯珠

news2025/7/28 6:00:35

瑞萨e2studio.28--SPI 驱动WS2812灯珠

  • 概述
  • 视频教学
  • 样品申请
  • 芯片级联方法
  • 数据传输
  • 时序
  • 新建工程
  • 软件准备
  • 保存工程路径
  • 芯片配置
  • 开始SPI配置
  • SPI属性配置
  • 时钟配置
  • SPI配置
  • CPHA配置
  • 代码
  • hal_entry.c
  • ws2812.c
  • ws2812.h

概述

本文介绍了如何使用瑞萨RA微控制器,结合E2STUDIO配置工具和SPI通讯接口,来驱动和控制WS2812 LED灯带。这是一个集硬件连接、软件配置和编程开发于一体的综合性项目,目标是实现对LED灯带颜色和亮度的精确控制。
最近在弄ST和瑞萨RA的课程,需要样片的可以加群申请:615061293 。

视频教学

样品申请

https://www.wjx.top/vm/wBbmSFp.aspx#

芯片级联方法

在这里插入图片描述
芯片在上电复位以后,接收DIN端打来的数据,接收够24bit后,DO端口开始转发数据,供下一个芯片提供输入数据。在转发之前,DO口一直拉低。此时灯珠将不接收新的数据,内置RGB芯片根据接收到的24bit数据后产生的不同占空比信号,展现不同亮度。如果DIN端输入信号为RESET信号,芯片将接收到的数据送显示,芯片将在该信号结束后重新接收新的数据,在接收完开始的24bit数据后,通过DO口转发数据,灯珠在没有接收到RESET码前,RGB亮度保持不变,当接收到80us以上低电平RESET码后,灯珠内部RGB芯片将根据刚才接收到的24bit数据后产生的不同占空比信号,展现不同亮度。
在这里插入图片描述

数据传输

在这里插入图片描述

24bit数据结构:
在这里插入图片描述

时序

时序波形图如下所示。
在这里插入图片描述

在这里插入图片描述

新建工程

在这里插入图片描述

软件准备

在这里插入图片描述

保存工程路径

在这里插入图片描述

芯片配置

本文中使用R7FA4M2AD3CFP来进行演示。

在这里插入图片描述

开始SPI配置

点击Stacks->New Stack->Connectivity->SPI (r_sci_spi)。

在这里插入图片描述

SPI属性配置

将SPI的配置速度设为7.5M,数据宽度设为8位。
CPHA配置为第二边沿采样;在第一个跳变沿时,MOSI在空闲状态保持高电平,而在第二个跳变沿,它会保持上一次传输的最终电平。由于发送数据的最后一位总是低电平,这样配置可以避免WS2812误判。CPOL设置为高,确保SCK在空闲时保持高电平状态。

在这里插入图片描述

时钟配置

SPI (r_sci_spi)的时钟来自PLCKA。
在这里插入图片描述

查询用户手册,配置7.5M频率需要PLCK主频为60M。

在这里插入图片描述

开发板上的外部高速晶振为12M,需要修改XTAL为12M,配置PCLKA为60MHz。

在这里插入图片描述
在这里插入图片描述

SPI配置

系统采用单总线协议,通过总线上高低电平的时长来区分逻辑0和1。WS2811工作在800kHz频率下,将SPI设置为6.4MHz—即其工作频率的8倍—可以确保每个字节(8位)正好对应一个逻辑位。在这种设置下,‘11111000’(0xF8)代表逻辑1,‘11000000’(0xC0)代表逻辑0。

在这里插入图片描述

由于瑞萨RA在SPI发送时候会拉高电平。

在这里插入图片描述

所以在发送的时候需要先发送8位低电平进行复位,复位时间最短位80us。
7.5MHz频率换算位时间位133.3ns,80us/133.3ns≈600位,为了确保复位成功,需发送700位的低电平数据,即发送700/8≈88字节数据。
所以定义显存数组为88+实际灯珠数量。

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

逻辑分析仪显示如下所示。
在这里插入图片描述

逻辑0下发送的数据为11000000’(0xC0)。
逻辑0下高电平位264ns。

在这里插入图片描述

逻辑0下低电平位800ns。

在这里插入图片描述

逻辑1下发送的数据为‘11111000’(0xF8)。
逻辑1下高电平位666ns。

在这里插入图片描述

逻辑1下低电平位400ns。

在这里插入图片描述

这种精确的时序配置和电平控制对于确保WS2812灯带的正确驱动至关重要,可以通过上述配置来优化SPI接口的性能,确保与WS2812的高效通信。

CPHA配置

CPHA配置为第二边沿采样下数据传输结束如下所示。
在这里插入图片描述

CPHA配置为第二边沿采样下数据传输结束如下所示。
在这里插入图片描述

由于RESET Code为低电平,且要大于80us,所以数据传输完毕必须为低电平。

在这里插入图片描述

代码

在main.c中添加头文件。


#include "ws2812.h"

在main.c中添加函数申明和移位操作以及回调函数处理。

fsp_err_t err = FSP_SUCCESS;
volatile bool g_transfer_complete = false;
void sci_spi_callback (spi_callback_args_t * p_args)
{
    if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
    {
        g_transfer_complete = true;
    }
}

extern tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT];

void move_Front()
{
    uint8_t i;
    uint8_t temp[3];
    temp[0] = gWs2812bDat[0].R;
    temp[1] = gWs2812bDat[0].G;
    temp[2] = gWs2812bDat[0].B; 
    for (i = 0; i < WS2812B_AMOUNT-1; i++)
    {
        gWs2812bDat[i].R = gWs2812bDat[i+1].R;
        gWs2812bDat[i].G = gWs2812bDat[i+1].G;
        gWs2812bDat[i].B = gWs2812bDat[i+1].B;
    }
        gWs2812bDat[7].R = temp[0];
        gWs2812bDat[7].G = temp[1];
        gWs2812bDat[7].B = temp[2];
}

添加初始化显示。

    err = R_SCI_SPI_Open(&g_spi0_ctrl, &g_spi0_cfg);
    assert(FSP_SUCCESS == err);

    sci_spi_extended_cfg_t sci_spi_extended_cfg_t1;
    WS2812B_Task();
    R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);

添加流水灯。

    while (1)
    {
      WS2812B_Task();
      move_Front();
      R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
    }

hal_entry.c

#include "hal_data.h"
#include "ws2812.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

fsp_err_t err = FSP_SUCCESS;
volatile bool g_transfer_complete = false;
void sci_spi_callback (spi_callback_args_t * p_args)
{
    if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
    {
        g_transfer_complete = true;
    }
}

extern tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT];

void move_Front()
{
    uint8_t i;
    uint8_t temp[3];
    temp[0] = gWs2812bDat[0].R;
    temp[1] = gWs2812bDat[0].G;
    temp[2] = gWs2812bDat[0].B;
    for (i = 0; i < WS2812B_AMOUNT-1; i++)
    {
        gWs2812bDat[i].R = gWs2812bDat[i+1].R;
        gWs2812bDat[i].G = gWs2812bDat[i+1].G;
        gWs2812bDat[i].B = gWs2812bDat[i+1].B;
    }
        gWs2812bDat[7].R = temp[0];
        gWs2812bDat[7].G = temp[1];
        gWs2812bDat[7].B = temp[2];
}



/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */
    err = R_SCI_SPI_Open(&g_spi0_ctrl, &g_spi0_cfg);
    assert(FSP_SUCCESS == err);

    sci_spi_extended_cfg_t sci_spi_extended_cfg_t1;
    WS2812B_Task();
    R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);

    while (1)
    {
      WS2812B_Task();
      move_Front();
      R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
    }

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
    }
}

#if BSP_TZ_SECURE_BUILD

FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
FSP_CPP_FOOTER

#endif

ws2812.c

/*
 * ws2812.c
 *
 *  Created on: 2023年10月31日
 *      Author: Administrator
 */

#include "ws2812.h"
#include "hal_data.h"
extern fsp_err_t err ;
extern volatile bool g_transfer_complete ;

//灯条显存SPI数据缓存
uint8_t gWs2812bDat_SPI[WS2812B_AMOUNT * 24+88] = {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
};

void WS2812b_Set(uint16_t Ws2b812b_NUM, uint8_t r,uint8_t g,uint8_t b)
{
    uint8_t *pR = &gWs2812bDat_SPI[88+(Ws2b812b_NUM) * 24 + 8];
    uint8_t *pG = &gWs2812bDat_SPI[88+(Ws2b812b_NUM) * 24];
    uint8_t *pB = &gWs2812bDat_SPI[88+(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;
    for(int i=0;i<88;i++)
    {
        gWs2812bDat_SPI[i]=0;

    }
    //将gWs2812bDat数据解析成SPI数据
    for(uint8_t iLED = 0; iLED < WS2812B_AMOUNT; iLED++)
    {
        WS2812b_Set(iLED, gWs2812bDat[iLED].R, gWs2812bDat[iLED].G, gWs2812bDat[iLED].B);
    }
    //总线输出数据

    /* Send the reset command */
    g_transfer_complete = false;
    err = R_SCI_SPI_Write(&g_spi0_ctrl, gWs2812bDat_SPI, sizeof(gWs2812bDat_SPI), SPI_BIT_WIDTH_8_BITS);
    assert(FSP_SUCCESS == err);
    /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */
    while (  g_transfer_complete==false)
    {
        ;
    }
//    //使总线输出低电平
//    g_transfer_complete = false;
//     err = R_SCI_SPI_Write(&g_spi0_ctrl, dat, 1, SPI_BIT_WIDTH_8_BITS);
//     assert(FSP_SUCCESS == err);
//     /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */
//     while (  g_transfer_complete==false)
//     {
//         ;
//     }

    //帧信号:一个大于50us的低电平
     R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
}


ws2812.h

/*
 * ws2812.h
 *
 *  Created on: 2023年10月31日
 *      Author: Administrator
 */

#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      8

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

extern tWs2812bCache_TypeDef gWs2812bDat[WS2812B_AMOUNT];

void WS2812b_Set(uint16_t Ws2b812b_NUM, uint8_t r,uint8_t g,uint8_t b);
void WS2812B_Task(void);


#endif /* WS2812_H_ */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1156514.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于热交换算法的无人机航迹规划-附代码

基于热交换算法的无人机航迹规划 文章目录 基于热交换算法的无人机航迹规划1.热交换搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用热交换算法来优化无人机航迹规划。 1.热交换…

【设计模式】第22节:行为型模式之“状态模式”

一、简介 状态模式一般用来实现状态机&#xff0c;而状态机常用在游戏、工作流引擎等系统开发中。不过&#xff0c;状态机的实现方式有多种&#xff0c;除了状态模式&#xff0c;比较常用的还有分支逻辑法和查表法。该模式允许对象内部状态改变使改变它的行为。 二、适用场景…

【NI-DAQmx入门】计数器

1.计数器的作用 NI产品的计数器一般来说兼容TTL信号&#xff0c;定义如下&#xff1a;0-0.8V为逻辑低电平&#xff0c;2~5V为高电平&#xff0c;0.8-2V为高阻态&#xff0c;最大上升下降时间为50ns。 计数器可以感测上升沿&#xff08;从逻辑低到逻辑高的转变&#xff09;和下降…

【电源专题】POE连接方式与功率等级划分

在文章【电源专题】什么是POE&#xff1f;中我们讲到了&#xff1a;PoE&#xff08;Power over Ethernet&#xff09;是指通过网线传输电力的一种技术&#xff0c;借助现有以太网口通过网线同时为终端设备&#xff08;如&#xff1a;IP电话、AP、IP摄像头等&#xff09;进行数据…

web:[GYCTF2020]Blacklist

题目 点开靶机&#xff0c;页面显示为 查看源码 没有其他线索 先提交1试一下 猜测是sql注入&#xff0c;先测试 同时注意到url 提交为3-1&#xff0c;发现页面回显为空白 可以判断为字符型注入 输入select&#xff0c;看是否存在回显 回显了黑名单限制的关键字 但是发现没有…

第五章 I/O管理 九、磁盘的结构

目录 一、概念 二、磁盘的物理地址 1、定义&#xff1a; 2、图像&#xff1a; 如何读取一个“块”&#xff1a; 三、磁盘的分类 四、总结 一、概念 磁盘是由多个盘片和读写磁头组成的&#xff0c;每个盘片都有自己的读写磁头。盘片表面被划分成许多同心圆的磁道&#xff…

并发编程-CPU缓存架构详解 Disruptor的高性能设计方案

1.CPU缓存架构详解 1.1 CPU高速缓存概念 CPU缓存即高速缓冲存储器&#xff0c;是位于CPU与主内存间的一种容量较小但速度很高的存储器。CPU高 速缓存可以分为一级缓存&#xff0c;二级缓存&#xff0c;部分高端CPU还具有三级缓存&#xff0c;每一级缓存中所储存的全部数 据都…

深入了解 RocketMQ:高性能消息中间件

二、RocketMQ基本概念 2.1 消息模型&#xff08;Message Model&#xff09; RocketMQ主要由Producer、Broker、Consumer三部分组成&#xff0c;其中Producer负责生产消息&#xff0c;Consumer负责消费消息&#xff0c;Broker负责存储消息。Broker在实际部署过程中对应一台服务…

硬件知识积累 RS422接口

1. RS422 基本介绍 EIA-422&#xff08;过去称为RS-422&#xff09;是一系列的规定采用4线&#xff0c;全双工&#xff0c;差分传输&#xff0c;多点通信的数据传输协议。它采用平衡传输采用单向/非可逆&#xff0c;有使能端或没有使能端的传输线。和RS-485不同的是EIA-422不允…

高精度5米分辨率DEM数字高程数据

​5米分辨率DEM/DSM(无控)&#xff0c;以多颗高分辨率卫星数据为原始数据&#xff0c;基于智能立体模型构建与点云密集匹配&#xff0c;利用网络分布式与多核并行计算技术&#xff0c;三维点云融合与地形提取技术&#xff0c;辅以智能化的人机交互编辑等手段&#xff0c;处理和…

Android开发知识学习——Kotlin基础

函数声明 声明函数要用用 fun 关键字&#xff0c;就像声明类要用 class 关键字一样 「函数参数」的「参数类型」是在「参数名」的右边 函数的「返回值」在「函数参数」右边使用 : 分隔&#xff0c;没有返回值时可以省略 声明没有返回值的函数&#xff1a; fun main(){println…

阿里云发布通义千问2.0,性能超GPT-3.5,加速追赶GPT-4

10月31日&#xff0c;阿里云正式发布千亿级参数大模型通义千问2.0。在10个权威测评中&#xff0c;通义千问2.0综合性能超过GPT-3.5&#xff0c;正在加速追赶GPT-4。当天&#xff0c;通义千问APP在各大手机应用市场正式上线&#xff0c;所有人都可通过APP直接体验最新模型能力。…

聊一聊B端产品和C端产品的区别

To C 和 To B 的产品究竟有什么区别&#xff1f;难道仅仅只是使用对象和买单者不一样嘛&#xff1f;刚入行的产品经理是不是傻傻分不清楚&#xff1f;做产品经理这么久的你是否思考过这个问题&#xff1f; 作为一名产品经理&#xff0c;也设计过To B 和 To C的产品&#xff0c…

13年测试老鸟,软件测试经验总结分享,这几年你走了多少坑...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试阶段划分 …

个性化医疗:数字孪生的未来之路

数字孪生技术已经成为医疗领域的一项重要创新&#xff0c;为医疗保障提供了全新的可能性。它基于数学、物理和计算机科学原理&#xff0c;通过创建数字化模型和仿真来模拟生物系统和医疗设备。 1. 个性化治疗 数字孪生技术可创建患者的个性化模型&#xff0c;以更好地了解疾病…

Python 自动化(十六)静态文件处理

准备工作 将不同day下的代码分目录管理&#xff0c;方便后续复习查阅 (testenv) [rootlocalhost projects]# ls day01 day02 (testenv) [rootlocalhost projects]# mkdir day03 (testenv) [rootlocalhost projects]# cd day03 (testenv) [rootlocalhost day03]# django-admi…

C语言 每日一题 day9

求最大值及其下标 本题要求编写程序&#xff0c;找出给定的n个数中的最大值及其对应的最小下标&#xff08;下标从0开始&#xff09;。 输入格式 : 输入在第一行中给出一个正整数n&#xff08;1 < n≤10&#xff09;。第二行输入n个整数&#xff0c;用空格分开。 输出格式 …

Nodejs和npm的使用方法和教程

Nodejs简介 Node.js 是一个开源和跨平台的 JavaScript 运行时环境。 它几乎是任何类型项目的流行工具&#xff01; &#xff08; 运行环境&#xff0c;是不是很熟悉&#xff0c;对。就是 java JRE&#xff0c;Java 运行时环境&#xff09; Node.js 在浏览器之外运行 V8 Java…

2023 CSP-J题解

T1 小苹果 题目描述 理论分析 对于第一问&#xff0c;我们按照题意模拟每天取走的是多少个苹果即可。由于每天可以取走原来的,数据范围没次会降低到&#xff0c;也就是说这样的过程的时间复杂度可以用下式表示&#xff1a; 对于本题的数据范围n<1e9&#xff0c;这个时间复杂…

PHP/MySQL开发本地服务器软件 MAMP Pro for Mac

MAMP Pro是一款专为Mac用户设计的全功能本地服务器软件&#xff0c;可以将电脑变成一个完整的Web开发环境。无论个人开发者、网站管理员还是团队协作&#xff0c;MAMP Pro都提供了强大的工具和便捷的管理方式&#xff0c;能够更加高效地构建和测试网站。 MAMP Pro的基本功能包括…