目录

一、硬件原理分析

二、寄存器分析

1、时钟源初始化

2、设置 IO 复用

3、初始化 IO 复用引脚(设置电气属性)

4、初始化GPIO

三、汇编代码(start.s)

四、公共头文件(imx6u.h)

四、C 代码编写

1、clk 模块(bsp_clk.c)

2、led 模块(bsp_led.c)

2、delay 模块(bsp_delay.c)

3、key 模块(bsp_key.c)

4、main.c

五、链接脚本(imx6u.lds)

六、Makefile 文件(测试工程的整体结构)


一、硬件原理分析

我们在《imx6ull 底板原理图》中找到按键 KEY 模块。R12 是一个上拉电阻,当按键 KEY0 没有按下时,KEY0 处于高电平;当按键KEY0 按下时,KEY0 接地,此时KEY0 将变为低电平。

接下来我们要去 核心板原理图上找 KEY0 连接的哪个引脚。我们发现是和 UART1_CTS 这个引脚相连。

二、寄存器分析

1、时钟源初始化

这里就不再赘述,可以参考:时钟源初始化

2、设置 IO 复用

按键属于 IO 的范畴,既然和 IO 有关,那我们就要去找第32章的 IOMUX(IO复用选择器)。根据之前的习惯,我们要找和 UART1_CTS 相关的复用寄存器。

IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B 就是我们要找的寄存器了。UART1_CTS 似乎可以复用为很多功能,我们选择的是复用为 GPIO1_IO18 功能。其他位不变,低四位设为 0101。

寄存器: IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B
基地址: 0x20E008C
初始化值: 0x5    # 低四位为0101,其他位不变

注意:

虽然找的是 UART,但不代表是复用为 UART功能,UART 是用于数据传输的;GPIO 只是简单控制某个设备的开关,或者读取某个设备的状态。

3、初始化 IO 复用引脚(设置电气属性)

接下来我们要初始化复用引脚,此时要找前缀为 IOMUXC_SW_PAD_xxx 而且和 UART 相关的寄存器。然后设置每一位。多数都和驱动LED时的设置一样。(初始化 IO 复用)

  • 0:0
  • 2-1:00
  • 5-3:000 (这里要禁用输出,相当于用于输入)
  • 7-6:10
  • 10-8:000
  • 11:0
  • 12:1
  • 13:1(选择 pull 功能)
  • 15-14:11(按键 KEY0 默认是上拉状态)
  • 16:0
  • 31-17:剩余为 0
寄存器: IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_B
基地址: 0x20E0318
初始化值: 0xF080    

4、初始化GPIO

从“设置IO复用”部分我们可以知道,UART_CTS 可被复用为 GPIO1_IO18,因此我们需要去初始化 GPIO1_IO18 引脚,设置的方式和驱动LED使用的方式类似。

寄存器: GPIO1_GDIR
基地址: 0x209C004
初始值: GPIO1_GDIR &= ~(1 << 18)    # 因为是GPIO1的第18个引脚设为输入,即第 18 bit应为0寄存器: GPIO1_DR
基地址: 0x209C000
初始值: - 低电平: GPIO1_DR &= ~(1 << 18)- 高电平: GPIO1_DR |= (1 << 18)

三、汇编代码(start.s)

汇编代码用于搭建C语言环境。关于汇编代码,可以参考之前驱动LED的汇编代码:汇编代码解析

四、公共头文件(imx6u.h)

公共头文件保存了要用到的寄存器的基地址。

#ifndef _IMX6U_H
#define _IMX6U_Htypedef unsigned int uint32_t;/** 时钟相关寄存器地址*/
#define CCM_CCGR0          *((volatile uint32_t*)0x20C4068)
#define CCM_CCGR1          *((volatile uint32_t*)0x20C406C)
#define CCM_CCGR2          *((volatile uint32_t*)0x20C4070)
#define CCM_CCGR3          *((volatile uint32_t*)0x20C4074)
#define CCM_CCGR4          *((volatile uint32_t*)0x20C4078)
#define CCM_CCGR5          *((volatile uint32_t*)0x20C407C)
#define CCM_CCGR6          *((volatile uint32_t*)0x20C4080)/** IOMUX 相关寄存器地址*/
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03   *((volatile uint32_t*)0x020E0068)        // IO复用为 GPIO1_IO03
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03   *((volatile uint32_t*)0x020E02F4)        // 设置复用引脚的电气属性#define IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B *((volatile uint32_t*)0x20E008C)          // IO 复用为 GPIO1_IO18
#define IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_B *((volatile uint32_t*)0x20E0318)          // 设置复用引脚的电气属性/** 设置GPIO输出相关寄存器地址*/
#define GPIO1_DR            *((volatile uint32_t*)0x0209C000)         // GPIO输出
#define GPIO1_GDIR          *((volatile uint32_t*)0x0209C004)         // 设置输入还是输出#endif 

