K210开发板(四)—按键独立中断

  1. 一.实验准备
    1. 1.外部中断
    2. 2.按键原理
    3. 3.函数介绍
      1. 4.1 gpiohs_set_pin_edge
      2. 4.2 gpiohs_irq_register
  2. 二.实验步骤
    1. 1.配置
      1. 1.1 引脚
      2. 1.2 函数
    2. 2.初始化
    3. 3.主体
  3. 三.实验总结

简介:
  本篇博客用于记录K210的学习和自己遇到的问题,主要内容为按键独立中断,按键未按下时播放音乐,按键按下时暂停播放。由于参考资料的教程比较齐全,本文会着重于讲述自己遇到的问题和解决方案


参考资料:http://www.yahboom.com/study/K210-Developer-Kit
提取码:moj1

一.实验准备

1.外部中断

  普通的按键的实验,虽然能实现 IO 口输入输出功能,但代码是一直在检测 IO 输入口的变化,因此效率不高,特别是在一些特定的场合,比如某个按键,可能 1 天才按下一次去执行相关功能,这样我们就浪费大量时间来实时检测按键的情况。为了解决这样的问题,我们引入外部中断概念,顾名思义,就是当按键被按下(产生中断)时,我们才去执行相关功能。这大大节省了 CPU 的资源,因此中断的在实际项目的应用非常普遍。

2.按键原理

  BOOT 按键按下的时候会把电平拉低,松开的时候会把电平拉高,只需要检测 BOOT 按键的 IO 口的电平,如果是按下则会产生下降沿,松开会产生上升沿,以 此的方式来检测并触发系统的中断

3.函数介绍

4.1 gpiohs_set_pin_edge

  设置GPIO中断触发模式

参数成员 描述 输入输出
pin GPIO管脚 输入
edge 中断触发方式 输入

4.2 gpiohs_irq_register

  设置GPIO中断回调函数

参数成员 描述 输入输出
pin GPIO管脚 输入
priority 中断优先级 输入
plic_irq_callback_t 中断回调函数 输入
*ctx 回调函数的形参 输入

二.实验步骤

1.配置

1.1 引脚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//定义硬件引脚(见原理图)
#define PIN_SPK_WS (30)
#define PIN_SPK_DATA (31)
#define PIN_SPK_BCK (32)

#define PIN_KEY (16)
//定义软件GPIO口
#define KEY_GPIONUM (3)
//将硬件引脚映射到软件GPIO功能
#define FUNC_SPK_WS FUNC_I2S2_WS
#define FUNC_SPK_DATA FUNC_I2S2_OUT_D0
#define FUNC_SPK_BCK FUNC_I2S2_SCLK

#define FUNC_KEY (FUNC_GPIOHS0 + KEY_GPIONUM)

void hardware_init(void){
fpioa_set_function(PIN_SPK_WS, FUNC_SPK_WS);
fpioa_set_function(PIN_SPK_DATA, FUNC_SPK_DATA);
fpioa_set_function(PIN_SPK_BCK, FUNC_SPK_BCK);

fpioa_set_function(PIN_KEY, FUNC_KEY);
}

1.2 函数

1
2
3
4
5
6
7
8
int key_irq_cb(void* ctx){
gpio_pin_value_t key_state = gpiohs_get_pin(KEY_GPIONUM);
//这里只是为了测试才在中断回调打印数据,正常情况下是不建议这么做的
printf("IRQ The PIN is %d\n", key_state);
uint32_t *tmp = (uint32_t *)(ctx);
printf("count is %d\n", (*tmp)++);
return 0;
}

2.初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 硬件引脚初始化
hardware_init();
//外部中断初始化
plic_init();
///使能全局中断
sysctl_enable_irq();
//设置系统时钟
sysctl_pll_set_freq(SYSCTL_PLL0, 320000000UL);
sysctl_pll_set_freq(SYSCTL_PLL1, 160000000UL);
sysctl_pll_set_freq(SYSCTL_PLL2, 45158400UL);
uarths_init();
//初始化I2S
i2s_init(I2S_DEVICE_2, I2S_TRANSMITTER, 0x03);
i2s_tx_channel_config(
I2S_DEVICE_2, // I2S设备号
I2S_CHANNEL_0, // I2S通道
RESOLUTION_16_BIT, // 接收数据位数
SCLK_CYCLES_32, // 单个数据时钟数
TRIGGER_LEVEL_4, // DMA触发时FIFO深度
RIGHT_JUSTIFYING_MODE); // 工作模式
// 初始化按键key
//设置按键的GPIO模式为上拉输入
gpiohs_set_drive_mode(KEY_GPIONUM,GPIO_DM_INPUT_PULL_UP);
//设置按键的GPIO电平触发模式为下降沿触发
gpiohs_set_pin_edge(KEY_GPIONUM,GPIO_PE_RISING);
//设置按键GPIO口的中断回调
gpiohs_irq_register(KEY_GPIONUM,1,key_irq_cb,&g_count);

3.主体

1
2
3
4
5
6
7
8
9
10
11
12
gpio_pin_value_t key_state = gpiohs_get_pin(KEY_GPIONUM);
//检测按键是否未被按下
if(key_state==1){
i2s_play(
I2S_DEVICE_2, // I2S设备号
DMAC_CHANNEL0, // DMA通道号
(uint8_t *)test_pcm, // 播放的PCM数据
sizeof(test_pcm), // PCM数据的长度
1024, // 单次发送数量
16, // 单次采样位宽
2); // 声道数
}

三.实验总结

遇到问题:音乐暂停没有实现真正意义上的暂停,松开按键只会重新播放
解决方案:未解决,需要了解如何暂停I2S的传输然后恢复


结语:
  无



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 21009200039@stu.xidian.edu.cn

💰

×

Help us with donation