开发板是GD32E103R-START,2020-6 V1.0
以下是非中断处理,代码比较简陋
#include "gd32e10x.h
int main(void)
{
volatile static uint8_t a = 0, b = 0, c = 0, d = 0;
systick_config();
rcu_periph_clock_enable(RCU_GPIOC);
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_6);
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_0);
while(1){
if (gpio_input_bit_get(GPIOA, GPIO_PIN_0)){
delay_1ms(20);
if (gpio_input_bit_get(GPIOA, GPIO_PIN_0)){
while (gpio_input_bit_get(GPIOA, GPIO_PIN_0) && c < 100){
c++;
delay_1ms(10);
}
}
}
if (c >= 100){
a = 0;
b = 0;
c = 0;
d = 0;
gpio_bit_write(GPIOC, GPIO_PIN_6, 1);
}
else{
c = 0;
if (a == 1){
gpio_bit_write(GPIOC, GPIO_PIN_6, 1);
delay_1ms(500);
gpio_bit_write(GPIOC, GPIO_PIN_6, 0);
delay_1ms(500);
}
if ((a == 1) && (b == 0) && (!(gpio_input_bit_get(GPIOA, GPIO_PIN_0))) && (d == 0)){
delay_1ms(20);
if (!gpio_input_bit_get(GPIOA, GPIO_PIN_0)){
d = 1;
}
}
if ((d == 1) && gpio_input_bit_get(GPIOA, GPIO_PIN_0)){
delay_1ms(20);
if (gpio_input_bit_get(GPIOA, GPIO_PIN_0)){
a = 0;
b = 0;
d = 2;
}
}
if ((d == 2) && (a == 0) && (b == 0)){
gpio_bit_write(GPIOC, GPIO_PIN_6, 1);
delay_1ms(100);
gpio_bit_write(GPIOC, GPIO_PIN_6, 0);
delay_1ms(100);
}
if ((a == 0) && (b == 0) && gpio_input_bit_get(GPIOA, GPIO_PIN_0)){
d = 0;
delay_1ms(20);
if (gpio_input_bit_get(GPIOA, GPIO_PIN_0)){
a = 1;
}
}
}
}
}
以下中断处理
#include "gd32e10x.h"
#include "key_led.h"
int main(void)
{
systick_config();
key_init();
rcu_periph_clock_enable(RCU_GPIOC);
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_6);
while(1){
if (key_sta.double_flag[0]){
gpio_bit_write(GPIOC, GPIO_PIN_6, 1);
delay_1ms(100);
gpio_bit_write(GPIOC, GPIO_PIN_6, 0);
delay_1ms(100);
}
else if (key_sta.short_flag[0]){
gpio_bit_write(GPIOC, GPIO_PIN_6, 1);
delay_1ms(500);
gpio_bit_write(GPIOC, GPIO_PIN_6, 0);
delay_1ms(500);
}
else if (key_sta.long_flag[0]){
gpio_bit_write(GPIOC, GPIO_PIN_6, 0);
}
}
}
// 按键状态定义
#define KEY_PRESSED (1U)
#define KEY_UNPRESSED (0U)
#define SHORT_TIME (40U)
#define LONG_TIME (100U)
#define DOUBLE_TIME (2U)
#define INTERVAL_MAX (40U)
#define INTERVAL_MIN (1U)
#define SINGLE_CLICKED (2U)
#define DOUBLE_CLICKED (3U)
// 按键数量
#define KEY_PORT_NUM (1U)
// 按键数据结构
#pragma pack(1)
struct ld_key{
uint8_t key_status[KEY_PORT_NUM];
uint8_t short_flag[KEY_PORT_NUM];
uint8_t long_flag[KEY_PORT_NUM];
uint8_t double_flag[KEY_PORT_NUM];
};
#pragma pack()
extern volatile struct ld_key key_sta;
#include "key_led.h"
#include "gd32e10x.h"
volatile struct ld_key key_sta = {0};
// 按键扫描间隔10ms
static void init_scan_timer(void)
{
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER3);
nvic_irq_enable(TIMER3_IRQn, 1, 1);
timer_deinit(TIMER3);
timer_struct_para_init(&timer_initpara);
timer_initpara.prescaler = 1199;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER3, &timer_initpara);
timer_auto_reload_shadow_enable(TIMER3);
timer_interrupt_flag_clear(TIMER3, TIMER_INT_FLAG_UP);
timer_interrupt_enable(TIMER3, TIMER_INT_UP);
timer_enable(TIMER3);
}
void key_init(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_0);
nvic_irq_enable(EXTI0_IRQn, 1, 1);
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_0);
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_RISING); // 这里需要根据原理图确定是上升沿还是下降沿触发
exti_interrupt_flag_clear(EXTI_0);
init_scan_timer();
}
以下是gd32e10x_it.c
#include "gd32e10x_it.h"
#include "systick.h"
#include "key_led.h"
// 10ms一次扫描
void TIMER3_IRQHandler(void)
{
static uint8_t key_holdon_ms[KEY_PORT_NUM] = {0};
static uint8_t double_interval_ms = 0;
static uint8_t which_press = 0;
static uint8_t double_flag = 0;
if (timer_interrupt_flag_get(TIMER3, TIMER_INT_FLAG_UP) != RESET){
gpio_input_bit_get(GPIOA, GPIO_PIN_0) ? (key_holdon_ms[0]++) : (0);
if ((key_holdon_ms[0] >= DOUBLE_TIME) && (key_holdon_ms[0] < SHORT_TIME)){
double_flag = SET;
}
else if ((key_holdon_ms[0] >= SHORT_TIME) && (key_holdon_ms[0] < LONG_TIME)){
which_press = SINGLE_CLICKED;
}
else if ((key_holdon_ms[0] >= LONG_TIME)){
which_press = RESET;
key_sta.long_flag[0] = SET;
key_sta.short_flag[0] = RESET;
key_sta.double_flag[0] = RESET;
}
else {}
(double_flag && (!gpio_input_bit_get(GPIOA, GPIO_PIN_0))) ? (double_interval_ms++) : (0);
if ((double_interval_ms > INTERVAL_MIN) && (double_interval_ms < INTERVAL_MAX) && (double_flag == SET)) {
which_press = DOUBLE_CLICKED;
double_flag = RESET;
double_interval_ms = RESET;
}
if (double_interval_ms > INTERVAL_MAX) {
which_press = RESET;
double_flag = RESET;
double_interval_ms = RESET;
}
if (!gpio_input_bit_get(GPIOA, GPIO_PIN_0) && key_sta.key_status[0] == KEY_PRESSED){
switch (which_press){
case SINGLE_CLICKED:
key_sta.short_flag[0] = SET;
key_sta.double_flag[0] = RESET;
key_sta.long_flag[0] = RESET;
break;
case DOUBLE_CLICKED:
key_sta.double_flag[0] = SET;
key_sta.short_flag[0] = RESET;
key_sta.long_flag[0] = RESET;
break;
default:
break;
}
key_sta.key_status[0] = KEY_UNPRESSED;
key_holdon_ms[0] = RESET;
which_press = RESET;
}
timer_interrupt_flag_clear(TIMER3, TIMER_INT_FLAG_UP);
}
}
void EXTI0_IRQHandler(void)
{
if (RESET != exti_interrupt_flag_get(EXTI_0)){
key_sta.key_status[0] = KEY_PRESSED;
exti_interrupt_flag_clear(EXTI_0);
}
}