四、C 代码编写

为了验证开关,我们加入之前的 led 代码,之前的 led 代码已经被封装好了,直接调用函数即可。我们的目的是通过开关控制灯的亮灭。

1、clk 模块(bsp_clk.c)

void clk_init()
{CCM_CCGR0 = 0xffffffff;CCM_CCGR1 = 0xffffffff;CCM_CCGR2 = 0xffffffff;CCM_CCGR3 = 0xffffffff;CCM_CCGR4 = 0xffffffff;CCM_CCGR5 = 0xffffffff;CCM_CCGR6 = 0xffffffff;
}

2、led 模块(bsp_led.c)

void led_init()
{/* 1、设置IO复用为GPIO1_IO03 */IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x5;/* 2、初始化复用引脚,设置电气属性 */IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10B0;/* 3、初始化GPIO1 */GPIO1_GDIR |= (1 << 3);
}void led_on()
{GPIO1_DR &= ~(1 << 3);
}void led_off()
{GPIO1_DR |= (1 << 3);
}void switch_led(uint8_t status)
{if (status == ON){led_on();}else{led_off();}
}

2、delay 模块(bsp_delay.c)

void delay_short(volatile unsigned int n)
{while(n--){}
}void delay(volatile unsigned int n)
{while(n--){delay_short(0x7ff);}
}

3、key 模块(bsp_key.c)

void key_init()
{/* 1、设置IO复用为GPIO1_IO03 */IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B = 0x5;/* 2、初始化复用引脚,设置电气属性 */IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_B = 0xF080;/* 3、初始化GPIO1 */GPIO1_GDIR &= ~(1 << 18);
}int read_key()
{int ret = 1;static unsigned char release = 1;       /* 按键松开 */ if ((release==1)&&((GPIO1_DR >> 18) & 0x01) == 0){delay(10);        /* 延时消抖*/release = 0;  /* 标记按键按下 */if (((GPIO1_DR >> 18) & 0x01) == 0){ret = 0;}}else if((GPIO1_DR >> 18) & 0x01 == 1){ret = 1;release = 1;}return ret;
}

4、main.c

int main(void)
{clk_init();     // 初始化时钟led_init();     // 初始化LEDkey_init();     // 初始化按键led_on();       // LED 初始为亮while (1){if (read_key() == 0){led_off(); }delay(1000);led_on();}return 0;
}

五、链接脚本(imx6u.lds)

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 = . ;
}

六、Makefile 文件(测试工程的整体结构)

测试工程的结构如下:

