《DNK210使用指南 -SDK版 V1.0》第六章 跑马灯实验

第六章 跑马灯实验


       本章实验将介绍如何使用SDK编程让Kendryte K210控制板载的双色LED闪烁,以实现跑马灯的效果。通过本章的学习,读者将学习到用SDK编程技术控制Kendryte K210的GPIO输出高低电平。

       本章分为如下几个小节:

       6.1 FPIOA介绍

       6.2 GPIO介绍

       6.3 硬件设计

       6.4 程序设计

       6.5 运行验证


        6.1 FPIOA介绍

       FPIOA(Field Programmable Input and Output Array,现场可编程IO阵列)是Kendryte K210芯片内部的模块,FPIOA最主要的功能是允许用户将Kendryte K210芯片内部的255个功能映射到芯片外围的48个自由IO上,因为Kendryte K210芯片内部外设的功能与Kendryte K210引出的外部引脚是彼此独立的,这样的好处是IO引脚可以再不同时刻扮演不同的角色,极大地方便了软硬件的开发,同时它还具有以下功能:

       1. 支持IO的可编程功能选择;

       2. 支持IO输出的8种驱动能⼒选择;

       3. 支持IO的内部上拉电阻选择;

       4. 支持IO的内部下拉电阻选择;

       5. 支持IO输入的内部施密特触发器设置;

       6. 支持IO输出的斜率控制;

       7. 支持内部输入逻辑的电平设置。

       裸机SDK内置了FPIOA 驱动文件fpioa.c和对应的头文件,共有数十个API函数,能够帮助开发者将引脚与具体的硬件功能进行绑定或解绑,以及方便各个管脚的使用和功能配置。

       Kendryte K210一共有48个自由IO,对应的引脚编号为0~47,本章实验只使用到几个普通GPIO口,更详细的硬件功能列表请见表6.1.1。


表6.1.1 Kendryte K210 FPIOA硬件功能表


       我们简单介绍下即将使用的API函数fpioa_set_function(),该函数的功能是将硬件的管脚号与FPIOA的功能号绑定,从而设置引脚的功能,这个和STM32的引脚复用功能有点相似,使用需要传入两个参数,分别是硬件引脚和功能号,方法如下所示:

int fpioa_set_function(int number, fpioa_function_t function)
{
    uint8_t index = 0;
    /* Check parameters */
    if(number < 0 || number >= FPIOA_NUM_IO || function < 0 || function >= FUNC_MAX)
        return -1;
    if(function == FUNC_RESV0)
    {
        fpioa_set_function_raw(number, FUNC_RESV0);
        return 0;
    }
    /* Compare all IO */
    for(index = 0; index < FPIOA_NUM_IO; index++)
    {
        if((fpioa->io[index].ch_sel == function) && (index != number))
            fpioa_set_function_raw(index, FUNC_RESV0);
    }
    fpioa_set_function_raw(number, function);
    return 0;
}

       其他未用到的API函数这里暂时不再介绍,大家如果想对其他API函数进一步了解可以查阅《裸机SDK编程指南》这份文档,第一章节的时候我们也介绍过这份文档的作用,所以大家一定要先保存好这份文档方便我们查阅,在A盘存放路径是:A盘àKendryte K210参考资料àKendryte K210裸机SDK编程指南,接下来讲解GPIO功能。


        6.2 GPIO介绍

       Kendryte K210上有两种GPIO(General-purpose input/output,通用输入/输出),分别为GPIOHS(高速GPIO)和GPIO(通用GPIO)。

       GPIOHS一共有32个,其特点如下所示:

       1. 可配置输入输出信号

       2. 每个IO具有独立的中断源

       3. 中断支持边缘触发和电平触发

       4. 每个IO可以分配到FPIOA上48个管脚之一

       5. 可配置上下拉,或者高阻

       GPIO一共有8个,其特点如下所示:

       1. 可配置输入输出信号

       2. 8个IO使用一个中断源

       3. 可配置触发IO总中断,边沿触发和电平触发

       4. 每个IO可以分配到FPIOA上48个管脚之一

       5. 可配置上下拉,或者高阻态


       6.2.1 Kendryte K210的GPIO简介

       上面提到,Kendryte K210的自由IO有48个,可作为GPIO的管脚情况如下图红框部分所示。


