合泰单片机 | HT66F3195 | 个人库开发过程 | 【5】GPIO - 基础属性配置

翻车更新说明 - 20220618

妈的🙄那个GPIO_Toggle的写法之前是比较规矩的,但是不知道后来为什么抽风换成了异或的写法。昨天测其他东西的时候发现怎么没有生效,找了一圈才发现是写错了。

_pb6 ^= _pb6这种展开不就相当于是_pb6 = _pb6 ^ _pb6自己异或自己结果就一定是0,改回去了,换成_pb ^= 0x40

GPIO

属性配置主要有以下几种:

  • 输入输出模式
  • 输出电平高低
  • 上拉电阻
  • 功能复用
  • 电流大小

操作,目前用得比较多的:

  • IO翻转

需要注意一点的是,PA组的引脚有8个,PB和PC组的引脚只有7个,PD组的引脚只有4个。

程序配置

GPIO.h

#ifndef	_GPIO_H_
#define	_GPIO_H_


#define	GPIO_Map_Group			0x01
#define	GPIO_Map_Pin			0x02


typedef enum
{
	GPIOA = 0x01,
	GPIOB = 0x02,
	GPIOC = 0x04,
	GPIOD = 0x08,

}GPIO_Group_T;


typedef enum
{
	Pin0 = 0x01,
	Pin1 = 0x02,
	Pin2 = 0x04,
	Pin3 = 0x08,
	Pin4 = 0x10,
	Pin5 = 0x20,
	Pin6 = 0x40,
	Pin7 = 0x80,

}GPIO_Pin_T;


/*------- GPIO - 读取电平状态 -------*/
#define	GPIOA_Get_Status()			_pa
#define	GPIOB_Get_Status()			_pb
#define	GPIOC_Get_Status()			_pc
#define	GPIOD_Get_Status()			_pd
/* -------------------------------- */


/*------- GPIO - 设置电平状态 -------*/
#define	GPIOA_Set_Status			_pa
#define	GPIOB_Set_Status			_pb
#define	GPIOC_Set_Status			_pc
#define	GPIOD_Set_Status			_pd
/* -------------------------------- */


/*------- GPIO - 设置输入输出 -------*/
#define	GPIOA_Set_Control			_pac
#define	GPIOB_Set_Control			_pbc
#define	GPIOC_Set_Control			_pcc
#define	GPIOD_Set_Control			_pdc
/* -------------------------------- */


/*--------- GPIO - 电平翻转 ---------*/
#define	GPIOA_Toggle()				_pa = ~_pa
#define	GPIOA_0_Toggle()			_pa ^= 0x01
#define	GPIOA_1_Toggle()			_pa ^= 0x02
#define	GPIOA_2_Toggle()			_pa ^= 0x04
#define	GPIOA_3_Toggle()			_pa ^= 0x08
#define	GPIOA_4_Toggle()			_pa ^= 0x10
#define	GPIOA_5_Toggle()			_pa ^= 0x20
#define	GPIOA_6_Toggle()			_pa ^= 0x40
#define	GPIOA_7_Toggle()			_pa ^= 0x80

#define	GPIOB_Toggle()				_pb = ~_pb
#define	GPIOB_0_Toggle()			_pb ^= 0x01
#define	GPIOB_1_Toggle()			_pb ^= 0x02
#define	GPIOB_2_Toggle()			_pb ^= 0x04
#define	GPIOB_3_Toggle()			_pb ^= 0x08
#define	GPIOB_4_Toggle()			_pb ^= 0x10
#define	GPIOB_5_Toggle()			_pb ^= 0x20
#define	GPIOB_6_Toggle()			_pb ^= 0x40

#define	GPIOC_Toggle()				_pc = ~_pc
#define	GPIOC_0_Toggle()			_pc ^= 0x01
#define	GPIOC_1_Toggle()			_pc ^= 0x02
#define	GPIOC_2_Toggle()			_pc ^= 0x04
#define	GPIOC_3_Toggle()			_pc ^= 0x08
#define	GPIOC_4_Toggle()			_pc ^= 0x10
#define	GPIOC_5_Toggle()			_pc ^= 0x20
#define	GPIOC_6_Toggle()			_pc ^= 0x40

