小熊派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占空
·
官网代码仓: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条内容
所有评论(0)