首页 > 其他分享 >在AvaotaA1全志T527开发板上驱动WS2812 RGB LCD

在AvaotaA1全志T527开发板上驱动WS2812 RGB LCD

时间:2024-07-22 14:26:56浏览次数:14  
标签:leds LED T527 全志 LCD fd path led cmax

在 Avaota SBC 的开发板中,通常会有几个 WS2812 RGB LED 灯。例如 Avaota A1 的如下位置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于 AvaotaOS,提供了硬件的 LEDC(Light Emitting Diode Controller),发光二极管控制器作为WS2812 RGB LED 灯的控制器。每个 LED 的三基色均可实现 256 级亮度显示,因此整个 LED 可完成 256ˆ3(即 16777216)种颜色的全真色彩显示。模块支持最大1024颗外控 LED级联。

WS2812 驱动介绍

LED 典型电路如图所示,其中 DI 表示控制数据输入脚,DO 表示控制数据输出脚。DI 端接收从控制器传过来的数据,每个 LED 内部的数据锁存器会存储 24bit 数据,剩余的数据经过内部整形处理电路整形放大后通过 DO 端口开始转发输出给下一个级联的 LED。因此,每经过一个LED,数据减少 24bit。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LED典型电路如上图所示,其中 DI 表示控制数据输入脚,DO 表示控制数据输出脚。DI 端接受从控制器传输过来的数据,每个 LED 内部的数据锁存器会存储 24bit (分别对应 R,G,B 三种颜色)数据,剩余的数据经过内部整形处理电路整形放大后通过 DO 端口开始转发输出给下一个级联的 LED 。因此,每经过一个 LED ,数据减少 24bit。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

WS2812 驱动配置说明

配置驱动,默认 Avaota OS 已经勾选该驱动。如果未勾选请配置

LED Drivers ->
	<*> LEDC Support for Allwinner SoCs

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

配置设备树,首先需要配置 PIO 节点,配置 LEDC 使用的 GPIO

&pio {
	ledc_pins_a: ledc@0{
		pins ="PH19";
		function ="ledc";
		drive-strength =<10>;
	};

	ledc_pins_b: ledc@1{
		pins ="PH19";
		function ="gpio_in";
	};
};

然后配置 LEDC 模块的数值

&ledc  {
	pinctrl-names ="default","sleep";
	pinctrl-0=<&ledc_pins_a>;
	pinctrl-1=<&ledc_pins_b>;
	led_count =<4>;
	output_mode ="GRB";
	reset_ns =<84>;
	t1h_ns =<800>;
	t1l_ns =<320>;
	t0h_ns =<300>;
	t0l_ns =<800>;
	wait_time0_ns =<84>;
	wait_time1_ns =<84>;
	wait_data_time_ns =<600000>;
	status ="okay";
};
  • pinctrl-names: 用于表示 0 和 1 的 pinctrl 哪个是默认和休眠状态。
  • pinctrl-0: 引脚配置,这里是默认使用的时候配置。
  • pinctrl-1: 同上,这里是休眠时的配置。
  • led_count: LED 灯的数目,根据硬件配置。
  • output_mode: LED 灯输出模式,根据 LED 灯的 datasheet 进行配置。
  • reset_ns: LED 灯 reset 时间控制。
  • t1h_ns: 1 码高电平时间,根据 LED 灯的 datasheet 进行配置。
  • t1l_ns: 1 码低电平时间,根据 LED 灯的 datasheet 进行配置。
  • t0h_ns: 0 码高电平时间,根据 LED 灯的 datasheet 进行配置。
  • t0l_ns: 0 码低电平时间,根据 LED 灯的 datasheet 进行配置。
  • wait_time0_ns: 两个 LED 数据之间的等待时间,根据 LED 灯的 datasheet 进行配置。
  • wait_time1_ns: 帧数据之间的等待时间,根据 LED 灯的 datasheet 进行配置。
  • wait_data_time_ns: 内部 FIFO 等待数据时间,超过时间触发异常中断。
  • status: 设备状态。

WS2812 使用说明

驱动会在 /sys/class/leds 注册每个LED对应的设备目录

/sys/class/leds/sunxi_led0r // 红色
/sys/class/leds/sunxi_led0g // 绿色
/sys/class/leds/sunxi_led0b // 蓝色

其中 0 表示LED的编号,如果是 1 号 LED 则是

/sys/class/leds/sunxi_led1r
/sys/class/leds/sunxi_led1g
/sys/class/leds/sunxi_led1b

需要调节第 0 个LED的颜色为白光且最亮,操作如下:

