智能车学习(十四)——K60单片机GPIO学习
一、头文件:
#ifndef __MK60_GPIO_H__ #define __MK60_GPIO_H__ #include "MK60_gpio_cfg.h" /* * 定义管脚方向 */ typedef enum GPIO_CFG { //这里的值不能改!!! GPI = 0, //定义管脚输入方向 GPIOx_PDDRn里,0表示输入,1表示输出 GPO = 1, //定义管脚输出方向 } GPIO_CFG; #define HIGH 1u #define LOW 0u extern GPIO_MemMapPtr GPIOX[PTX_MAX]; #define GPIOX_BASE(PTxn) GPIOX[PTX(PTxn)] //GPIO模块的地址 /****************************外部使用****************************/ extern void gpio_init (PTXn_e, GPIO_CFG, uint8 data); //初始化gpio extern void gpio_ddr (PTXn_e, GPIO_CFG); //设置引脚数据方向 extern void gpio_set (PTXn_e, uint8 data); //设置引脚状态 extern void gpio_turn (PTXn_e); //反转引脚状态 extern uint8 gpio_get (PTXn_e); //读取引脚状态 //如下 4个 函数 的 PTxn 只能是 宏定义,不能是 变量 #define GPIO_SET(PTxn,data) (PTXn_T(PTxn,OUT)= (data)) //设置输出电平 #define GPIO_TURN(PTxn) (PTXn_T(PTxn,T)= 1) //翻转输出电平 #define GPIO_GET(PTxn) (PTXn_T(PTxn,IN)) //读取引脚输入状态 #define GPIO_DDR(PTxn,ddr) (PTXn_T(PTxn,DDR) = ddr) //输入输出状态 //如下 函数 的 PTxn 可以是 宏定义,也可以是 变量 //n位操作 #define GPIO_SET_NBIT(NBIT,PTxn,data) GPIO_PDOR_REG(GPIOX_BASE(PTxn)) = ( \ ( \ GPIO_PDOR_REG(GPIOX_BASE(PTxn)) \ & \ ((uint32)( ~(((1<<NBIT)-1)<<PTn(PTxn)))) \ ) \ | ((data) \ &( \ ((1<<NBIT)-1) \ <<PTn(PTxn) \ )) \ ) #define GPIO_DDR_NBIT(NBIT,PTxn,ddr) GPIO_PDDR_REG(GPIOX_BASE(PTxn)) = ( \ ( \ GPIO_PDDR_REG(GPIOX_BASE(PTxn)) \ & \ ((uint32)( ~(((1<<NBIT)-1)<<PTn(PTxn)))) \ ) \ | ((ddr) \ &( \ ((1<<NBIT)-1) \ <<PTn(PTxn) \ )) \ ) #define GPIO_T_NBIT(NBIT,PTxn,data) GPIO_PTOR_REG(GPIOX_BASE(PTxn)) = ( \ ( \ GPIO_PTOR_REG(GPIOX_BASE(PTxn)) \ & \ ((uint32)( ~(((1<<NBIT)-1)<<PTn(PTxn)))) \ ) \ | ((data) \ &( \ ((1<<NBIT)-1) \ <<PTn(PTxn) \ )) \ ) #define GPIO_GET_NBIT(NBIT,PTxn) (( GPIO_PDIR_REG(GPIOX_BASE(PTxn))>>PTn(PTxn) ) & ((1<<NBIT)-1)) #endif //__MK60_GPIO_H__
二、源文件:
/* * 包含头文件 */ #include "common.h" #include "MK60_port.h" #include "MK60_gpio.h" /* * 定义数组 */ GPIO_MemMapPtr GPIOX[PTX_MAX] = {PTA_BASE_PTR, PTB_BASE_PTR, PTC_BASE_PTR, PTD_BASE_PTR, PTE_BASE_PTR}; //定义五个指针数组保存 GPIOX 的地址 /*! * @brief 初始化gpio * @param PTxn 端口 * @param cfg 引脚方向,0=输入,1=输出 * @param data 输出初始状态,0=低电平,1=高电平 (对输入无效) * @since v5.0 * Sample usage: gpio_init (PTA8, GPI,0); //初始化 PTA8 管脚为输入 */ void gpio_init (PTXn_e ptxn, GPIO_CFG cfg, uint8 data) { //复用管脚为GPIO功能 port_init( ptxn, ALT1); //端口方向控制输入还是输出 if( cfg == GPI ) { //设置端口方向为输入 GPIO_PDDR_REG(GPIOX_BASE(ptxn)) &= ~(1 << PTn(ptxn)); // GPIO PDDR 管脚号 清0,即对应管脚配置为端口方向输入 } else { //设置端口方向为输出 GPIO_PDDR_REG(GPIOX_BASE(ptxn)) |= (1 << PTn(ptxn)); // GPIO PDDR 管脚号 置1,即对应管脚配置为端口方向输出 //端口输出数据 if(data == 0) { GPIO_PDOR_REG(GPIOX_BASE(ptxn)) &= ~(1 << PTn(ptxn)); // GPIO PDOR 管脚号 清0,即对应管脚配置为端口输出低电平 } else { GPIO_PDOR_REG(GPIOX_BASE(ptxn)) |= (1 << PTn(ptxn)); // GPIO PDOR 管脚号 置1,即对应管脚配置为端口输出高电平 } } } /*! * @brief 设置引脚数据方向 * @param PTxn 端口 * @param cfg 引脚方向,0=输入,1=输出 * @since v5.0 * Sample usage: gpio_ddr (PTA8, GPI); //设置 PTA8 管脚为输入 */ void gpio_ddr (PTXn_e ptxn, GPIO_CFG cfg) { //端口方向控制输入还是输出 if( cfg == GPI ) { //设置端口方向为输入 GPIO_PDDR_REG(GPIOX_BASE(ptxn)) &= ~(1 << PTn(ptxn)); // GPIO PDDR 管脚号 清0,即对应管脚配置为端口方向输入 } else { //设置端口方向为输出 GPIO_PDDR_REG(GPIOX_BASE(ptxn)) |= (1 << PTn(ptxn)); // GPIO PDDR 管脚号 置1,即对应管脚配置为端口方向输出 } } /*! * @brief 设置引脚状态 * @param PTxn 端口 * @param data 输出初始状态,0=低电平,1=高电平 (对输入无效) * @since v5.0 * @warning 务必保证数据方向为输出(DEBUG模式下,有断言进行检测) * Sample usage: gpio_set (PTA8, 1); // PTA8 管脚 输出 1 */ void gpio_set (PTXn_e ptxn, uint8 data) { ASSERT( BIT_GET( GPIO_PDDR_REG(GPIOX_BASE(ptxn)) , PTn(ptxn)) == GPO ); // 断言,检测 输出方向是否为输出 // 获取 GPIO PDDR 管脚号 ,比较是否为输出 //端口输出数据 if(data == 0) { GPIO_PDOR_REG(GPIOX_BASE(ptxn)) &= ~(1 << PTn(ptxn)); // GPIO PDOR 管脚号 清0,即对应管脚配置为端口输出低电平 } else { GPIO_PDOR_REG(GPIOX_BASE(ptxn)) |= (1 << PTn(ptxn)); // GPIO PDOR 管脚号 置1,即对应管脚配置为端口输出高电平 } } /*! * @brief 反转引脚状态 * @param PTxn 端口 * @since v5.0 * @warning 务必保证数据方向为输出(DEBUG模式下,有断言进行检测) * Sample usage: gpio_turn (PTA8); // PTA8 管脚 输出 反转 */ void gpio_turn (PTXn_e ptxn) { ASSERT( BIT_GET( GPIO_PDDR_REG(GPIOX_BASE(ptxn)) , PTn(ptxn)) == GPO ); // 断言,检测 输出方向是否为输出 // 获取 GPIO PDDR 管脚号 ,比较是否为输出 GPIO_PTOR_REG( GPIOX_BASE(ptxn)) = 1 << (PTn(ptxn )); // GPIO PTOR ptxn 置1,其他清0 ,即对应管脚配置为端口输出反转,其他位不变 // 此处不能用 BIT_SET 这个宏来置1 ,因为必须保证其他位 不变,其他位直接清0即可 } /*! * @brief 读取引脚输入状态 * @param PTxn 端口 * @return 管脚的状态,1为高电平,0为低电平 * @since v5.0 * @warning 务必保证数据方向为输入(DEBUG模式下,有断言进行检测) * Sample usage: uint8 pta8_data = gpio_get (PTA8); // 获取 PTA8 管脚 输入电平 */ uint8 gpio_get(PTXn_e ptxn) { ASSERT( BIT_GET( GPIO_PDDR_REG(GPIOX_BASE(ptxn)) , PTn(ptxn)) == GPI ); // 断言,检测 输出方向是否为输入 // 获取 GPIO PDDR 管脚号 ,比较是否为输入 return ((GPIO_PDIR_REG(GPIOX_BASE(ptxn)) >> PTn(ptxn )) & 0x01); // 获取 GPIO PDIR ptxn 状态,即读取管脚输入电平 }
三、小结:
主要是学会怎么调用,出现问题的话,检查寄存器的配置(不过一般不需要)。
本文作者:Blue Mountain
本文链接:https://www.cnblogs.com/BlueMountain-HaggenDazs/p/4993121.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步