课主要验证 K210 的定时器功能
K210 芯片定时器总共有 3 个,每个定时器有 4 路通道。每个定时器可以设置触发间隔,和定时器中断处理函数。
K210开发板出厂默认已经焊接好BOOT按键和RGB灯。按键连接的引脚为IO16。RGB 灯 R 连接的是 IO6,G 连接的是 IO7, B 连接的是 IO8。
以头文件 timer.h为例,以下接口:
• timer_init:初始化定时器。
• timer_set_interval:设置定时间隔。
• timer_set_irq (0.6.0 后不再支持,请使用 timer_irq_register)
• timer_set_enable:使能/禁止定时器。
• timer_irq_register:注册定时器中断回调函数。
• timer_irq_deregister:注销定时器中断。
定时器的核心其实是加1 计数器,对机器周期进行计数,每过一个机器周期,计数器自动加 1,直到计数器计满溢出。由于计数的周期是固定的,所以根据计数的多少就可以很方便的计算出计数的时间,当符合自己设定的超时时间,则调用中断回调函数,然后重新开始计数。
#ifndef _PIN_CONFIG_H_
#define _PIN_CONFIG_H_
/*****************************HEAR-FILE************************************/
#include "fpioa.h"
/*****************************HARDWARE-PIN*********************************/
// 硬件IO口,与原理图对应
#define PIN_RGB_R (6)
#define PIN_RGB_G (7)
#define PIN_RGB_B (8)
#define PIN_KEY (16)
/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define RGB_R_GPIONUM (0)
#define RGB_G_GPIONUM (1)
#define RGB_B_GPIONUM (2)
#define KEY_GPIONUM (3)
/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_RGB_R (FUNC_GPIOHS0 + RGB_R_GPIONUM)
#define FUNC_RGB_G (FUNC_GPIOHS0 + RGB_G_GPIONUM)
#define FUNC_RGB_B (FUNC_GPIOHS0 + RGB_B_GPIONUM)
#define FUNC_KEY (FUNC_GPIOHS0 + KEY_GPIONUM)
void hardware_init(void)
{
/* fpioa映射 */
fpioa_set_function(PIN_RGB_R, FUNC_RGB_R);
fpioa_set_function(PIN_RGB_G, FUNC_RGB_G);
fpioa_set_function(PIN_RGB_B, FUNC_RGB_B);
fpioa_set_function(PIN_KEY, FUNC_KEY);
}
plic_init();
sysctl_enable_irq();
void init_rgb(void)
{
/* 设置RGB灯的GPIO模式为输出 */
gpiohs_set_drive_mode(RGB_R_GPIONUM, GPIO_DM_OUTPUT);
gpiohs_set_drive_mode(RGB_G_GPIONUM, GPIO_DM_OUTPUT);
gpiohs_set_drive_mode(RGB_B_GPIONUM, GPIO_DM_OUTPUT);
/* 关闭RGB灯 */
rgb_all_off();
}
void rgb_all_off(void)
{
gpiohs_set_pin(RGB_R_GPIONUM, GPIO_PV_HIGH);
gpiohs_set_pin(RGB_G_GPIONUM, GPIO_PV_HIGH);
gpiohs_set_pin(RGB_B_GPIONUM, GPIO_PV_HIGH);
}
void init_key(void)
{
// 设置按键的GPIO模式为上拉输入
gpiohs_set_drive_mode(KEY_GPIONUM, GPIO_DM_INPUT_PULL_UP);
// 设置按键的GPIO电平触发模式为上升沿和下降沿
gpiohs_set_pin_edge(KEY_GPIONUM, GPIO_PE_BOTH);
// 设置按键GPIO口的中断回调
gpiohs_irq_register(KEY_GPIONUM, 1, key_irq_cb, NULL);
}
int key_irq_cb(void* ctx)
{
gpio_pin_value_t key_state = gpiohs_get_pin(KEY_GPIONUM);
if (key_state)
timer_set_enable(TIMER_DEVICE_0, TIMER_CHANNEL_0, 1);
else
timer_set_enable(TIMER_DEVICE_0, TIMER_CHANNEL_0, 0);
return 0;
}
void init_timer(void) {
/* 定时器初始化 */
timer_init(TIMER_DEVICE_0);
/* 设置定时器超时时间,单位为ns */
timer_set_interval(TIMER_DEVICE_0, TIMER_CHANNEL_0, 500 * 1e6);
/* 设置定时器中断回调 */
timer_irq_register(TIMER_DEVICE_0, TIMER_CHANNEL_0, 0, 1, timer_timeout_cb, &g_count);
/* 使能定时器 */
timer_set_enable(TIMER_DEVICE_0, TIMER_CHANNEL_0, 1);
}
int timer_timeout_cb(void *ctx) {
uint32_t *tmp = (uint32_t *)(ctx);
(*tmp)++;
if ((*tmp)%2)
{
rgb_all_on();
}
else
{
rgb_all_off();
}
return 0;
}
void rgb_all_on(void)
{
gpiohs_set_pin(RGB_R_GPIONUM, GPIO_PV_LOW);
gpiohs_set_pin(RGB_G_GPIONUM, GPIO_PV_LOW);
gpiohs_set_pin(RGB_B_GPIONUM, GPIO_PV_LOW);
}
int main(void)
{
/* 硬件引脚初始化 */
hardware_init();
/* 初始化系统中断并使能 */
plic_init();
sysctl_enable_irq();
/* 初始化RGB灯 */
init_rgb();
/* 初始化按键key */
init_key();
/* 初始化定时器 */
init_timer();
while (1);
return 0;
}
cmake .. -DPROJ=watchdog -G "MinGW Makefiles"
make
烧录完成固件后,系统会弹出一个终端界面,如果没有弹出终端界面的可以打开串口助手显示调试内容。
RGB 灯亮白色,每 0.5 秒后熄灭再亮白色,一直循环,当按住 BOOT 键时,定时器停止,RGB 灯保存当前的状态,不再切换状态,当松开 BOOT 键时,定时器恢复启动,RGB 灯又开始每 0.5 秒切换状态。