ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

K210应用6-使用定时器timer的不同通道分别控制不同的LED状态

2021-11-15 23:30:00  阅读:185  来源: 互联网

标签:value 定时器 led K210 TIMER timer LED


使用timer定时器控制LED亮灭

  • 实验目的

        本节实验目的为实现定时器的功能应用。这一节计划采取使用定时器中断来实现LED状态反转,实现LED的亮灭循环。计划实现功能为:使用定时器0的两个通道,通道0设置定时1s,通道2设置2s,在通道0中实现红色LED的状态反转,通道2中实现绿色LED的状态反转。

  • 实验准备

        1)、带发光二极管(LED)的K210开发板一块,用于实践并查看实验现象;

        2)、官方裸机编程指导手册:kendryte_standalone_programming_guide,用于查阅SDK中接口说明。

  • 实验原理

        定时器实质上是一个加1计数器,每过一个机器周期,计数器自动加1,当达到我们设定值时,计数器溢出,产生中断,执行中断回调函数。由于每个机器周期的时长是固定的,所以,根据每个机器周期的时长,我们很方便的便能计算出我们想要设定的时间的计数设定值,从实现定时的目的。

  • 硬件设计

        硬件电路图如下:

  • 软件设计

        软件流程图如下:

  • 软件实现

        根据硬件设计和软件设计可知,本节应用实现步骤如下:

        1)、设置引脚复用功能:由硬件原理图可知:我们需要将IO12、IO13设置为GPIOHS功能,如下图:

        2)、LED初始化,如下图:

        3)、timer0初始化,如下图:

        4)、实现timer0通道0和通道1的中断回调函数,在中断回调函数中,实现LED状态信息更新,如下图:

        5)、检测是否更新LED状态,如果更新,进入更新,将LED更新状态设置为不更新,并控制LED状态,如下图:

        根据上述实现步骤,最终代码如下:

#include <fpioa.h>
#include <gpiohs.h>
#include <timer.h>
#include <plic.h>
#include <sysctl.h>
#include <sleep.h>

#define TIMER_1s    (1e9)

#define LED_R_PIN   (12)
#define LED_G_PIN   (13)
#define LED_R_GPIOHSNUM (0)
#define LED_G_GPIOHSNUM (1)
#define LED_R_FUNC  (FUNC_GPIOHS0+LED_R_GPIOHSNUM)
#define LED_G_FUNC  (FUNC_GPIOHS0+LED_G_GPIOHSNUM)

enum LEDNUM {
    LED_R = 0,
    LED_G,
};

struct UNITLED {
    enum LEDNUM led_num;
    gpio_pin_value_t led_value;
    char ledst_updata;
};
struct LEDINFO {
    struct UNITLED led_r;
    struct UNITLED led_g;
};
/*********************************
 * 管脚功能初始化
 ********************************/
void init_hardware(void)
{
    fpioa_set_function(LED_R_PIN, LED_R_FUNC);
    fpioa_set_function(LED_G_PIN, LED_G_FUNC);
}
/*********************************
 * LED初始化
 ********************************/
void init_led()
{
    gpiohs_set_drive_mode(LED_R_GPIOHSNUM, GPIO_DM_OUTPUT);
    gpiohs_set_drive_mode(LED_G_GPIOHSNUM, GPIO_DM_OUTPUT);

    gpiohs_set_pin(LED_R_GPIOHSNUM, GPIO_PV_HIGH);
    gpiohs_set_pin(LED_G_GPIOHSNUM, GPIO_PV_HIGH);
}
/*********************************
 * 控制LED亮灭
 ********************************/
void ctl_led(enum LEDNUM led, gpio_pin_value_t value)
{
    gpiohs_set_pin(led, value);
}

/*********************************
 * 定时器0通道0 中断回调函数
 ********************************/
int irq_timer00_callback_t(void *ctx)
{
    struct UNITLED *led = (struct UNITLED *)ctx;
    led->led_num = LED_R;
    led->led_value = !led->led_value;
    led->ledst_updata = 1;
    return 0;
}
/*********************************
 * 定时器0通道1 中断回调函数
 ********************************/
int irq_timer01_callback_t(void *ctx)
{
    struct UNITLED *led = (struct UNITLED *)ctx;
    led->led_num = LED_G;
    led->led_value = !led->led_value;
    led->ledst_updata = 1;
    return 0;
}
/*********************************
 * 定时器初始化
 ********************************/
void init_timer(struct LEDINFO *ledinfo)
{
    plic_init();
    timer_init(TIMER_DEVICE_0);

    timer_set_interval(TIMER_DEVICE_0, TIMER_CHANNEL_0, TIMER_1s);
    timer_irq_register(TIMER_DEVICE_0, TIMER_CHANNEL_0, 0, 1, irq_timer00_callback_t, &ledinfo->led_r);
    timer_set_enable(TIMER_DEVICE_0, TIMER_CHANNEL_0, 1);

    timer_set_interval(TIMER_DEVICE_0, TIMER_CHANNEL_1, 2*TIMER_1s);
    timer_irq_register(TIMER_DEVICE_0, TIMER_CHANNEL_1, 0, 1, irq_timer01_callback_t, &ledinfo->led_g);
    timer_set_enable(TIMER_DEVICE_0, TIMER_CHANNEL_1, 1);

    sysctl_enable_irq();
}

int main(void)
{
    init_hardware();
    init_led();
    struct LEDINFO led_info = {
        .led_r = {
            .led_num = LED_R,
            .led_value = GPIO_PV_HIGH,
            .ledst_updata = 0,
        },
        .led_g = {
            .led_num = LED_G,
            .led_value = GPIO_PV_HIGH,
            .ledst_updata = 0,
        },
    };
    init_timer(&led_info);

    while(1)
    {
        if(led_info.led_r.ledst_updata == 1)
        {
            led_info.led_r.ledst_updata = 0;
            ctl_led(led_info.led_r.led_num, led_info.led_r.led_value);
        }
        if(led_info.led_g.ledst_updata == 1)
        {
            led_info.led_g.ledst_updata = 0;
            ctl_led(led_info.led_g.led_num, led_info.led_g.led_value);
        }
        usleep(2000);
    }
}

  • 编译

        1)、同上一节类似,在SDK中创建timer文件夹,在新建的文件夹中创建一个main.c文件,然后将本节代码输入到main.c文件中,如下图:

        2)、同上一节的编译方式类似,打开vscode终端,在终端中进入上一节创建的build文件夹,然后输入:cmake ../ -DPROJ=timer -G "MinGW Makefiles" ,生成makefile文件,如下图:

        3)、生成makefile文件后,输入:make ,开始编译,如下图:

        4)、编译完成后,会在build目录下生成烧录文件:timer.bin,如下图:

  • 烧录

        同上一节的烧录方式类似,注意:Firmware那一项选择我们刚编译出的timer.bin文件。

  • 实验现象

        红色LED亮1s,灭1s;同时绿色LED亮2s,灭2s;以此循环。

  • 实验总结

        1)、K210总有三个定时器,每个定时器有四个通道,每个通道都拥有独立中断,用户可根据需求自由选择;

        2)、K210定时器可使用timer_set_enable函数来开启和关闭定时器,初始化完成之后,开启和关闭定时器不需要重新配置。

标签:value,定时器,led,K210,TIMER,timer,LED
来源: https://blog.csdn.net/w723291206/article/details/121346069

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有