小熊派bearpi-HM-nano(hi3861鸿蒙LiteOS)点亮WS2812灯板(spi方式)

官网代码仓:BearPi-HM_Nano: 小熊派BearPi-HM Nano开发板基于HarmonyOS的源码

代码仓和全网几乎没有hi3861SPI相关的例程序,故分享给大家(首发哈哈)

这个是代码的效果视频

ws2812

驱动ws2812灯板关键点为实现ws2812时序的0/1码

在liteos上我想到有三种方法

1.GPIO翻转

实时性不够,实测的不能得到400ns宽度(0码的脉宽)的电平

2.PWM占空比

没有找到dma发送的接口(不能连续发送多个字节),每次只能设置一个占空比,现象为连续多个相同占空比的电平

3.SPI发数据

理想情况下800K*8HZ发送一个字节(8bit)模拟ws2812一个时序周期

发送0xFC(11111100)时为‘1码’

发送0xE0 (11100000)时为‘0码’

发送0x00时为低电平,用作break/reset(MOSI空闲时为高电平),放在每帧开始

以下为接线图

 以下为源码

spi_example.c

#include <stdio.h>
#include <string.h>
#include "hi_gpio.h"
#include "hi_spi.h"
#include <hi_io.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_pwm.h"
#include "wifiiot_gpio.h"
#include "wifiiot_spi.h"
#include "wifiiot_gpio_ex.h"
#define RED_INDEX   0
#define GREEN_INDEX 1
#define BLUE_INDEX  2


//功能:把 3BYTE 的RGB数据转换成 24BYTE SPI数据
static void WS2812_send(unsigned char *rgb)
{
    unsigned char data[24];
    unsigned char i, bit;
    unsigned char index = 0;
        for(i = 0; i < 8; i++) // GREEN  按位发送
        {
            bit = ((rgb[GREEN_INDEX] << i) & 0x80);
            data[index] = (bit == 0x80) ? 0xfc : 0xe0;//spi发送0xfc 为ws812 1码 spi发送0xe0 为ws812 0码
            index++;
        } 
        for(i = 0; i < 8; i++) // RED
        {
            bit = ((rgb[RED_INDEX]<<i) & 0x80);
            data[index] = (bit==0x80) ? 0xfc : 0xe0;
            index++;
        }
        for(i=0; i<8; i++) // BLUE
        {
            bit = ((rgb[BLUE_INDEX]<<i) & 0x80);
            data[index] = (bit==0x80) ? 0xfc : 0xe0;
            index++;
        }
        hi_spi_host_write(WIFI_IOT_SPI_ID_0, data, 24);
}
//色带
unsigned char color[8][3]=
{
    {255,255,255},//白
    {255,255, 0 },
    {255, 0 ,255},
    { 0 ,255,255},
    { 0 , 0 ,255},//蓝
    { 0 ,255, 0 },//绿
    {255, 0 , 0 },//红
    { 0 , 0 , 0 }
};

static void WS2812Task(void)
{

    //初始化GPIO
    GpioInit();
    
    hi_spi_deinit(HI_SPI_ID_0); /* if wake_up from deep sleep, should deinit first */
    hi_spi_cfg_basic_info spi_cfg_basic_info;
    spi_cfg_basic_info.cpha = 0;
    spi_cfg_basic_info.cpol = 0;
    spi_cfg_basic_info.data_width = HI_SPI_CFG_DATA_WIDTH_E_8BIT;
    spi_cfg_basic_info.endian = 0;
    spi_cfg_basic_info.fram_mode = 0;
    spi_cfg_basic_info.freq = 8*900000; 
    hi_spi_cfg_init_param spi_init_param = {0};
    spi_init_param.is_slave = 0;
    hi_spi_init(HI_SPI_ID_0, spi_init_param, &spi_cfg_basic_info); //基本参数配置
    hi_spi_set_loop_back_mode(HI_SPI_ID_0, 1);
    hi_io_set_func(HI_IO_NAME_GPIO_12, HI_IO_FUNC_GPIO_12_SPI0_CSN);//io配置
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_SPI0_CK);
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_SPI0_RXD);
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_SPI0_TXD);
    hi_io_set_driver_strength(HI_IO_NAME_GPIO_6, HI_IO_DRIVER_STRENGTH_2);//驱动能力
    hi_spi_set_irq_mode(HI_SPI_ID_0, 0);
    hi_spi_set_dma_mode(HI_SPI_ID_0, 1);

    unsigned char data[50];
    unsigned char rgb[3];
    unsigned int i;
    while (1)
    {
        for (i = 0; i < 256; i ++)
        {
            memset(data, 0, sizeof(data));
            hi_spi_host_write(WIFI_IOT_SPI_ID_0, data, sizeof(data));//前50byte为低电平break

            for (unsigned int j = 0; j < 256; j ++)//亮度
            {
                rgb[0] = color[i%7][0]&j;//色带
                rgb[1] = color[i%7][1]&j;
                rgb[2] = color[i%7][2]&j;
                for (unsigned int k = 0; k < 256; k ++)//控制256个灯
                WS2812_send(rgb);
                usleep(10 * 1000);
            }
            
        }
        i = 0;
    }
}

static void WS2812ExampleEntry(void)
{
    osThreadAttr_t attr;

    attr.name = "WS2812Task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024;
    attr.priority = osPriorityAboveNormal6 ;

    if (osThreadNew((osThreadFunc_t)WS2812Task, NULL, &attr) == NULL)//创建线程
    {
        printf("Falied to create WS2812Task!\n");
    }
}

APP_FEATURE_INIT(WS2812ExampleEntry);

BUILD.gn 

static_library("spi_example") {
    sources = [
        "spi_example.c",
        "//ohos_bundles/@bearpi/hm_nano_hi3861/platform/drivers/spi/hi_spi.c",
        "//ohos_bundles/@bearpi/hm_nano_hi3861/platform/drivers/spi/spi.c",
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//ohos_bundles/@bearpi/hm_nano_hi3861/include",
    ]
}

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值