# ################################################################
# # 指定编译器、获取源文件、指定目标文件的生成位置
# ################################################################
# 编译器
TOOLCHAIN_PATH      := /home/pigeon/workspace/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
CC                  := $(TOOLCHAIN_PATH)/arm-linux-gnueabihf-gcc
LD                  := $(TOOLCHAIN_PATH)/arm-linux-gnueabihf-ld
OBJCOPY             := $(TOOLCHAIN_PATH)/arm-linux-gnueabihf-objcopy
OBJDUMP             := $(TOOLCHAIN_PATH)/arm-linux-gnueabihf-objdump# 目标文件名
TARGET_NAME     := key
OBJ_DIR         := obj# 引入头文件
INCLUDES        := -Icommon -Ibsp# 获取到一级子目录下的源文件
DIR1            := project
SOURCES         += $(wildcard ${DIR1}/*.c ${DIR1}/*.s)# 获取到二级子目录下的源文件
DIR2            := bsp
SUBDIRS         = $(shell ls $(DIR2) -l | grep ^d | awk '{print   $$9}')
SOURCES         += $(foreach subdir,${SUBDIRS}, $(wildcard $(DIR2)/${subdir}/*.c))# 创建 $(OBJ_DIR) 目录
$(shell \if test -e $(OBJ_DIR); then \rm -rf $(OBJ_DIR)/*; \else \mkdir -p $(OBJ_DIR); \
fi)# 生成 .o 文件
define compile
OBJ = $(if $(findstring .c,$1), $(patsubst %.c,%.o,$1), $(patsubst %.s,%.o,$1))
NODIR_OBJ = $$(notdir $$(OBJ))
$$(shell $$(CC) -o $$(OBJ_DIR)/$$(NODIR_OBJ) -c $1 $$(INCLUDES))
OBJ_FILE    += $$(OBJ_DIR)/$$(NODIR_OBJ)
endefOBJ_FILE       :=
$(foreach src_file, ${SOURCES}, $(eval $(call compile, $(src_file))))   # 遍历每一个源文件,同时生成对应的 .o 文件# ################################################################
# # 编译生成目标文件、库文件/执行文件
# ################################################################
default:$(LD) -Timx6u.lds -o $(OBJ_DIR)/$(TARGET_NAME).elf $(OBJ_FILE)$(OBJCOPY) -O binary -S -g $(OBJ_DIR)/$(TARGET_NAME).elf $(OBJ_DIR)/$(TARGET_NAME).bin$(OBJDUMP) -D $(OBJ_DIR)/$(TARGET_NAME).elf > $(OBJ_DIR)/$(TARGET_NAME).dis# ################################################################
# # 伪目标/自定义函数
# ################################################################
.PHONY:clean
clean:rm -rf ${OBJ_DIR}/*

【裸机开发】按键输入实验相关推荐

  1. 【正点原子MP157连载】第十二章 按键输入实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  2. ARM(IMX6U)裸机按键输入实验(BSP+SDK、GPIO输入与输出、按键消抖)

    参考:Linux之ARM(IMX6U)裸机按键输入实验(GPIO的输出与输入) 作者:一只青木呀 发布时间: 2020-08-17 21:43:37 网址:https://blog.csdn.net/ ...

  3. 判断按键值_ALIENTEK 阿波罗 STM32F767 开发板资料连载第七章 按键输入实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第七章 按键输入实验 上 ...

  4. 【正点原子STM32连载】 第十五章 按键输入实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

    1)实验平台:正点原子stm32f103战舰开发板V4 2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420 3)全套实验源码+手册+视 ...

  5. stm32 工业按键检测_「正点原子STM32Mini板资料连载」第七章 按键输入实验

    1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第七章 按键输入实验 上一章,我们介 ...

  6. 【STM32学习笔记】(11)——按键输入实验详解

    按键输入实验 实验内容:通过 ALIENTEK 精英 STM32F103 上已有的 3 个按键(KEY_UP.KEY0 和 KEY1),来控制板上的 2 个 LED(DS0 和 DS1)和蜂鸣器,其中 ...

  7. 嵌入式 按键输入实验(修改版)

    按键输入实验 1. 硬件设计: 开发板上有4个按键:key0,key1,key2和wk_up,分别接在PE4,PE3,PE2和PA0上: 2. 软件设计: KEY0. KEY1 和 KEY2 是低电平 ...

  8. 基于STM32F103ZET6库函数按键输入实验

    基于STM32F103ZET6库函数按键输入实验 GPIO_ReadInputDataBit函数 硬件设计 软件设计 我们将通过 ALIENTEK 精英 STM32F103 上载有的 3 个按钮(KE ...

  9. 【吃灰板子捡起来】按键输入实验

    按键输入实验 一.驱动源码 二.应用源码 三.实验总结 一.驱动源码 硬件原理图 #include "nuc972_gpio.h"#include <linux/module ...

  10. Linux按键输入实验(体验一下输入驱动,实际开发使用input子系统处理)

    目录 Linux下按键驱动原理(使用原子操作) 硬件原理图分析 实验程序编写 修改设备树文件 按键驱动程序编写 编写测试APP(循环读取按键值) 运行测试 编译驱动程序和测试APP 运行测试(whil ...

最新文章

  1. 查看 python 的版本 以及 python 的安装位置路径
  2. 关于外部存储器件对存储数据的管理。
  3. VGG模型构建与实现
  4. python摄像头推流_树莓派使用python-librtmp实现rtmp推流h264的方法
  5. 工作总结6:token问题
  6. 【程序猿必备】数据结构与算法精选面试题
  7. 均值(信息学奥赛一本通-T1060)
  8. 【转】系统缓存全解析一
  9. win10无法访问服务器上的共享文件夹怎么设置,提示:你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问...
  10. win10 Abaqus2018 血泪备注
  11. (17)DialogBox和DialogBoxParam函数
  12. 神舟bios更改第一启动项为u盘
  13. 用台达PLC485通信控制11台英威腾变频启动停止速度设定
  14. 关于英伟达显卡驱动程序(GeForce)无法下载的问题
  15. matlab识别中国象棋棋盘,c – 使用OpenCV在棋盘中检测中国象棋棋子
  16. vue中加载maptalks图标(markers)点击事件InfoWindow添加按钮点击事件
  17. 解决svg格式的图片移入PPT中,图片出现viewer does not support svg 1.1问题
  18. 128、函数接口类---Consumer
  19. esxi服务器更换硬盘,ESXi下磁盘分区删除步骤详解
  20. yapi 权限_YAPI安装方法

热门文章

  1. 同花顺_知识_庄家技法_2吸货技法、3缓步推高股价
  2. C++习题--加密通信
  3. DRAM知识整理系列(二):DRAM状态转换图与命令(真值表)相关整理
  4. 云计算技术与应用课后答案第六章
  5. 和ChatGPT关于Swing music的一场对话(下篇)
  6. 将atomthreads应用到stm8s207上
  7. 中国python之父是谁-Python之父退休
  8. 用Python爬取了三大相亲软件评论区,结果…
  9. swoole协程+zephir纯php开发大型RPG微信小游戏(已开源)
  10. python下载视频用youget_python学习:超好用的视频下载组件 you-get