图6.2.1.1 Kendryte K210可做GPIO功能管脚图


       GPIO口输出来的信号是数字信号。数字信号是以0,1表示的不连续信号,也就是以二进制形式表示的信号。在SDK中数字信号用高低电平来表示,高电平为数字信号1,低电平为数字信号0。如下图所示:


图6.2.1.2数字信号


       图中Kendryte K210输出的低电平为0V,输出的高电平为当前Kendryte K210的工作电压,我们K210开发板芯片的供电电压为3.3V,则其高电平为3.3V。


       6.2.2 GPIO函数介绍

       Kendryte K210提供非常多操作GPIO的函数,这里我们只讲述本实验用到的函数,这些函数介绍如下,高速GPIO口这里就不再介绍了,用法都差不多。


       1, gpio_init函数

       该函数是通用GPIO才有的,主要用于时钟使能,如下代码所示:

int gpio_init(void)
{
    return sysctl_clock_enable(SYSCTL_CLOCK_GPIO);
}


       2,gpio_set_drive_mode函数

       该函数用来配置指定管脚的工作模式,包括输入输出模式、上下拉等,如下代码所示:

/* 函数原型 */
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
/**
 * gpio_set_drive_mode功能的mode配置参数
 */
typedef enum _gpio_drive_mode
{
    GPIO_DM_INPUT,
    GPIO_DM_INPUT_PULL_DOWN,
    GPIO_DM_INPUT_PULL_UP,
    GPIO_DM_OUTPUT,
} gpio_drive_mode_t;

       下面我们来讲解一下这几个变量的作用。

       ①:参数pin为引脚软件编号,最大值要小于8。

       ②:参数mode为指定的配置模式,如下表所示:


表6.2.2.1 引脚配置的模式


       该函数无返回值。


       3,gpio_set_pin函数

       该函数用来设置GPIO的电平状态,该函数原型及参数描述如下所示:

void gpio_set_pin(uint8_t pin, gpio_pin_value_t value)
 
 
typedef enum _gpio_pin_value
{
    GPIO_PV_LOW,
    GPIO_PV_HIGH
} gpio_pin_value_t;

       下面我们讲解下这个函数的两个参数,第一个是引脚的软件编号,同上,第二个参数用于设置IO管脚的高低电平状态,GPIO_PV_LOW为指向IO输出低电平, GPIO_PV_HIGH为输出的高电平。该函数无返回值。


       4,gpio_get_pin函数

       该函数用来获取IO的电平状态,该函数原型如下所示:

gpio_pin_value_t gpio_get_pin(uint8_t pin)

       pin用来指向获取那个IO的电平,该函数的返回值就是指定IO的电平状态0或1。


        6.3 硬件设计


       6.3.1 例程功能

       1. 控制板载双色LED轮流闪烁,实现跑马灯的效果


       6.3.2 硬件资源


       1. 双色LED

               LEDR - IO24

              LEDB - IO25


       6.3.3 原理图

       本章实验内容,需要控制板载双色LED轮流闪烁,以实现跑马灯的效果,正点原子DNK210开发板上双色LED的连接原理图,如下图所示:


图6.3.3.1 双色LED连接原理图


       通过以上原理图可以看出,双色LED中红色和蓝色LED对应的IO编号分别为IO24和IO25,且都是当IO输出低电平时LED亮起,当IO输出高电平时LED熄灭。


        6.3 程序设计


       6.3.1 led驱动代码

       这里我们只讲核心部分,LED驱动源码包括两个文件:led.c和led.h(正点原子团队编写的外设驱动基本都是包含一个.c 文件和一个.h 文件,下同),下面我们先介绍led.h文件。

