AB32开发板测评:GPIO控制RGB彩灯

【AB32VG1】开发板测评:RGB彩灯

最近参加了RT-Thread社区的一个活动,报名了一款开发板的测评,有幸成为第一批测评人员,申请了一块中科蓝讯的开发板AB32VG1,测评任务是GPIO测试,作为点灯老手,本次测评准备使用矩阵键盘输入控制信号,GPIO模拟PWM的方式,输入三路PWM来改变RGB彩灯的颜色,测评完成后总结了这篇文章,分享点灯经验

一、初始准备

1.硬件平台

AB32VG1开发板

在这里插入图片描述

芯片介绍:

CPU:AB5301A;(LQFP48 封装,主频 120M,片上集成 RAM 192K, flash 8 Mbit,ADC,PWM,USB,UART,IIC 等资源)

Flash和RAM真大,感觉专门为了RT-Thread配置的,适合上RTT完整版

2.软件平台

RT-Thread Stdio软件平台

Downloader下载平台

在这里插入图片描述

二、操作步骤

1.RTT环境生成

  • 新建RTT项目

新建RTT控件如下

在这里插入图片描述

选择基于开发板的项目,填写工程名字,选择我们使用到的开发板(AB32VG1),调试器我们随便选,下载方式不是通过此处下载

在这里插入图片描述

注意:如果第一次使用RISC-V芯片需要安装工具链,在SDK管理器中下载工具链

在这里插入图片描述

然右击项目名称,进入属性

在这里插入图片描述

找到MCU->RISC-V ToolchainsPat ,配置Tool的环境,在软件安装位置下面的路径中

软件安装位置\RT-ThreadStudio\repo\Extract\ToolChain_Support_Packages\RISC-V\RISC-V-GCC\10.1.0\bin

在这里插入图片描述

工程新建后左边的项目资源管理器会显示我们的工程,我们把他展开,并且编译一下,编译结果如下

在这里插入图片描述

  • 新建程序文件

新建一个Hardware文件夹,建立一个pwm.c和.h文件,再建立一个key_board.c和.h文件,建立后如下

在这里插入图片描述

2.RTT程序编写

  • 程序源码

创建之后分别写入头文件和.c文件的代码

PWM文件

头文件代码简单理解,不用多说,c语言基本格式

#ifndef PWM_H__
#define PWM_H__
//GPIO模拟PWM的GPIO初始化
void pwm_init(void);
//GPIO模拟PWM的实体
void pwm_entry(void);

#endif

.c文件逻辑如下,我们点亮LED是对IO口进行操作,在RTT里面,IO口的在drv_gpio.c内定义为引脚,我们在drv_gpio.c里面找到对应引脚,在开发板原理图上RGB引脚对应IO口如下:

在这里插入图片描述

PE1—R / PE4—G / PA2—B

找到对应的GPIO口之后,我们创建一个RGB_GPIO_INIT初始化函数,对使用到的三个RGB的GPIO口进行初始化,GPIO初始化的步骤很简单,因为是基于板载工程,创建首先获取板载资源IO口,这里是R、G、B三个口,获取后返回一个GPIO对象,对对象进行操作,配置模式,在之后的读取与写入也是对对象进行操作,初始化GPIO的同时,也创建一个PWM产生线程,初始化代码如下:

//GPIO模拟PWM的GPIO初始化
void pwm_init(void)
{
    
    
    rt_thread_t tid;
    rt_err_t ret = RT_EOK;
    //返回句柄
    R = rt_pin_get(LED_R);
    G = rt_pin_get(LED_G);
    B = rt_pin_get(LED_B);

    /* 设置PIN脚模式为输出 */
    rt_pin_mode(R, PIN_MODE_OUTPUT);
    rt_pin_mode(G, PIN_MODE_OUTPUT);
    rt_pin_mode(B, PIN_MODE_OUTPUT);

    rt_pin_write(R, PIN_HIGH);
    rt_pin_write(G, PIN_HIGH);
    rt_pin_write(B, PIN_HIGH);

    tid = rt_thread_create("pwm_rgb",
                            pwm_entry,
                            RT_NULL,
                            512,
                            10,
                            20);
    if (tid != RT_NULL)
    {
    
    
        //创建线程
        rt_thread_startup(tid);
    }
    else
    {
    
    
        ret = RT_ERROR;
    }
}

GPIO初始化完成后,我们对三个GPIO口编写模拟PWM线程函数(非寄存器比较输出),我先分享一下GPIO模拟PWM的概念,PWM的含义:一般指脉冲宽度调制,实际上就是一个周期方波,其中高电平占据整个周期的比例叫做占空比,我们先设置一个传入当前周期计数数目,用于与整个周期计数长度进行比较,当当前计数周期数目小于我们设定的比较值时,GPIO输出高电平,否则输出低电平,我们单独设置一个线程,线程内部延时10ms,每次执行对一个当前进行计数周期+1,大于最大周期则复位,继续循环,函数主体如下,我们只要改变三个传入的比较值就可以改变PWM,从而形成RGB灯光效果的改变!

PWM线程主体

//GPIO模拟PWM的实体
void pwm_entry(void* p)
{
    
    
    uint8_t count;
    while(1)
    {
    
    
        //设定脉宽200ms
        count++;
        count %=10;
        rt_thread_mdelay(1);
        //模拟pwm比较
        //红色的pwm输出
        if(count>a)
        {
    
    
            rt_pin_write(R, PIN_LOW);
        }
        else {
    
    
            rt_pin_write(R, PIN_HIGH);
        }
        //绿色的PWM输出
        if(count>b)
        {
    
    
            rt_pin_write(G, PIN_LOW);
        }
        else {
    
    
            rt_pin_write(G, PIN_HIGH);
        }
        //蓝色的pwm输出
        if(count>b)
        {
    
    
            rt_pin_write(B, PIN_LOW);
        }
        else
        {
    
    
            rt_pin_write(B, PIN_HIGH);
        }
    }
}