echo 255 > /sys/class/leds/sunxi_led0r/brightness
echo 255 > /sys/class/leds/sunxi_led0g/brightness
echo 255 > /sys/class/leds/sunxi_led0b/brightness

实现七彩流水灯

C 语言实现
#include<fcntl.h>
#include<stdint.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/times.h>
#include<sys/types.h>
#include<unistd.h>

// 使用RGB 分量合成颜色值
#defineMERAGECOLOR(G, R, B)(((uint32_t)G <<16)|((uint16_t)R <<8)| B)
#definePIXEL_NUM4

int fd[PIXEL_NUM][3];// 存放文件描述符数组

voidinit_leds(){
char path[100];

// 初始化LED文件描述符
for(int i =0; i < PIXEL_NUM;++i){
snprintf(path,sizeof(path),"/sys/class/leds/sunxi_led%d%c/brightness", i,'r');
        fd[i][0]=open(path, O_WRONLY);
if(fd[i][0]==-1){
printf("Failed to open file for LED %d, color %c\n", i,'r');
}
snprintf(path,sizeof(path),"/sys/class/leds/sunxi_led%d%c/brightness", i,'g');
        fd[i][1]=open(path, O_WRONLY);
if(fd[i][1]==-1){
printf("Failed to open file for LED %d, color %c\n", i,'g');
}
snprintf(path,sizeof(path),"/sys/class/leds/sunxi_led%d%c/brightness", i,'b');
        fd[i][2]=open(path, O_WRONLY);
if(fd[i][2]==-1){
printf("Failed to open file for LED %d, color %c\n", i,'b');
}
}
}

voidsunxi_set_led_brightness(int led_id,uint8_t r,uint8_t g,uint8_t b){
if(led_id <0|| led_id >= PIXEL_NUM){
printf("Invalid LED ID\n");
return;
}

dprintf(fd[led_id][0],"%d", r);
dprintf(fd[led_id][1],"%d", g);
dprintf(fd[led_id][2],"%d", b);
}

voidclose_leds(){
// 关闭LED文件描述符
for(int i =0; i < PIXEL_NUM;++i){
for(int j =0; j <3;++j){
if(fd[i][j]!=-1){
close(fd[i][j]);
}
}
}
}

// 生成颜色
uint32_tWS281x_Wheel(uint8_t wheelPos){
    wheelPos =255- wheelPos;
if(wheelPos <85){
returnMERAGECOLOR(255- wheelPos *3,0, wheelPos *3);
}
if(wheelPos <170){
        wheelPos -=85;
returnMERAGECOLOR(0, wheelPos *3,255- wheelPos *3);
}
    wheelPos -=170;
returnMERAGECOLOR(wheelPos *3,255- wheelPos *3,0);
}

// 亮度设置
voidWS281xLSet(uint32_t id,uint32_t rgb,float k){
uint8_t r, g, b;
float h, s, v;
uint8_t cmax, cmin, cdes;

    r =(uint8_t)(rgb >>16);
    g =(uint8_t)(rgb >>8);
    b =(uint8_t)(rgb);

    cmax = r > g ? r : g;
if(b > cmax)
        cmax = b;
    cmin = r < g ? r : g;
if(b < cmin)
        cmin = b;
    cdes = cmax - cmin;

    v = cmax /255.0f;
    s = cmax ==0?0: cdes /(float) cmax;
    h =0;

if(cmax == r && g >= b)
        h =((g - b)*60.0f/ cdes)+0;
elseif(cmax == r && g < b)
        h =((g - b)*60.0f/ cdes)+360;
elseif(cmax == g)
        h =((b - r)*60.0f/ cdes)+120;
else
        h =((r - g)*60.0f/ cdes)+240;

    v *= k;

float f, p, q, t;
float rf, gf, bf;
int i =((int)(h /60)%6);
    f =(h /60)- i;
    p = v *(1- s);
    q = v *(1- f * s);
    t = v *(1-(1- f)* s);
switch(i){
case0:
            rf = v;
            gf = t;
            bf = p;
break;
case1:
            rf = q;
            gf = v;
            bf = p;
break;
case2:
            rf = p;
            gf = v;
            bf = t;
break;
case3:
            rf = p;
            gf = q;
            bf = v;
break;
case4:
            rf = t;
            gf = p;
            bf = v;
break;
case5:
            rf = v;
            gf = p;
            bf = q;
break;
default:
break;
}

    r =(uint8_t)(rf *255.0);
    g =(uint8_t)(gf *255.0);
    b =(uint8_t)(bf *255.0);

sunxi_set_led_brightness(id, r, g, b);
}