#define	GPIOD_Toggle()				_pd = ~_pd
#define	GPIOD_0_Toggle()			_pd ^= 0x01
#define	GPIOD_1_Toggle()			_pd ^= 0x02
#define	GPIOD_2_Toggle()			_pd ^= 0x04
#define	GPIOD_3_Toggle()			_pd ^= 0x08
/* --------------------------------- */


/*------ GPIO - 电平输出高低 ------*/
#define	GPIOA_Status(x)				_pa = x
#define	GPIOA_0_Status(x)			_pa0 = x
#define	GPIOA_1_Status(x)			_pa1 = x
#define	GPIOA_2_Status(x)			_pa2 = x
#define	GPIOA_3_Status(x)			_pa3 = x
#define	GPIOA_4_Status(x)			_pa4 = x
#define	GPIOA_5_Status(x)			_pa5 = x
#define	GPIOA_6_Status(x)			_pa6 = x
#define	GPIOA_7_Status(x)			_pa7 = x

#define	GPIOB_Status(x)				_pb = x
#define	GPIOB_0_Status(x)			_pb0 = x
#define	GPIOB_1_Status(x)			_pb1 = x
#define	GPIOB_2_Status(x)			_pb2 = x
#define	GPIOB_3_Status(x)			_pb3 = x
#define	GPIOB_4_Status(x)			_pb4 = x
#define	GPIOB_5_Status(x)			_pb5 = x
#define	GPIOB_6_Status(x)			_pb6 = x

#define	GPIOC_Status(x)				_pc = x
#define	GPIOC_0_Status(x)			_pc0 = x
#define	GPIOC_1_Status(x)			_pc1 = x
#define	GPIOC_2_Status(x)			_pc2 = x
#define	GPIOC_3_Status(x)			_pc3 = x
#define	GPIOC_4_Status(x)			_pc4 = x
#define	GPIOC_5_Status(x)			_pc5 = x
#define	GPIOC_6_Status(x)			_pc6 = x

#define	GPIOD_Status(x)				_pd = x
#define	GPIOD_0_Status(x)			_pd0 = x
#define	GPIOD_1_Status(x)			_pd1 = x
#define	GPIOD_2_Status(x)			_pd2 = x
#define	GPIOD_3_Status(x)			_pd3 = x

typedef enum 
{
	IO_Low = 0,
	IO_High = 1,
	IO_Error = 0xFF,

}GPIO_Status_T;
/* ------------------------------- */


/*--------- GPIO - 输入输出状态 ---------*/
#define	GPIOA_Control(x)			_pac = x
#define	GPIOA_0_Control(x)			_pac0 = x
#define	GPIOA_1_Control(x)			_pac1 = x
#define	GPIOA_2_Control(x)			_pac2 = x
#define	GPIOA_3_Control(x)			_pac3 = x
#define	GPIOA_4_Control(x)			_pac4 = x
#define	GPIOA_5_Control(x)			_pac5 = x
#define	GPIOA_6_Control(x)			_pac6 = x
#define	GPIOA_7_Control(x)			_pac7 = x

#define	GPIOB_Control(x)			_pbc = x
#define	GPIOB_0_Control(x)			_pbc0 = x
#define	GPIOB_1_Control(x)			_pbc1 = x
#define	GPIOB_2_Control(x)			_pbc2 = x
#define	GPIOB_3_Control(x)			_pbc3 = x
#define	GPIOB_4_Control(x)			_pbc4 = x
#define	GPIOB_5_Control(x)			_pbc5 = x
#define	GPIOB_6_Control(x)			_pbc6 = x

#define	GPIOC_Control(x)			_pcc = x
#define	GPIOC_0_Control(x)			_pcc0 = x
#define	GPIOC_1_Control(x)			_pcc1 = x
#define	GPIOC_2_Control(x)			_pcc2 = x
#define	GPIOC_3_Control(x)			_pcc3 = x
#define	GPIOC_4_Control(x)			_pcc4 = x
#define	GPIOC_5_Control(x)			_pcc5 = x
#define	GPIOC_6_Control(x)			_pcc6 = x

