full_stack 发表于 2022-5-11 09:25

【平头哥RVB2601创意应用开发】流水灯渐变灯

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

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

<p>再体验一下最简单的人机交互应用&mdash;&mdash;点亮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&amp;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>&nbsp;</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 />
&nbsp;</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&lt;24; i++)
        {
                if(0x800000 == (dat &amp; 0x800000) )        {csi_gpio_pin_write(&amp;r, GPIO_PIN_HIGH); delay_250ns(); delay_250ns(); delay_250ns(); csi_gpio_pin_write(&amp;r, GPIO_PIN_LOW); delay_100ns(); delay_100ns();}
                else                                                                {csi_gpio_pin_write(&amp;r, GPIO_PIN_HIGH); delay_250ns(); csi_gpio_pin_write(&amp;r, GPIO_PIN_LOW); delay_100ns(); delay_250ns(); delay_250ns();}
                dat &lt;&lt;= 1;                                                       
        }
}

void WS_SetAll( uint32_t color, uint32_t led_num)                        //发送同样的颜色color_num,led_num个数量的灯,颜色序号
{
        uint32_t j;
        for(j=0; j&lt;led_num; j++)
        {
                WS_Set_One(color);
        }
        csi_gpio_pin_write(&amp;r, GPIO_PIN_LOW);
}
int32_t abs0(int32_t num)
{
      if(num&gt;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&gt;&gt;8) ;
        Green0 = (color0&gt;&gt;16) ;
        Blue0= color0 ;
       
        Red1   = (color1&gt;&gt;8);
        Green1 = (color1&gt;&gt;16);
        Blue1= color1;
       
        // 计算需要多少步(取差值的最大值)
        RedMinus   = Red1 - Red0 ;
        GreenMinus = Green1 - Green0;
        BlueMinus= Blue1 - Blue0;
       
        NStep = ( abs0(RedMinus) &gt; abs0(GreenMinus) ) ? abs0(RedMinus):abs0(GreenMinus);
        NStep = ( NStep &gt; abs0(BlueMinus) ) ? NStep:abs0(BlueMinus);
        // 计算出各色步进值
        RedStep   = (float)RedMinus   / NStep;
        GreenStep = (float)GreenMinus / NStep;
        BlueStep= (float)BlueMinus/ NStep;
       

        // 渐变开始
        for(i=0; i&lt; NStep; i++)
        {
                Red1   = Red0   + (int)(RedStep   * i);
                Green1 = Green0 + (int)(GreenStep * i);
                Blue1= Blue0+ (int)(BlueStep* i);       
                color= Green1&lt;&lt;16 | Red1&lt;&lt;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(&amp;r, PA7);
    csi_gpio_pin_dir(&amp;r, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_init(&amp;g, PA25);
    csi_gpio_pin_dir(&amp;g, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_init(&amp;b, PA4);
    csi_gpio_pin_dir(&amp;b, GPIO_DIRECTION_OUTPUT);
    g_ctr = 0;
}

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

      csi_gpio_pin_write(&amp;r, GPIO_PIN_HIGH);
      csi_gpio_pin_write(&amp;g, GPIO_PIN_LOW);
      csi_gpio_pin_write(&amp;b, GPIO_PIN_LOW);
    }
    else if (g_ctr % 2 == 0)
    {
      csi_gpio_pin_write(&amp;r, GPIO_PIN_LOW);
      csi_gpio_pin_write(&amp;g, GPIO_PIN_HIGH);
      csi_gpio_pin_write(&amp;b, GPIO_PIN_LOW);
    }
    else
    {
      csi_gpio_pin_write(&amp;r, GPIO_PIN_LOW);
      csi_gpio_pin_write(&amp;g, GPIO_PIN_LOW);
      csi_gpio_pin_write(&amp;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 &lt;= 30; arg++)
                                WS_SetAll(0xFF0000, arg),udelay(25 * 1000);
                        WS_SetAll(0x00, 30);
                }
      //led_refresh();
    }
}</code></pre>

<p>&nbsp;</p>

wangerxian 发表于 2022-5-11 11:38

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

full_stack 发表于 2022-5-11 15:41

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

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

wangerxian 发表于 2022-5-11 15:54

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

<p>是啊,可以在家搞个KTV,哈哈</p>
页: [1]
查看完整版本: 【平头哥RVB2601创意应用开发】流水灯渐变灯