翻车更新说明 - 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属性也不会经常配置,用头文件另一套写法也可以满足需求,就先这样子写了,后续看看有无特殊的需求或者更好的写法再进行更改。