#define	GPIOD_Control(x)			_pdc = x
#define	GPIOD_0_Control(x)			_pdc0 = x
#define	GPIOD_1_Control(x)			_pdc1 = x
#define	GPIOD_2_Control(x)			_pdc2 = x
#define	GPIOD_3_Control(x)			_pdc3 = x

typedef enum
{
	IO_Output = 0,
	IO_Input = 1,
}GPIO_Control_T;
/* ------------------------------------ */


/*---------- GPIO - 上拉电阻 ----------*/
#define	GPIOA_Pullup(x)				_papu = x
#define	GPIOA_0_Pullup(x)			_papu0 = x
#define	GPIOA_1_Pullup(x)			_papu1 = x
#define	GPIOA_2_Pullup(x)			_papu2 = x
#define	GPIOA_3_Pullup(x)			_papu3 = x
#define	GPIOA_4_Pullup(x)			_papu4 = x
#define	GPIOA_5_Pullup(x)			_papu5 = x
#define	GPIOA_6_Pullup(x)			_papu6 = x
#define	GPIOA_7_Pullup(x)			_papu7 = x

#define	GPIOB_Pullup(x)				_pbpu = x
#define	GPIOB_0_Pullup(x)			_pbpu0 = x
#define	GPIOB_1_Pullup(x)			_pbpu1 = x
#define	GPIOB_2_Pullup(x)			_pbpu2 = x
#define	GPIOB_3_Pullup(x)			_pbpu3 = x
#define	GPIOB_4_Pullup(x)			_pbpu4 = x
#define	GPIOB_5_Pullup(x)			_pbpu5 = x
#define	GPIOB_6_Pullup(x)			_pbpu6 = x

#define	GPIOC_Pullup(x)				_pcpu = x
#define	GPIOC_0_Pullup(x)			_pcpu0 = x
#define	GPIOC_1_Pullup(x)			_pcpu1 = x
#define	GPIOC_2_Pullup(x)			_pcpu2 = x
#define	GPIOC_3_Pullup(x)			_pcpu3 = x
#define	GPIOC_4_Pullup(x)			_pcpu4 = x
#define	GPIOC_5_Pullup(x)			_pcpu5 = x
#define	GPIOC_6_Pullup(x)			_pcpu6 = x

#define	GPIOD_Pullup(x)				_pdpu = x
#define	GPIOD_0_Pullup(x)			_pdpu0 = x
#define	GPIOD_1_Pullup(x)			_pdpu1 = x
#define	GPIOD_2_Pullup(x)			_pdpu2 = x
#define	GPIOD_3_Pullup(x)			_pdpu3 = x

/* -------------------------------- */


/*---------------------------- GPIO - 引脚电流 ----------------------------*/
#define	GPIOA_0_3_Current(x)		_sledc0 = (_sledc0&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOA_4_7_Current(x)		_sledc0 = (_sledc0&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOB_0_3_Current(x)		_sledc0 = (_sledc0&(~(REG_2_BIT<<4)))|(x<<4)
#define	GPIOB_4_6_Current(x)		_sledc0 = (_sledc0&(~(REG_2_BIT<<6)))|(x<<6)
#define	GPIOC_0_3_Current(x)		_sledc1 = (_sledc1&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOC_4_6_Current(x)		_sledc1 = (_sledc1&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOD_0_3_Current(x)		_sledc1 = (_sledc1&(~(REG_2_BIT<<4)))|(x<<4)

typedef enum
{
	IO_Current_Level1 = 0,
	IO_Current_Level2,
	IO_Current_Level3,
	IO_Current_Level4,
}GPIO_Current_T;
/* ------------------------------------------------------------------------- */


/*------------------------- GPIO - 功能复用------------------------- */
#define	GPIOA_0_Mode(x)		_pas0 = (_pas0&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOA_1_Mode(x)		_pas0 = (_pas0&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOA_2_Mode(x)		_pas0 = (_pas0&(~(REG_2_BIT<<4)))|(x<<4)
#define	GPIOA_3_Mode(x)		_pas0 = (_pas0&(~(REG_2_BIT<<6)))|(x<<6)
#define	GPIOA_4_Mode(x)		_pas1 = (_pas1&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOA_5_Mode(x)		_pas1 = (_pas1&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOA_6_Mode(x)		_pas1 = (_pas1&(~(REG_2_BIT<<4)))|(x<<4)
#define	GPIOA_7_Mode(x)		_pas1 = (_pas1&(~(REG_2_BIT<<6)))|(x<<6)

