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. 底板上按键的原理图

I.MX6U 裸机开发10.GPIO按键实验_上拉


实体图如下:

I.MX6U 裸机开发10.GPIO按键实验_嵌入式硬件_02

2. 核心板上的引脚

原理图如下所示:

I.MX6U 裸机开发10.GPIO按键实验_#include_03

可以看到KEY0 接到 UART1_CTS 上。
默认情况下,KEY0 为高,当按下KEY0 时, UART1_CTS 拉为低。

3. 开发步骤

  1. 设置 UART1_CTS 复用为 GPIO
  2. 设置 UART1_CTS 的电气属性
  3. 配置 UART1_CTS 为输入模式
  4. 读取 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 寄存器:

I.MX6U 裸机开发10.GPIO按键实验_#include_04


可以看到,UART1_CTS_B复用为 GPIO1_IO18。

代码如下:

// 设置复用
    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);

设置电气属性,从参考手册找到设置电气属性寄存器:

I.MX6U 裸机开发10.GPIO按键实验_上拉_05


逐位分析其功能:

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。