/*****************************HARDWARE-PIN*********************************/
/* 硬件IO口,与原理图对应 */
#define PIN_LED_G             (25)
#define PIN_LED_B             (24)
 
/*****************************SOFTWARE-GPIO********************************/
/* 软件GPIO口,与程序对应 */
#define LEDR_GPIONUM          (0)
#define LEDB_GPIONUM          (1)
 
/*****************************FUNC-GPIO************************************/
/* GPIO口的功能,绑定到硬件IO口 */
#define FUNC_LEDR             (FUNC_GPIO0 + LEDR_GPIONUM)
#define FUNC_LEDB             (FUNC_GPIO0 + LEDB_GPIONUM)

       这部分宏定义了两个led引脚的硬件引脚号、软件编号和功能号,通过这里,我们便可通过函数将引脚功能绑定起来,同时也方便我们修改功能和硬件管脚。

/* IO操作 */
#define LEDR(x)                 do { (x) ?                                     \
                                    gpio_set_pin(LEDR_GPIONUM, GPIO_PV_HIGH):  \
                                    gpio_set_pin(LEDR_GPIONUM, GPIO_PV_LOW);   \
                                } while (0)
#define LEDB(x)                 do { (x) ?                                     \
                                    gpio_set_pin(LEDB_GPIONUM, GPIO_PV_HIGH):  \
                                    gpio_set_pin(LEDB_GPIONUM, GPIO_PV_LOW);   \
                                } while (0)

       LEDR和LEDB的这两个宏定义,分别控制红灯和蓝灯连接的IO引脚的高低电平,进而控制灯的亮灭,通过硬件连接图我们可以,当连接LED灯的引脚为低电平时,LED亮,为高电平时,LED灭。

       当x=1时,对应引脚输出高电平,当x=0时,对应引脚输出低电平,这样我们就非常方便的控制led的亮灭。

       接下来我们看led.c文件。

void led_init(void)
{
    gpio_init();     /* 使能GPIO时钟 */
    
    fpioa_set_function(PIN_LED_R, FUNC_LEDR);
    fpioa_set_function(PIN_LED_B, FUNC_LEDB);
    
    /* 设置LEDR和LEDB的GPIO模式为输出 */
    gpio_set_drive_mode(LEDR_GPIONUM, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(LEDB_GPIONUM, GPIO_DM_OUTPUT);
    
    /* 先关闭LEDR和LEDB */
    gpio_set_pin(LEDR_GPIONUM, GPIO_PV_HIGH);
    gpio_set_pin(LEDB_GPIONUM, GPIO_PV_HIGH);
}

       这个文件只有led_init()这个函数,我们首先是进行GPIO使能,然后通过fpioa的函数将硬件管脚和功能绑定,然后设置GPIO的功能,最后将管脚电平拉高,使两个LED灯处于关闭状态,这部分内容还是比较容易理解。


       6.3.2 main.c代码

       main.c中的代码如下所示:

#include 
#include 
#include "./BSP/LED/led.h"
#include "gpio.h"
#include "fpioa.h"
 
int main(void)
{
    led_init();    /* LED初始化 */
 
    while (1)
    {
        LEDR(1);   /* 红灯灭 */
        LEDB(0);   /* 蓝灯亮 */
        sleep(1);  /* 延时1秒 */
        LEDR(0);   /* 红灯亮 */
        LEDB(1);   /* 蓝灯灭 */
        sleep(1);  /* 延时1秒 */
    }
}

       可以看到,首先通过led_init()为控制双色LED的两个IO分别分配了GPIO0和GPIO1的功能,并配置为输出模式,最后在一个循环中轮流设置LEDR和LEDB输出不同的高低电平并延时一秒时间,从而应该能看到板载的双色LED轮流亮起、熄灭,实现跑马灯的效果。


        6.4 运行验证

       将DNK210开发板连接到电脑主机,通过VSCode将固件烧录到开发板中(方法参考上一章内容,下同),可以看到板载的双色LED轮流亮起、熄灭,实现跑马灯的效果,这与理论推断的结果一致。


请使用浏览器的分享功能分享到微信等