【平头哥RVB2601创意应用开发】流水灯渐变灯
本帖最后由 full_stack 于 2022-5-11 16:11 编辑<p>学习完调试方法,也建立helloworld并调试工程之后,</p>
<p>再体验一下最简单的人机交互应用——点亮LED灯</p>
<p>老样子,在CDK欢迎界面新建工程中搜索2601,上下翻找,就能找到一个ch2601_marquee_demo的工程,就从这个工程开始。</p>
<p></p>
<p>打开工程之后编译下载运行,复位之后看到左下角RGB灯依次亮起三种不同颜色,说明工程正常没有问题,基本上算是一个跑马灯例程。</p>
<p>但是看到main函数就几句话,从软件的角度,以及找到方法分析一下例程。</p>
<pre>
<code>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;
}</code></pre>
<p>程序运行到main之后,第一个函数看函数名是板子的初始化,然后接下来的两个函数是打印函数以及行数。</p>
<p>此时</p>
<p>右键aos_task_new函数名选择Goto Declaration或者按住键盘ALT健可查看函数声明,</p>
<p>右键aos_task_new函数名选择Goto Implementation或者按住键盘Ctrl健可查看函数原型,</p>
<p></p>
<pre>
<code>/**
* Create a task.
*
* @paramname task name.
* @paramfn function to run.
* @paramarg argument of the function.
* @paramstacksizestack-size in bytes.
*
* <a href="home.php?mod=space&uid=784970" target="_blank">@return</a> 0: success.
*/
int aos_task_new(const char *name, void (*fn)(void *), void *arg, int stack_size);</code></pre>
<p> </p>
<pre>
<code>接口定义
动态创建一个任务
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返回失败</code></pre>
<p>通过查看函数原型,大概可以明白这个函数意思是创建一个任务</p>
<p>如果看英文不习惯可以选择查看官方操作系统API:</p>
<p>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</p>
<p>搜索 aos_task_new 点击第一个 任务,就能找到该函数的详细说明。</p>
<p></p>
<p>创建完后自动运行 采用默认优先级。</p>
<p>然后找到这个函数,稍微懂点C语言的基本就能看懂了,</p>
<p>一系列的初始化之后,一秒钟更新一次LED,就出现了跑马灯的效果。</p>
<pre>
<code>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();
}
}</code></pre>
<p>细心的还能发现,main.c文件和led.c文件有相同的void led_pinmux_init()和void led_refresh()函数,其实,这是历程中用不同的实现方式实现跑马灯的效果,实际执行中只有一个被编译,在app_config.h中可以切换,突然想到,这种通过宏定义没被编译的代码,改变下颜色,成灰色,可视化就更好了。</p>
<pre>
<code>#define CONFIG_PWM_MODE
//#define CONFIG_GPIO_MODE</code></pre>
<p>接下来做个升级,共享一篇我移植的WS2812的程序,主要是实现渐变灯的效果,但是我发现拍视频之后效果很不明显,然后又加了个流水灯的效果。</p>
<p>程序用到的IO口为PA7,灯条电源外接(12V),刚开始没共地,灯一直闪闪的不停,后来共地之后很稳定。视频效果及源代码如下。</p>
<p></p>
<p></p>
<p>a2f3bed719ed95013d02eee521334a92<br />
</p>
<pre>
<code>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();
}
}</code></pre>
<p> </p>
<p>后期想给自己家里搞一个智能灯,接入小爱同学~</p>
wangerxian 发表于 2022-5-11 11:38
后期想给自己家里搞一个智能灯,接入小爱同学~
<p>WS2812是真好玩,只要一个IO,可以千万级别的颜色效果。</p>
full_stack 发表于 2022-5-11 15:41
WS2812是真好玩,只要一个IO,可以千万级别的颜色效果。
<p>是啊,可以在家搞个KTV,哈哈</p>
页:
[1]