#define	GPIOB_0_Mode(x)		_pbs0 = (_pbs0&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOB_1_Mode(x)		_pbs0 = (_pbs0&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOB_2_Mode(x)		_pbs0 = (_pbs0&(~(REG_2_BIT<<4)))|(x<<4)
#define	GPIOB_3_Mode(x)		_pbs0 = (_pbs0&(~(REG_2_BIT<<6)))|(x<<6)
#define	GPIOB_4_Mode(x)		_pbs1 = (_pbs1&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOB_5_Mode(x)		_pbs1 = (_pbs1&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOB_6_Mode(x)		_pbs1 = (_pbs1&(~(REG_2_BIT<<4)))|(x<<4)

#define	GPIOC_0_Mode(x)		_pcs0 = (_pcs0&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOC_1_Mode(x)		_pcs0 = (_pcs0&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOC_2_Mode(x)		_pcs0 = (_pcs0&(~(REG_2_BIT<<4)))|(x<<4)
#define	GPIOC_3_Mode(x)		_pcs0 = (_pcs0&(~(REG_2_BIT<<6)))|(x<<6)
#define	GPIOC_4_Mode(x)		_pcs1 = (_pcs1&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOC_5_Mode(x)		_pcs1 = (_pcs1&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOC_6_Mode(x)		_pcs1 = (_pcs1&(~(REG_2_BIT<<4)))|(x<<4)

#define	GPIOD_0_Mode(x)		_pds0 = (_pds0&(~(REG_2_BIT<<0)))|(x<<0)
#define	GPIOD_1_Mode(x)		_pds0 = (_pds0&(~(REG_2_BIT<<2)))|(x<<2)
#define	GPIOD_2_Mode(x)		_pds0 = (_pds0&(~(REG_2_BIT<<4)))|(x<<4)
#define	GPIOD_3_Mode(x)		_pds0 = (_pds0&(~(REG_2_BIT<<6)))|(x<<6)

typedef enum
{
	IO_Mode1 = 0,
	IO_Mode2,
	IO_Mode3,
	IO_Mode4,
}GPIO_Mode_T;
/* ------------------------------------------------------------------- */


/*----------- GPIOA - 唤醒功能 ----------- */
#define	GPIOA_Wakeup(x)			_pawu = x
#define	GPIOA_0_Wakeup(x)		_pawu0 = x
#define	GPIOA_1_Wakeup(x)		_pawu1 = x
#define	GPIOA_2_Wakeup(x)		_pawu2 = x
#define	GPIOA_3_Wakeup(x)		_pawu3 = x
#define	GPIOA_4_Wakeup(x)		_pawu4 = x
#define	GPIOA_5_Wakeup(x)		_pawu5 = x
#define	GPIOA_6_Wakeup(x)		_pawu6 = x
#define	GPIOA_7_Wakeup(x)		_pawu7 = x

/* -------------------------------------- */


unsigned char GPIO_Map_Parameter_Check(GPIO_Group_T gpio, GPIO_Pin_T pin);
GPIO_Status_T GPIO_Map_Read(GPIO_Group_T gpio, GPIO_Pin_T pin);
void GPIO_Map_Write(GPIO_Group_T gpio, GPIO_Pin_T pin, GPIO_Status_T io_status);
void GPIO_Map_Control(GPIO_Group_T gpio, GPIO_Pin_T pin, GPIO_Control_T io_status);


#endif

GPIO的这个文件已经重新写过几遍了,但是至今我感觉都没有写好,不知道怎么形容,很难做到可以应付各种开发状况,兼顾代码可读性以及代码运行效率,目前的想法是,如果不能同时兼顾的话,其实可以在同一个文件中用两种写法,如果是对时间效率不高的话,可以采用写法A,配置GPIO各种属性的时候像STM32库那样,有各种参数检查,如果是对时间效率比较高的话比如短时间内要多次翻转IO这种,采用写法B,等同于直接操作寄存器那种,不过是被我多封装了一层宏。

多个GPIO映射关系