以上两个函数用到的变量的定义

//使用板载资源
#define LED_R "PE.1"
#define LED_G "PE.4"
#define LED_B "PA.2"

uint8_t R,G,B;   //GPIO口句柄
uint8_t a,b,c;    //比较值

key_board.c文件

RGB驱动编写好了,下面我们就是编写按键的驱动,这里RGB彩灯有三个通道,每个通道都需要一个数值增加按键和数值减少按键,蓝讯板子上没有如此多的按键,所以我焊接外扩了六个按键(本来想使用矩阵键盘的,但奈何我的矩阵键盘模块丢了,所以就焊接了6个)原理图接口如下,按键为按下产生上升沿

在这里插入图片描述

实物图如下:

在这里插入图片描述

功能图:

在这里插入图片描述

按键程序的编写有两种方式:第一种是一直死循环扫描读取对应的GPIO电平,当按键按下时程序执行,第二种则是通过外部中断来实现,当按键按下,GPIO口电平变换,GPIO口关联的外部中断触发,在中断函数里面置位按键触发标志,然后主函数内处理程序

两个方法各有优势:方式一简单但消耗CPU运行资源,方式二复杂,但资源占用小,这里我使用的是方式一(简单)

编写key_board_init()函数,用于初始化各个IO口为输入

uint8_t key1,key2,key3,key4,key5,key6;
uint8_t key_pres;
void key_board_init(void)
{
    
    
    key1= rt_pin_get("PF.1");
    key2= rt_pin_get("PA.6");
    key3= rt_pin_get("PA.5");
    key4= rt_pin_get("PF.0");
    key5= rt_pin_get("PA.1");
    key6= rt_pin_get("PA.0");
    // 下拉输入
    rt_pin_mode(key1, PIN_MODE_INPUT_PULLDOWN );
    rt_pin_mode(key2, PIN_MODE_INPUT_PULLDOWN );
    rt_pin_mode(key3, PIN_MODE_INPUT_PULLDOWN );
    rt_pin_mode(key4, PIN_MODE_INPUT_PULLDOWN );
    rt_pin_mode(key5, PIN_MODE_INPUT_PULLDOWN );
    rt_pin_mode(key6, PIN_MODE_INPUT_PULLDOWN );
}

编写key_Scan函数,用于读取返回按键值,这里设置了一个key_pres用于保护,禁止连续按,按一次只生效一次,软件延时消抖

uint8_t key_scan(void)
{
    if(key_pres==0)
    {
        key_pres=1;
        if(rt_pin_read(key1)==1)
        {
            rt_thread_mdelay(30);//消抖
            if(rt_pin_read(key1)==1)
            {
                   return 1;
            }
        }
        if(rt_pin_read(key2)==1)
        {
            rt_thread_mdelay(30);
            if(rt_pin_read(key2)==1)
            {
                   return 2;
            }
        }
        if(rt_pin_read(key3)==1)
        {
            rt_thread_mdelay(30);
            if(rt_pin_read(key3)==1)
            {
                   return 3;
            }
        }
        if(rt_pin_read(key4)==1)
        {
            rt_thread_mdelay(30);
            if(rt_pin_read(key4)==1)
            {
                   return 4;
            }
        }
        if(rt_pin_read(key5)==1)
        {
            rt_thread_mdelay(30);
            if(rt_pin_read(key5)==1)
            {
                   return 5;
            }
        }
        if(rt_pin_read(key6)==1)
        {
            rt_thread_mdelay(30);
            if(rt_pin_read(key6)==1)
            {
                   return 6;
            }
        }
    }else {
        if(rt_pin_read(key1)|rt_pin_read(key2)|rt_pin_read(key3)|rt_pin_read(key4)|rt_pin_read(key5)|rt_pin_read(key6))
        {
            key_pres=0;
        }
    }
    return 0;
}

主线程内对按键结果的处理

int main(void)
{
    
    
    uint8_t key;
    key_board_init();
    pwm_init();
    while(1)
    {
    
    
        key=key_scan();
        if(key==1)
            a++;
        else if(key==2)
            a--;
        else if(key==3)
            b++;
        else if(key==4)
            b--;
        else if(key==5)
            c++;
        else if(key==6)
            c--;

        if(a>9)
            a=9;
        else if(a<1)
            a=1;
        if(b>9)
            b=9;
        else if(b<1)
            b=1;
        if(c>9)
            c=9;
        else if(c<1)
            c=1;
        rt_thread_mdelay(10);
    }
    return 0;
}

3.程序下载,观察现象

代码编写完成,点击小锤子编译,下图编译无报错警告,功能实现

在这里插入图片描述

编译完成,打开Downloaded下载器(打开前需要先安装串口驱动)

在这里插入图片描述

扫描串口,点击开始后,按一下板子上复位按键下载程序

在这里插入图片描述

下载后复位可以看到按键控制输出PWM控制灯光,因为CSDN不允许放外链,电脑端可以到我左边的自定义模块栏目找到我的个人网页源网址对应的文章观看效果!

三、心得

前几天事件比较紧,没有时间花费在板子上研究,这两天才开始研究一下,因为做的GPIO测评,难度也不高,没花多久就完成了,使用的RTT-STUDIO进行开发,开发流程也很简单,没有使用控制台进行调试,有个逻辑设计错了好一会才发现过来,希望以后控制加入在线仿真功能,让调试更加舒服

猜你喜欢

转载自blog.csdn.net/qq_45396672/article/details/115180646