2025|3

34

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

【平头哥RVB2601创意应用开发】流水灯渐变灯 [复制链接]

  本帖最后由 full_stack 于 2022-5-11 16:11 编辑

学习完调试方法,也建立helloworld并调试工程之后,

再体验一下最简单的人机交互应用——点亮LED灯

老样子,在CDK欢迎界面新建工程中搜索2601,上下翻找,就能找到一个ch2601_marquee_demo的工程,就从这个工程开始。

打开工程之后编译下载运行,复位之后看到左下角RGB灯依次亮起三种不同颜色,说明工程正常没有问题,基本上算是一个跑马灯例程。

但是看到main函数就几句话,从软件的角度,以及找到方法分析一下例程。

int main(void)
{
    board_yoc_init();

    printf("===%s, %d\n", __FUNCTION__, __LINE__);
    printf("===%s, %d\n", __FUNCTION__, __LINE__);
    aos_task_new("demo", demo_task, NULL, 10 * 1024);
    return 0;
}

程序运行到main之后,第一个函数看函数名是板子的初始化,然后接下来的两个函数是打印函数以及行数。

此时

右键aos_task_new函数名选择Goto Declaration或者按住键盘ALT健可查看函数声明,

右键aos_task_new函数名选择Goto Implementation或者按住键盘Ctrl健可查看函数原型,

/**
 * Create a task.
 *
 * @param[in]  name       task name.
 * @param[in]  fn         function to run.
 * @param[in]  arg        argument of the function.
 * @param[in]  stacksize  stack-size in bytes.
 *
 * @return 0: success.
 */
int aos_task_new(const char *name, void (*fn)(void *), void *arg, int stack_size);

 

接口定义
动态创建一个任务
int aos_task_new(const char name, void (fn)(void ), void arg, int stack_size);
动态创建一个任务,任务句柄不返回,创建完后自动运行 采用默认优先级AOS_DEFAULT_APP_PRI(32),受宏RHINO_CONFIG_KOBJ_DYN_ALLOC开关控制

参数:

name:任务名
fn:任务处理函数
Arg: 任务处理函数参数
stack_size:任务栈大小(单位:字节)
返回值:

类型:0 返回成功 小于0返回失败

通过查看函数原型,大概可以明白这个函数意思是创建一个任务

如果看英文不习惯可以选择查看官方操作系统API:

https://yoc.docs.t-head.cn/yocbook/Chapter3-AliOS/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%8E%A5%E5%8F%A3/%E4%BB%BB%E5%8A%A1.html

搜索 aos_task_new 点击第一个 任务,就能找到该函数的详细说明。

创建完后自动运行 采用默认优先级。

然后找到这个函数,稍微懂点C语言的基本就能看懂了,

一系列的初始化之后,一秒钟更新一次LED,就出现了跑马灯的效果。

static void demo_task(void *arg)
{
    lv_init();
    oled_init();
    lable_test();
    led_pinmux_init();

    while (1)
    {
        lv_task_handler();
        udelay(1000 * 1000);
        lv_tick_inc(1);
        led_refresh();
    }
}

细心的还能发现,main.c文件和led.c文件有相同的void led_pinmux_init()和void led_refresh()函数,其实,这是历程中用不同的实现方式实现跑马灯的效果,实际执行中只有一个被编译,在app_config.h中可以切换,突然想到,这种通过宏定义没被编译的代码,改变下颜色,成灰色,可视化就更好了。

#define CONFIG_PWM_MODE
//#define CONFIG_GPIO_MODE

接下来做个升级,共享一篇我移植的WS2812的程序,主要是实现渐变灯的效果,但是我发现拍视频之后效果很不明显,然后又加了个流水灯的效果。

程序用到的IO口为PA7,灯条电源外接(12V),刚开始没共地,灯一直闪闪的不停,后来共地之后很稳定。视频效果及源代码如下。

渐变灯流水灯.mp4 (8.61 MB, 下载次数: 0)