// 测试 LEDC
intmain(){
int i =0, j =0, err;
int mode =0;
uint8_t R =0, G =0, B =0;

init_leds();

while(1){
for(j =0; j <256; j++){
for(i =0; i < PIXEL_NUM; i++){
WS281xLSet(i,WS281x_Wheel(((i *256/ PIXEL_NUM)+ j)&255),0.1);
}
usleep(1000);
}
usleep(10000);
}

close_leds();

return1;
}
Python 实现
import os
import time
import math

PIXEL_NUM =4
fd =[[None,None,None]for _ inrange(PIXEL_NUM)]# 文件描述符数组

definit_leds():
global fd
    path =""

# 初始化LED文件描述符
for i inrange(PIXEL_NUM):
        path =f"/sys/class/leds/sunxi_led{i}{'r'}/brightness"
        fd[i][0]= os.open(path, os.O_WRONLY)
if fd[i][0]==-1:
print(f"Failed to open file for LED {i}, color {'r'}")

        path =f"/sys/class/leds/sunxi_led{i}{'g'}/brightness"
        fd[i][1]= os.open(path, os.O_WRONLY)
if fd[i][1]==-1:
print(f"Failed to open file for LED {i}, color {'g'}")

        path =f"/sys/class/leds/sunxi_led{i}{'b'}/brightness"
        fd[i][2]= os.open(path, os.O_WRONLY)
if fd[i][2]==-1:
print(f"Failed to open file for LED {i}, color {'b'}")

defsunxi_set_led_brightness(led_id, r, g, b):
if led_id <0or led_id >= PIXEL_NUM:
print("Invalid LED ID")
return

    os.write(fd[led_id][0],str(r).encode())
    os.write(fd[led_id][1],str(g).encode())
    os.write(fd[led_id][2],str(b).encode())

defclose_leds():
# 关闭LED文件描述符
global fd
for i inrange(PIXEL_NUM):
for j inrange(3):
if fd[i][j]isnotNone:
                os.close(fd[i][j])

defws281x_wheel(wheel_pos):
    wheel_pos =255- wheel_pos
if wheel_pos <85:
return merge_color(255- wheel_pos *3,0, wheel_pos *3)
if wheel_pos <170:
        wheel_pos -=85
return merge_color(0, wheel_pos *3,255- wheel_pos *3)
    wheel_pos -=170
return merge_color(wheel_pos *3,255- wheel_pos *3,0)

defmerge_color(r, g, b):
return(r <<16)|(g <<8)| b

defws281x_lset(id, rgb, k):
    r =(rgb >>16)&0xFF
    g =(rgb >>8)&0xFF
    b = rgb &0xFF

    cmax =max(r, g, b)
    cmin =min(r, g, b)
    cdes = cmax - cmin

    v = cmax /255.0
    s = cmax /255.0if cmax ==0else cdes / cmax

if cmax == r and g >= b:
        h =(g - b)*60.0/ cdes +0
elif cmax == r and g < b:
        h =(g - b)*60.0/ cdes +360
elif cmax == g:
        h =(b - r)*60.0/ cdes +120
else:
        h =(r - g)*60.0/ cdes +240

    v *= k

    i = math.floor(h /60)%6
    f = h /60- i
    p = v *(1- s)
    q = v *(1- f * s)
    t = v *(1-(1- f)* s)

if i ==0:
        rf, gf, bf = v, t, p
elif i ==1:
        rf, gf, bf = q, v, p
elif i ==2:
        rf, gf, bf = p, v, t
elif i ==3:
        rf, gf, bf = p, q, v
elif i ==4:
        rf, gf, bf = t, p, v
else:
        rf, gf, bf = v, p, q

    r =int(rf *255.0)
    g =int(gf *255.0)
    b =int(bf *255.0)

    sunxi_set_led_brightness(id, r, g, b)

defmain():
    init_leds()
try:
whileTrue:
for j inrange(256):
for i inrange(PIXEL_NUM):
                    ws281x_lset(i, ws281x_wheel(int((float(i)*256.0/float(PIXEL_NUM)+ j))&255),0.1)
                time.sleep(0.01)# 控制LED变化速度
            time.sleep(0.1)
finally:
        close_leds()

if __name__ =="__main__":
    main()

标签:leds,LED,T527,全志,LCD,fd,path,led,cmax
From: https://blog.csdn.net/weixin_43094346/article/details/140603398

