K210开发板学习笔记-点亮LED灯

1. 介绍

和 51 单片机非常像,实验的2个LED灯都是一头接了 +3.3v 电源,控制 LED灯亮的话需要 K210芯片 对应的管脚提供一个低电平。

管脚:

  • 低电平-LED亮
  • 高电平-LED灭

GPIO 连接为:

  • K210-io0  -> LED0 ->+3.3v
  • K210-io17 -> LED1 ->+3.3v

2. 代码

  • pin_config.h
/**
* @par  Copyright (C): 2016-2022, Shenzhen Yahboom Tech
* @file         pin_config.c
* @author       Gengyue
* @version      V1.0
* @date         2020.05.27
* @brief        硬件引脚与软件GPIO的宏定义
* @details      
* @par History  见如下说明
*                 
* version:	由于K210使用fpioa现场可编程IO阵列,允许用户将255个内部功能映射到芯片外围的48个自由IO上
*           所以把硬件IO和软件GPIO功能抽出来单独设置,这样更容易理解。
*/
#ifndef _PIN_CONFIG_H_
#define _PIN_CONFIG_H_
/*****************************HEAR-FILE************************************/
#include "fpioa.h"

/*****************************HARDWARE-PIN*********************************/
// 硬件IO口,与原理图对应
#define PIN_LED_0             (0)
#define PIN_LED_1             (17)

/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define LED0_GPIONUM          (0)
#define LED1_GPIONUM          (1)

/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
//通用gpio共8个,使用同一个中断源,可配置输入输出信号,可配置触发IO口总中断,边沿触发和电平触发。每隔IO可以分配到FPIOA上48个管脚之一
//也就是说,可用的通用 gpio 一共有 8 个, 从 FUNC_GPIO0 可知, 对应功能编号为 FUNC_GPIO0(56) ~ FUNC_GPIO7(63)
//在此处采用了 在 基准 FUNC_GPIO0 基础上 +0、+1 来确定对应的 通用 gpio 编号
#define FUNC_LED0             (FUNC_GPIO0 + LED0_GPIONUM)
#define FUNC_LED1             (FUNC_GPIO0 + LED1_GPIONUM)

#endif /* _PIN_CONFIG_H_ */

  • main.c
/**
* @par  Copyright (C): 2016-2022, Shenzhen Yahboom Tech
* @file         main.c
* @author       Gengyue
* @version      V1.0
* @date         2020.05.27
* @brief        FPIOA映射和GPIO驱动LED灯
* @details      
* @par History  见如下说明
*                 
* version:	V1.0: LED0与LED1交替点亮,时间间隔为1秒。
*/
#include <stdio.h>
#include <unistd.h>
#include "gpio.h"
#include "pin_config.h"

/**
* Function       hardware_init
* @author        Gengyue
* @date          2020.05.27
* @brief         硬件初始化,绑定GPIO口
* @param[in]     void
* @param[out]    void
* @retval        void
* @par History   无
*/
void hardware_init(void)
{
    //绑定 K210芯片实际管脚与其对应的fpioa函数编号
    fpioa_set_function(PIN_LED_0, FUNC_LED0);
    fpioa_set_function(PIN_LED_1, FUNC_LED1);
}

/**
* Function       main
* @author        Gengyue
* @date          2020.05.27
* @brief         主函数,程序的入口
* @param[in]     void
* @param[out]    void
* @retval        0
* @par History   无
*/
int main(void)
{
    hardware_init();// 硬件引脚初始化

    gpio_init();    // 使能GPIO的时钟
    
    // 设置LED0和LED1的GPIO模式为输出
    gpio_set_drive_mode(LED0_GPIONUM, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(LED1_GPIONUM, GPIO_DM_OUTPUT);
    
    // 先关闭LED0和LED1
    gpio_pin_value_t value = GPIO_PV_HIGH;
    gpio_set_pin(LED0_GPIONUM, value);
    gpio_set_pin(LED1_GPIONUM, value);

    while (1)
    {
        sleep(1);
        gpio_set_pin(LED0_GPIONUM, value);
        gpio_set_pin(LED1_GPIONUM, value = !value);
    }
    return 0;
}

通过 main.c 可以看到,总共有如下步骤:

  1. 硬件引脚初始化;
  2. 使能 GPIO 时钟;
  3. 设置LED0和LED1的GPIO模式为输出
  4. 循环控制 LED0 和 LED1 亮灭交替
1. 硬件引脚初始化
void hardware_init(void)
{
    //绑定 K210芯片实际管脚与其对应的fpioa函数编号
    fpioa_set_function(PIN_LED_0, FUNC_LED0);
    fpioa_set_function(PIN_LED_1, FUNC_LED1);
}

PIN_LED_0 是 K210 实际引脚编号,FUNC_LED0 (FUNC_GPIO0 + LED0_GPIONUM)是映射的 fpioa 函数编号
在fpioa_set_function(int number, fpioa_function_t function)中

int fpioa_set_function(int number, fpioa_function_t function)
{
    uint8_t index = 0;
    /* Check parameters */
    // 检查参数
    //1. 0<引脚编号number<FPIOA_NUM_IO(48)
    //2. 0<函数编号<FUNC_MAX(256)
    if(number < 0 || number >= FPIOA_NUM_IO || function < 0 || function >= FUNC_MAX)
        return -1;
    //如果引脚绑定的函数为 保留功能FUNC_RESV0(120),直接设置并返回
    if(function == FUNC_RESV0)
    {
        fpioa_set_function_raw(number, FUNC_RESV0);
        return 0;
    }
    /* Compare all IO */
    //在48个IO FPIOA_NUM_IO 查询
    //如果待绑定的函数 function 已被其他 管脚io占用,设置占用的管脚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);
    }
    //绑定 K210 实际管脚 number 与 内置函数编号 function
    //注意,在点亮LED例程,传入的 function:
    // (FUNC_GPIO0 + LED0_GPIONUM) 和 (FUNC_GPIO0 + LED0_GPIONUM) (56+0, 56+1)
    fpioa_set_function_raw(number, function);
    return 0;
}
2. 设置LED0和LED1的GPIO模式为输出