渐变灯流水灯

 

volatile uint32_t g_debug = 0;
volatile uint32_t g_debug_v = 0;

static void demo_task(void *arg);
#define delay_250ns()  do {    \
        __NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();  __NOP();   \
		        __NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();  __NOP();   \
		        __NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();  __NOP();   \
} while (0)

#define delay_100ns()  do {    \
		__NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();    \
				__NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();    \
				__NOP();  __NOP();  __NOP();  __NOP(); __NOP();  __NOP();  __NOP();  __NOP();    \
        __NOP();    \
} while (0)

#include "csi_core.h"
/**
 * main
 */
int main(void)
{
    board_yoc_init();

    printf("===%s, %d\n", __FUNCTION__, __LINE__);
    printf("===%s, %d\n", __FUNCTION__, __LINE__);
    aos_task_new("demo", demo_task, NULL, 10 * 1024);
    return 0;
}

static void lable_test(void)
{
    lv_obj_t *p = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(p, LV_LABEL_LONG_BREAK);
    lv_label_set_align(p, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_pos(p, 0, 4);
    lv_obj_set_size(p, 128, 60);
    lv_label_set_text(p, "WS2812B\nColorToColor\nTest");
}



#ifdef CONFIG_GPIO_MODE
static uint32_t g_ctr = 0;
static csi_gpio_pin_t r;
static csi_gpio_pin_t g;
static csi_gpio_pin_t b;

void WS_Set_One(uint32_t dat)
{
	uint32_t i;	
	for(i=0; i<24; i++)
	{
		if(0x800000 == (dat & 0x800000) )	{csi_gpio_pin_write(&r, GPIO_PIN_HIGH); delay_250ns(); delay_250ns(); delay_250ns(); csi_gpio_pin_write(&r, GPIO_PIN_LOW); delay_100ns(); delay_100ns();}
		else								{csi_gpio_pin_write(&r, GPIO_PIN_HIGH); delay_250ns(); csi_gpio_pin_write(&r, GPIO_PIN_LOW); delay_100ns(); delay_250ns(); delay_250ns();}
		dat <<= 1;							
	}
}

void WS_SetAll( uint32_t color, uint32_t led_num)			//发送同样的颜色color_num,led_num个数量的灯,颜色序号
{
	uint32_t j;
	for(j=0; j<led_num; j++)
	{
		WS_Set_One(color);
	}
	csi_gpio_pin_write(&r, GPIO_PIN_LOW);
}
int32_t abs0(int32_t num)
{
        if(num>0) return num;
        
        num = -num;
        return num;
}

void ColorToColor(uint32_t color0, uint32_t color1, uint32_t len)
{
	unsigned char Red0, Green0, Blue0;  // 起始三原色
	unsigned char Red1, Green1, Blue1;  // 结果三原色
	int	 RedMinus, GreenMinus, BlueMinus;	// 颜色差(color1 - color0)
	unsigned char NStep; 							// 需要几步
	float RedStep, GreenStep, BlueStep;		// 各色步进值
	uint32_t color;							// 结果色
	unsigned char i;
	// 绿 红 蓝 三原色分解
	Red0   = (color0>>8) ;
	Green0 = (color0>>16) ;
	Blue0  = color0 ;
	
	Red1   = (color1>>8);
	Green1 = (color1>>16);
	Blue1  = color1;
	
	// 计算需要多少步(取差值的最大值)
	RedMinus   = Red1 - Red0 ; 
	GreenMinus = Green1 - Green0; 
	BlueMinus  = Blue1 - Blue0;
	
	NStep = ( abs0(RedMinus) > abs0(GreenMinus) ) ? abs0(RedMinus):abs0(GreenMinus);
	NStep = ( NStep > abs0(BlueMinus) ) ? NStep:abs0(BlueMinus);
	// 计算出各色步进值
	RedStep   = (float)RedMinus   / NStep;
	GreenStep = (float)GreenMinus / NStep;
	BlueStep  = (float)BlueMinus  / NStep;
	

	// 渐变开始
	for(i=0; i< NStep; i++)
	{
		Red1   = Red0   + (int)(RedStep   * i);
		Green1 = Green0 + (int)(GreenStep * i);
		Blue1  = Blue0  + (int)(BlueStep  * i);	
		color  = Green1<<16 | Red1<<8 | Blue1; 	// 合成  绿红蓝		
		WS_SetAll(color, 30);

		udelay(8*1000);						// 渐变速度
	}
}


void led_pinmux_init()
{
    csi_pin_set_mux(PA7, PIN_FUNC_GPIO);
    csi_pin_set_mux(PA25, PIN_FUNC_GPIO);
    csi_pin_set_mux(PA4, PIN_FUNC_GPIO);
    csi_gpio_pin_init(&r, PA7);
    csi_gpio_pin_dir(&r, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_init(&g, PA25);
    csi_gpio_pin_dir(&g, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_init(&b, PA4);
    csi_gpio_pin_dir(&b, GPIO_DIRECTION_OUTPUT);
    g_ctr = 0;
}

void led_refresh()
{
    g_ctr++;
    if (g_ctr % 3 == 0)
    {

        csi_gpio_pin_write(&r, GPIO_PIN_HIGH);
        csi_gpio_pin_write(&g, GPIO_PIN_LOW);
        csi_gpio_pin_write(&b, GPIO_PIN_LOW);
    }
    else if (g_ctr % 2 == 0)
    {
        csi_gpio_pin_write(&r, GPIO_PIN_LOW);
        csi_gpio_pin_write(&g, GPIO_PIN_HIGH);
        csi_gpio_pin_write(&b, GPIO_PIN_LOW);
    }
    else
    {
        csi_gpio_pin_write(&r, GPIO_PIN_LOW);
        csi_gpio_pin_write(&g, GPIO_PIN_LOW);
        csi_gpio_pin_write(&b, GPIO_PIN_HIGH);
    }
}

void marquee_test(void)
{
    while (1)
    {

        udelay(1000 * 1000);

        led_refresh();
    }
}
#endif

static void demo_task(void *arg)
{

    lv_init();
    oled_init();
    lable_test();
    led_pinmux_init();

    while (1)
    {
		unsigned char arg;
        lv_task_handler();
        udelay(1000 * 1000);
        lv_tick_inc(1);
		//WS_SetAll(0xFFFFFF, 30);
		ColorToColor(0xFF0000, 0x00FF00,30);		//红到绿
		ColorToColor(0x0000FF, 0xFFFFFF,30);		//蓝到白
		ColorToColor(0x0000FF, 0xFF0000,30);		//蓝到白
		while(1)
		{
			for(arg = 0; arg <= 30; arg++)
				WS_SetAll(0xFF0000, arg),udelay(25 * 1000);
			WS_SetAll(0x00, 30);
		}
        //led_refresh();
    }
}

 

最新回复

是啊,可以在家搞个KTV,哈哈   详情 回复 发表于 2022-5-11 15:54
点赞 关注
 
 

回复
举报

7244

帖子

2

TA的资源

版主

沙发
 

后期想给自己家里搞一个智能灯,接入小爱同学~

点评

WS2812是真好玩,只要一个IO,可以千万级别的颜色效果。  详情 回复 发表于 2022-5-11 15:41
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
wangerxian 发表于 2022-5-11 11:38 后期想给自己家里搞一个智能灯,接入小爱同学~

WS2812是真好玩,只要一个IO,可以千万级别的颜色效果。

点评

是啊,可以在家搞个KTV,哈哈  详情 回复 发表于 2022-5-11 15:54
 
 
 

回复

7244

帖子

2

TA的资源

版主

4
 
full_stack 发表于 2022-5-11 15:41 WS2812是真好玩,只要一个IO,可以千万级别的颜色效果。

是啊,可以在家搞个KTV,哈哈

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表