《嵌入式硬件(十):基于IMX6ULL的按键操作》
本文介绍了嵌入式开发中GPIO模块的代码复用实现方法。首先通过gpio.c和gpio.h文件封装了GPIO初始化、读写等基础操作函数,提高了代码复用性。然后展示了LED和蜂鸣器模块如何调用这些通用函数实现具体功能。接着详细说明了按键检测原理与实现步骤,包括硬件连接、电气属性设置和输入方向配置。最后给出了完整的项目代码结构,包括主程序main.c和启动文件start.S,实现了按键控制LED和蜂鸣器
·
一、提高代码复用性
顶层与底层硬件区分开
gpio.c
#include "gpio.h"
//传递参数为初始化的GIPIO的组,引脚号,状态
void init_gpio(GPIO_Type *base, int pin, struct GPIO_Type_t *gpio)
{
if(gpio->direction == gpio_output)
{
base->GDIR |= (1 << pin);
if(gpio->defalut_value)
{
base->DR |= (1 << pin);
}
else
{
base->DR &= ~(1 << pin);
}
}
else
{
base->GDIR &= ~(1 << pin);
}
}
void write_gpio(GPIO_Type *base, int pin, int value)
{
if(value)
{
base->DR |= (1 << pin);
}
else
{
base->DR &= ~(1 << pin);
}
}
int read_gpio(GPIO_Type *base, int pin)
{
return (base->DR & (1 << pin)) != 0;//返回1高电平,0低电平
}
gpio.h
#ifndef _GPIO_H_
#define _GPIO_H_
#include "MCIMX6Y2.h"
enum GPIO_Diection
{
gpio_output,
gpio_input
};
struct GPIO_Type_t
{
enum GPIO_Diection direction;
int defalut_value;
};
extern void init_gpio(GPIO_Type *base, int pin, struct GPIO_Type_t *gpio);
extern void write_gpio(GPIO_Type *base, int pin, int value);
extern int read_gpio(GPIO_Type *base, int pin);
#endif
根据上面的函数,那么我们的代码:led.c,beep.c就可以修改
led.c
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "led.h"
#include "gpio.h"
void enable_clocks(void)
{
CCM->CCGR0 = 0xffffffff;
CCM->CCGR1 = 0xffffffff;
CCM->CCGR2 = 0xffffffff;
CCM->CCGR3 = 0xffffffff;
CCM->CCGR4 = 0xffffffff;
CCM->CCGR5 = 0xffffffff;
CCM->CCGR6 = 0xffffffff;
}
void init_led(void)
{
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0x10b0);
//GPIO1 -> GDIR |= (1 << 3);
struct GPIO_Type_t t =
{
.direction = gpio_output,
.defalut_value = 1,
};
init_gpio(GPIO1, 3, &t);
}
void led_on(void)
{
//GPIO1 -> DR &= ~(1 << 3);
write_gpio(GPIO1, 3, 0);
}
void led_off(void)
{
//GPIO1 -> DR |= (1 << 3);
write_gpio(GPIO1, 3, 1);
}
void led_nor(void)
{
//GPIO1 -> DR ^= (1 << 3);
write_gpio(GPIO1, 3, !read_gpio(GPIO1, 3)) ;
}
void delay(unsigned int n)
{
while(n--);
}
beep.c
#include "beep.h"
#include "fsl_iomuxc.h"
#include "MCIMX6Y2.h"
#include "gpio.h"
void init_beep(void)//1500
{
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0);
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0x10b0);
//GPIO5 -> GDIR |= (1 << 1);
struct GPIO_Type_t t =
{
.direction = gpio_output,
.defalut_value = 1,
};
init_gpio(GPIO5, 1, &t);
}
void beep_on(void)
{
//GPIO5 -> DR &= ~(1 << 1);
write_gpio(GPIO5, 1, 0);
}
void beep_off(void)
{
//GPIO5 -> DR |= (1 << 1);
write_gpio(GPIO5, 1, 1);
}
void beep_nor(void)
{
//GPIO5 -> DR ^= (1 << 1);
write_gpio(GPIO5, 1, !read_gpio(GPIO5, 1)) ;
}
二、按键原理
1.底板原理图

key0按下低电平,不按高电平

2.功能复用

3.电气属性


加一个22k的上拉电阻,值为0xF0B0
4.输入输出方向

5.数据寄存器

三、步骤
1)初始化时钟
2)设置引脚功能复用(GPIO)
3)引脚电气属性(功率、电阻)
4)设置外设引脚的输入输出方向
5)设置数据寄存器拉低/拉高电平
四、代码
结构与之前一样
1.bsp
1)key.c
#include "key.h"
#include "fsl_iomuxc.h"
#include "gpio.h"
#include "core_ca7.h"
void init_key(void)
{
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);
struct GPIO_Type_t t =
{
.direction = gpio_input
};
init_gpio(GPIO1, 18, &t);
}
int key_pressed(void)
{
if(read_gpio(GPIO1, 18) == 0)
{
return 1;
}
else
{
return 0;
}
}
2)key.h
#ifndef _KEY_H_
#define _KEY_H_
#include "fsl_iomuxc.h"
#include "gpio.h"
extern void init_key(void);
extern int key_pressed(void);
#endif
3)led.c---beep.c
2.project
1)main.c
#include "led.h"
#include "beep.h"
#include "MCIMX6Y2.h"
#include "key.h"
#include "core_ca7.h"
void enable_clocks(void)
{
CCM->CCGR0 = 0xFFFFFFFF;
CCM->CCGR1 = 0xFFFFFFFF;
CCM->CCGR2 = 0xFFFFFFFF;
CCM->CCGR3 = 0xFFFFFFFF;
CCM->CCGR4 = 0xFFFFFFFF;
CCM->CCGR5 = 0xFFFFFFFF;
CCM->CCGR6 = 0xFFFFFFFF;
}
void delay(unsigned int n)
{
while(n--);
}
int main(void)
{
enable_clocks();
init_led();
init_beep();
init_key();
while(1)
{
if(key_pressed())
{
led_on();
beep_on();
}
}
return 0;
}
2)start.S
.global _start
_start:
ldr pc, =_reset_handler
ldr pc, =_undefine_handler
ldr pc, =_svc_handler
ldr pc, =_prefetch_abort_handler
ldr pc, =_data_abort_handler
ldr pc, =_reserved_handler
ldr pc, =_irq_handler
ldr pc, =_fiq_handler
_undefine_handler:
ldr pc, =_undefine_handler
_svc_handler:
ldr pc, =_svc_handler
_prefetch_abort_handler:
ldr pc, =_prefetch_abort_handler
_data_abort_handler:
ldr pc, =_data_abort_handler
_reserved_handler:
ldr pc, =_reserved_handler
_irq_handler:
ldr pc, =_irq_handler
_fiq_handler:
ldr pc, =_fiq_handler
_reset_handler:
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x12 //irq
msr cpsr, r0
ldr sp, =0x80600000
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x1F //system
msr cpsr, r0
ldr sp, =0x80400000
bl _bss_clear
b main
_bss_clear:
ldr r0, =__bss_start
ldr r2, =__bss_end
loop:
mov r1, #0
str r1, [r0]
add r0, r0, #4
cmp r0, r2
blt loop
bx lr
finished:
b finished
更多推荐


所有评论(0)