I.MX6U 裸机开发10.GPIO按键实验
- 一、原理图
- 1. 底板上按键的原理图
- 2. 核心板上的引脚
- 3. 开发步骤
- 二、程序编写
- 1. 创建工程文件夹
- 2. key文件
- key.h
- key.c
- key_init 函数设置引脚的复用、电气属性,首先在 fsl_iomuxc.h 里找到 UART1_CTS 寄存器:
- 0: SRE
- 2-1: 未使用
- 5-3:DSE
- 7-6:SPEED:设置速度,值如下:
- 10-8:未使用
- 11:ODE
- 12:PKE
- 13: PUE
- 15-14:PUS
- 16:HYS
- 31-17: 未使用
- key_get_value
- 3. main文件
- 三、链接文件四字节对齐
一、原理图
本项目实现轮询KEY0的状态值,并根据按键状态控制LED0和BEEP。
1. 底板上按键的原理图
实体图如下:
2. 核心板上的引脚
原理图如下所示:
可以看到KEY0 接到 UART1_CTS 上。
默认情况下,KEY0 为高,当按下KEY0 时, UART1_CTS 拉为低。
3. 开发步骤
- 设置 UART1_CTS 复用为 GPIO
- 设置 UART1_CTS 的电气属性
- 配置 UART1_CTS 为输入模式
- 读取 UART1_CTS 的值,即按键值
二、程序编写
1. 创建工程文件夹
从上章直接复制项目,将 Makefile 里的项目名称改成 key 。
在apps下新增 key.c和 key.h 文件。
2. key文件
key.h
//
// Created by Xundh on 2024/11/15.
//
#ifndef LEARN_I_MX6U_KEY_H
#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "MCIMX6Y2.h"
#define KEY0 0
#define KEY1 1
void key_init(void);
int key_get_value(int key);
#define LEARN_I_MX6U_KEY_H
#endif //LEARN_I_MX6U_KEY_H
key.c
key_init 函数设置引脚的复用、电气属性,首先在 fsl_iomuxc.h 里找到 UART1_CTS 寄存器:
可以看到,UART1_CTS_B复用为 GPIO1_IO18。
代码如下:
// 设置复用
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
设置电气属性,从参考手册找到设置电气属性寄存器:
逐位分析其功能:
0: SRE
用于设置引脚的转换速率,与GPIO输入功能无关,置0;
2-1: 未使用
5-3:DSE
设置引脚的驱动强度,输出使用,置0;
7-6:SPEED:设置速度,值如下:
- 00 SPEED_0_low_50MHz_ — 低速(50MHz)
- 01 SPEED_1_medium_100MHz_ — 中速(100MHz)
- 10 SPEED_2_medium_100MHz_ — 中速(100MHz)
- 11 SPEED_3_max_200MHz_ — 最高速(200MHz)
这里设置为100M,值0b10。
10-8:未使用
11:ODE
- 0: ODE_0_Open_Drain_Disabled:开漏禁用
- 1: ODE_1_Open_Drain_Enabled:开漏启用
这里使用0 开漏禁用。
12:PKE
Pull / Keep Enable Field(拉/保持使能字段)用于设置引脚的拉/保持功能。
- 0 PKE_0_Pull_Keeper_Disabled — 拉/保持禁用
- 1 PKE_1_Pull_Keeper_Enabled — 拉/保持启用
这里使用1,启用上拉。
13: PUE
Pull / Keep Select Field(拉/保持选择字段)用于设置引脚的拉/保持功能。
0 PUE_0_Keeper — 保持
1 PUE_1_Pull — 拉
这里使用值1,设置上拉。
15-14:PUS
Pull Up / Down Config. Field(上拉/下拉配置字段)用于设置引脚的上拉或下拉电阻。
- 00 PUS_0_100K_Ohm_Pull_Down — 100K 欧姆下拉
- 01 PUS_1_47K_Ohm_Pull_Up — 47K 欧姆上拉
- 10 PUS_2_100K_Ohm_Pull_Up — 100K 欧姆上拉
- 11 PUS_3_22K_Ohm_Pull_Up — 22K 欧姆上拉
这里设置 11, 22K上拉。
16:HYS
Hyst. Enable Field(迟滞使能字段)用于设置引脚的迟滞功能。
- 0 HYS_0_Hysteresis_Disabled — 迟滞禁用
- 1 HYS_1_Hysteresis_Enabled — 迟滞启用
这里设置为0。
31-17: 未使用
最终设置值为 0xF080:
// 设置电气属性
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);
key_get_value
/**
* @brief 获取按键值,加消抖
* @param key 按键编号
* @return 按键值
*/
int key_get_value(int key)
{
int ret = 0;
switch(key)
{
case KEY0:
if((GPIO1->DR & (1 << 18)) == 0)
{
delay(10);
if((GPIO1->DR & (1 << 18)) == 0)
ret = 0;
}
else
ret = 1;
break;
case KEY1:
break;
}
return ret;
}
3. main文件
#include "inc/main.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "led.h"
#include "beep.h"
#include "key.h"
int main(void)
{
clk_enable(); /* 使能外设时钟 */
led_init(); /* 初始化LED */
beep_init(); /* 初始化蜂鸣器 */
while(1) {
int key_val = key_get_value(KEY0);
if(key_val == 0) {
led_switch(LED0, LED_ON);
beep_switch(BEEP_ON);
} else {
led_switch(LED0, LED_OFF);
beep_switch(BEEP_OFF);
}
}
return 0;
}
烧录程序,本程序效果是按下 KEY0, LED0会亮并发出BEEP声音。
由于本项目使用的轮询方式会阻塞程序运行,后面的章节会改用中断重新实现按键读取功能。
三、链接文件四字节对齐
正点原子的官方视频里,出现了段地址对齐问题。不过我的测试没有发生这种情况。
据教程描述,问题现象是编译后烧录的程序无法正常工作,检查 beep.dis,发现 _bss_start 段的地址不是四字节 对齐的。
修正方式是,修改 链接脚本文件,
SECTIONS{
. = 0x87800000;
.text :
{
obj/start.o
*(.text)
}
.rodata ALIGN(4) : {*(.rodata*)}
.data ALIGN(4) : {*(.data)}
. = ALIGN(4); # 这里是添加的一行
__bss_start = . ;
.bss ALIGN(4) : {*(.bss) *(COMMON)}
__bss_end=.;
}
添加的行是 . = ALIGN(4);
, 这句的意思是在这里加定位计数器,. 是四字节对齐的,再把点赋值给__bss_start。