使能 GPIO 时钟 就是字面意思,不再加以分析

    // 设置LED0和LED1的GPIO模式为输出
    // 传参分别为:
    // LED0_GPIONUM(0), GPIO_DM_OUTPUT(3)
    // LED1_GPIONUM(1), GPIO_DM_OUTPUT(3)
    gpio_set_drive_mode(LED0_GPIONUM, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(LED1_GPIONUM, GPIO_DM_OUTPUT);
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
{
    // 确保 GPIO pin <  GPIO_MAX_PINNO(8,最大通用gpio)
    configASSERT(pin < GPIO_MAX_PINNO);
    //根据功能号获取 IO 管脚号
    //大于等于 0 IO 管脚号
    //小于 0 失败
    int io_number = fpioa_get_io_by_function(FUNC_GPIO0 + pin);
    //确保获取通用管脚号成功
    configASSERT(io_number >= 0);

    fpioa_pull_t pull;
    uint32_t dir;

    switch(mode)
    {
        case GPIO_DM_INPUT:
            pull = FPIOA_PULL_NONE;
            dir = 0;
            break;
        case GPIO_DM_INPUT_PULL_DOWN:
            pull = FPIOA_PULL_DOWN;
            dir = 0;
            break;
        case GPIO_DM_INPUT_PULL_UP:
            pull = FPIOA_PULL_UP;
            dir = 0;
            break;
        case GPIO_DM_OUTPUT:
            pull = FPIOA_PULL_DOWN;
            dir = 1;
            break;
        default:
            configASSERT(!"GPIO drive mode is not supported.") break;
    }
    //设置 IO 的上拉下拉
    fpioa_set_io_pull(io_number, pull);
    set_gpio_bit(gpio->direction.u32, pin, dir);
}

在这个函数中,就可以看出之前明明绑定 k210实际管脚时用的是:

//FUNC_LED0 (FUNC_GPIO0 + LED0_GPIONUM)
fpioa_set_function(PIN_LED_0, FUNC_LED0);

但是设置 GPIO模式为输出 时用的是:

gpio_set_drive_mode(LED0_GPIONUM, GPIO_DM_OUTPUT);

原理就在于 在传入到 gpio_set_drive_mode 函数后,找 函数对应的管脚号用的是:

int io_number = fpioa_get_io_by_function(FUNC_GPIO0 + pin);

其中 pin=LED0_GPIONUM
可能考虑到函数的简洁,函数fpioa_get_io_by_function(uint8_t pin, gpio_drive_mode_t mode)软件GPIO口 LED0_GPIONUMGPIO口的功能 FUNC_LED0的对应关系封装起来了;
结果就导致虽然在 pin_config.h 中定义了

/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define LED0_GPIONUM          (0)
#define LED1_GPIONUM          (1)

/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
//通用gpio共8个,使用同一个中断源,可配置输入输出信号,可配置触发IO口总中断,边沿触发和电平触发。每隔IO可以分配到FPIOA上48个管脚之一
//也就是说,可用的通用 gpio 一共有 8 个, 从 FUNC_GPIO0 可知, 对应功能编号为 FUNC_GPIO0(56) ~ FUNC_GPIO7(63)
//在此处采用了 在 基准 FUNC_GPIO0 基础上 +0、+1 来确定对应的 通用 gpio 编号
#define FUNC_LED0             (FUNC_GPIO0 + LED0_GPIONUM)
#define FUNC_LED1             (FUNC_GPIO0 + LED1_GPIONUM)

但在 main.c 中不知道为什么可以通过 LED0_GPIONUM 设置 FUNC_LED0 绑定的 K210 实际管脚的工作方式

posted @ 2022-07-25 03:17  BrianSun  阅读(978)  评论(0编辑  收藏  举报