如果只是IO口普通应用的话,引用头文件已经可以完成大部分开发工作了。
下面这些代码是我某天突然想到的一种方法,不适合频繁调用,因为只是一些简单的操作要经历各种分支,时间上并不是很划算。
光是从代码上看其实有点抽象,要结合实际案例去理解就一下子能看明白。先把代码贴出来。

传入参数检查,之前也说过了,PB和PC只有7个,PD只有4个引脚,如果输入的参数类似PB7,PC7以及PD4~PD7都是不允许的。

unsigned char GPIO_Map_Parameter_Check(GPIO_Group_T gpio, GPIO_Pin_T pin)
{
	if((gpio == GPIOB)||(gpio == GPIOC))
    {
        if(pin & 0x80)
            return Parameter_Abnormal;
    }
    else if(gpio == GPIOD)
    {
        if(pin & 0xF0)
            return Parameter_Abnormal;
    }
    return Parameter_Normal;
}

多个GPIO状态读取。

GPIO_Status_T GPIO_Map_Read(GPIO_Group_T gpio, GPIO_Pin_T pin)
{
    GPIO_Status_T io_status;

    if(GPIO_Map_Parameter_Check(gpio, pin) == Parameter_Abnormal)
    	return (IO_Error);

    switch(gpio)
    {
        case GPIOA:     io_status = !!(GPIOA_Get_Status() & pin);   break;
        case GPIOB:     io_status = !!(GPIOB_Get_Status() & pin);   break;
        case GPIOC:     io_status = !!(GPIOC_Get_Status() & pin);   break;
        case GPIOD:     io_status = !!(GPIOD_Get_Status() & pin);   break;
        default:        io_status = (IO_Error);                 break;
    }
    return io_status;
}

多个GPIO输出电平配置。

void GPIO_Map_Write(GPIO_Group_T gpio, GPIO_Pin_T pin, GPIO_Status_T io_status)
{
	if(GPIO_Map_Parameter_Check(gpio, pin) == Parameter_Abnormal)
    	return ;

    if(io_status == IO_High)
    {
        switch(gpio)
        {
            case GPIOA:     GPIOA_Set_Status |= pin;        	break;
            case GPIOB:     GPIOB_Set_Status |= pin;        	break;
            case GPIOC:     GPIOC_Set_Status |= pin;        	break;
            case GPIOD:     GPIOD_Set_Status |= pin;        	break;
            default:                         		    		break;
        }
    }
    else if(io_status == IO_Low)
    {
        switch(gpio)
        {
            case GPIOA:     GPIOA_Set_Status &= (~pin);      	break;
            case GPIOB:     GPIOB_Set_Status &= (~pin);      	break;
            case GPIOC:     GPIOC_Set_Status &= (~pin);      	break;
            case GPIOD:     GPIOD_Set_Status &= (~pin);      	break;
            default:                             				break;
        }
    }
    return ;
}

多个GPIO输出输入模式配置。

void GPIO_Map_Control(GPIO_Group_T gpio, GPIO_Pin_T pin, GPIO_Control_T io_status)
{
	if(GPIO_Map_Parameter_Check(gpio, pin) == Parameter_Abnormal)
    	return ;

    if(io_status == IO_Input)
    {
        switch(gpio)
        {
            case GPIOA:     GPIOA_Set_Control |= pin;          	break;
            case GPIOB:     GPIOB_Set_Control |= pin;          	break;
            case GPIOC:     GPIOC_Set_Control |= pin;          	break;
            case GPIOD:     GPIOD_Set_Control |= pin;          	break;
            default:                             			 	break;
        }
    }
    else if(io_status == IO_Output)
    {
        switch(gpio)
        {
            case GPIOA:     GPIOA_Set_Control &= (~pin);    	break;
            case GPIOB:     GPIOB_Set_Control &= (~pin);    	break;
            case GPIOC:     GPIOC_Set_Control &= (~pin);    	break;
            case GPIOD:     GPIOD_Set_Control &= (~pin);    	break;
            default:                              				break;
        }
    }
    return ;
}

因为剩余的GPIO属性也不会经常配置,用头文件另一套写法也可以满足需求,就先这样子写了,后续看看有无特殊的需求或者更好的写法再进行更改。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值