相关文章

  • 【嵌入式DIY实例-ESP8266篇】-LCD ST7789显示DHT11传感器数据
    LCDST7789显示DHT11传感器数据文章目录LCDST7789显示DHT11传感器数据1、硬件准备与接线2、代码实现本文介绍如何将ESP8266NodeMCU板(ESP-12E)与DHT11(RHT01)数字湿度和温度传感器连接。NodeMCU从DHT11传感器读取温度和湿度值,并在ST7789TFT......
  • 【嵌入式DIY实例-ESP8266篇】- LCD ST7789显示DS18B20传感器数据
    LCDST7789显示DS18B20传感器数据文章目录LCDST7789显示DS18B20传感器数据1、硬件准备与接线2、代码实现本文介绍如何使用ESP8266NodeMCU开发板(ESP-12E)和DS18B20数字温度传感器实现简单的数字温度计。在此项目中,NodeMCU板从DS18B20传感器读......
  • LCD控制函数详解
    1.LCD控制器模块介绍1.1硬件框图LCD控制器的作用:承上启下IMX6ULL的LCD控制器名称为eLCDIF(EnhancedLCDInterface,增强型LCD接口),主要特性如下:支持MPU模式:有些显示屏自带显存,只需要把命令、数据发送给显示屏即可;就是前面讲的8080接口VSYNC模式:跟MPU模式类似,多了VSYNC......
  • 基于QEMU的LCD驱动详解
    1.使用QEMU的优点概述:使用QEMU模型LCD屏幕,可以只写驱动程序,不需要设置LCD硬件相关,也不需要映射Framebuffer。使用QEMU可以非常方便地调试内核、查看驱动程序执行过程有助于深入研究内核及驱动Linux驱动=驱动框架+硬件操作。如果硬件操作足够简单,我们就可以把精力......
  • 光电显示技术-LCD篇
    LCD显示技术本文对应资料:1.视频资料,2.PPT资料1.技术简介TFT-LCD是每一个子像素均由单独的薄膜晶体管(TFT)驱动实现显示,该方法在非晶硅显示面板上大规模的被使用,使得TFT-LCD成为目前主流的显示器件,下图是TFT的显示结构。图1TFT-LCD显示结构该结构主要由前面的面板,后方主要由......
  • HAL库源码移植与使用之驱动LCD屏
    LCD屏会有烧屏残影的风险,但因其价格便宜他非常适合用于单片机显示显示屏分为以下几种:他的组成部包含玻璃基板、背光、驱动IC等LCD接口的种类MCU很简单,连51单片机都能驱动,但无法频繁刷新,一般有着20几个引脚引出的就是MCU接口我们常用的是就是MCU,下面讲的也是LCD屏幕MCU驱动......
  • mipi LCD 的CLK时钟频率与显示分辨率及帧率的关系
    我们先来看一个公式:Mipiclock=[(width+hsync+hfp+hbp)x(height+vsync+vfp+vbp)]x(bus_width)xfps/(lane_num)/2即mipi屏的传输时钟频率(CLKN,CLKP)等于(屏幕分辨率宽width+hsync+hfp+hbp)x(屏幕分辨率高height+vsync+vfp+vbp)x(RGB显示数据宽度)x帧率/(lane_num)/......
  • 全志科技官方Ubuntu16.04根文件系统镜像的替换和测试方法
    本文主要基于全志A40i开发板——TLA40i-EVM,一款基于全志科技A40i处理器设计的4核ARMCortex-A7高性能低功耗国产评估板,演示Ubuntu根文件系统镜像的替换和测试方法。创龙科技TLA40i-EVM评估板接口资源丰富,引出双路网口、双路CAN、双路USB、双路RS485等通信接口,板载Bluetooth、WIFI......
  • 【资料分享】全志科技T507-H开发板规格书
    1评估板简介 创龙科技TLT507-EVM是一款基于全志科技T507-H处理器设计的4核ARMCortex-A53国产工业评估板,主频高达1.416GHz,由核心板和评估底板组成。核心板CPU、ROM、RAM、电源、晶振等所有器件均采用国产工业级方案,国产化率100%。同时,评估底板大部分元器件亦采用国产工业级......
  • 全志科技T507-H工业核心板规格书
    1核心板简介创龙科技SOM-TLT507是一款基于全志科技T507-H处理器设计的4核ARMCortex-A53全国产工业核心板,主频高达1.416GHz。核心板CPU、ROM、RAM、电源、晶振等所有元器件均采用国产工业级方案,国产化率100%。核心板通过邮票孔连接方式引出MIPICSI、HDMIOUT、RGBDISPLAY、LVDS......