4、PIC32系列 GPIO介绍

PIC32系列 GPIO介绍

1、PIC32参考资源

2、GPIO寄存器介绍

3、使用寄存器配置IO口输出LED闪烁

4、库函数封装定义

5、库函数

6、实验验证


1、PIC32参考资源

PIC32系列参考手册 中文版  链接地址:PIC系列参考手册-中文版 第12章IO端口.pdf

2、GPIO寄存器介绍

1、TRIS(三态)寄存器

TRIS寄存器用于配置通过IO端口引脚的数据方向。TRIS寄存器决定PORT I/O引脚是输入还是输出。

• TRIS 位设为 1 时,相应的 I/O 端口引脚配置为输入。

• TRIS 位设为 0 时,相应的 I/O 端口引脚配置为输出。

• 读 TRIS 寄存器时,将会读取最后写入 TRIS 寄存器的值。

• 上电复位之后,所有 I/O 端口引脚都定义为输入。

2、PORT 寄存器

PORT 寄存器用于访问 (读取) I/O 引脚。

• 写 PORT 寄存器时,数据将会写入相应的 LAT 寄存器 (PORT 数据锁存器)。那些配置为输出的 I/O 端口引脚会被更新。

• 写 PORT 寄存器实际上等同于写 LAT 寄存器。

• 读 PORT 寄存器时,将会读取施加到端口 I/O 引脚的同步信号。

3、LAT 寄存器

LAT 寄存器 (PORT 数据锁存器)用于保存写入端口 I/O 引脚的数据。

• 写 LAT 寄存器时,会将数据锁存到相应的端口 I/O 引脚。那些配置为输出的 I/O 端口引脚会被更新。

• 读 LAT 寄存器时,将会读取 PORT 数据锁存器中保存的数据,而不是从端口 I/O 引脚读取数据。

4、SET、CLR 和 和 INV I/O 端口寄存器

除 TRIS、PORT 和 LAT 基址寄存器外,每个端口模块还有关联的 SET(置 1)、CLR(清零)和 INV (取反)寄存器,用于提供原子级位操作并允许更快速的 I/O 引脚操作。正如寄存器名称所示,向 SET、 CLR 或 INV 寄存器写入值会有效地执行其名称所示的操作,但只会修改相应的基址寄存器中指定为 1 的位。不会修改指定为 0 的位。

• 向 TRISASET 寄存器写入 0x0001,只会将基址寄存器 TRISA 中的 bit 0 置 1

• 向 PORTDCLR 寄存器写入 0x0020,只会将基址寄存器 PORTD 中的 bit 5 清零

• 向 LATCINV 寄存器写入 0x9000,只会将基址寄存器 LATC 中的 bit 15 和 bit 12 取反

读取 SET、CLR 和 INV 寄存器会返回未定义的值。要查看对 SET、CLR 或 INV 寄存器执行写操作后的效果,必须读取基址寄存器。

SET、CLR 和 INV 寄存器不限于 TRIS、PORT 和 LAT 寄存器。其他 I/O 端口模块寄存器 ODC、CNEN 和 CNPUE 也具有这些位操作寄存器。

5、简而言之

TRS寄存器:设置数字引脚输入还是输出,置1配为输入(默认),清0配置为输出;

LAT寄存器:写端口值

POR寄存器:读端口值

CLR寄存器:清零

SET寄存器:置1

INV寄存器:翻转

端口组合

LATCSET |= (1<<0); //PORTC端口寄存器bit0置1

LATCCLR |= (1<<0); //PORTC端口寄存器bit0清0

LATCINV |= (1<<0); //PORTC端口寄存器bit0翻转

3、使用寄存器配置IO口输出LED闪烁

LED引脚端口RB0

TRISBCLR |= (1<<0); //设置RB0为输出口;
LATBCLR |= (1<<0); //输出0;

LED翻转程序

int main(void)
{
    TRISBCLR |= (1<<0); //设置RB0为输出口;
    LATBCLR |= (1<<0); //输出0;

    while(1)
    {
        LATBINV |= (1<<0); //端口电平翻转
        delay(1000); //延时1000ms
    }
}

4、库函数封装定义

1、端口定义

typedef enum
{
    GPIO_PORT_A = 0,
    GPIO_PORT_B = 1,
    GPIO_PORT_C = 2,
    GPIO_PORT_D = 3,
    GPIO_PORT_E = 4,
    GPIO_PORT_F = 5,
    GPIO_PORT_G = 6,
} GPIO_PORT;

2、引脚定义

typedef enum
{
    GPIO_PIN_RA0 = 0,
    GPIO_PIN_RA1 = 1,
    GPIO_PIN_RA2 = 2,
    GPIO_PIN_RA3 = 3,
    GPIO_PIN_RA4 = 4,
    GPIO_PIN_RA5 = 5,
    GPIO_PIN_RA6 = 6,
    GPIO_PIN_RA7 = 7,
    GPIO_PIN_RA9 = 9,
    GPIO_PIN_RA10 = 10,
    GPIO_PIN_RA14 = 14,
    GPIO_PIN_RA15 = 15,
    GPIO_PIN_RB0 = 16,
    GPIO_PIN_RB1 = 17,
    GPIO_PIN_RB2 = 18,
    GPIO_PIN_RB3 = 19,
    GPIO_PIN_RB4 = 20,
    GPIO_PIN_RB5 = 21,
    GPIO_PIN_RB6 = 22,
    GPIO_PIN_RB7 = 23,
    GPIO_PIN_RB8 = 24,
    GPIO_PIN_RB9 = 25,
    GPIO_PIN_RB10 = 26,
    GPIO_PIN_RB11 = 27,
    GPIO_PIN_RB12 = 28,
    GPIO_PIN_RB13 = 29,
    GPIO_PIN_RB14 = 30,
    GPIO_PIN_RB15 = 31,
    GPIO_PIN_RC1 = 33,
    GPIO_PIN_RC2 = 34,
    GPIO_PIN_RC3 = 35,
    GPIO_PIN_RC4 = 36,
    GPIO_PIN_RC12 = 44,
    GPIO_PIN_RC13 = 45,
    GPIO_PIN_RC14 = 46,
    GPIO_PIN_RC15 = 47,
    GPIO_PIN_RD0 = 48,
    GPIO_PIN_RD1 = 49,
    GPIO_PIN_RD2 = 50,
    GPIO_PIN_RD3 = 51,
    GPIO_PIN_RD4 = 52,
    GPIO_PIN_RD5 = 53,
    GPIO_PIN_RD6 = 54,
    GPIO_PIN_RD7 = 55,
    GPIO_PIN_RD8 = 56,
    GPIO_PIN_RD9 = 57,
    GPIO_PIN_RD10 = 58,
    GPIO_PIN_RD11 = 59,
    GPIO_PIN_RD12 = 60,
    GPIO_PIN_RD13 = 61,
    GPIO_PIN_RD14 = 62,
    GPIO_PIN_RD15 = 63,
    GPIO_PIN_RE0 = 64,
    GPIO_PIN_RE1 = 65,
    GPIO_PIN_RE2 = 66,
    GPIO_PIN_RE3 = 67,
    GPIO_PIN_RE4 = 68,
    GPIO_PIN_RE5 = 69,
    GPIO_PIN_RE6 = 70,
    GPIO_PIN_RE7 = 71,
    GPIO_PIN_RE8 = 72,
    GPIO_PIN_RE9 = 73,
    GPIO_PIN_RF0 = 80,
    GPIO_PIN_RF1 = 81,
    GPIO_PIN_RF2 = 82,
    GPIO_PIN_RF3 = 83,
    GPIO_PIN_RF4 = 84,
    GPIO_PIN_RF5 = 85,
    GPIO_PIN_RF8 = 88,
    GPIO_PIN_RF12 = 92,
    GPIO_PIN_RF13 = 93,
    GPIO_PIN_RG0 = 96,
    GPIO_PIN_RG1 = 97,
    GPIO_PIN_RG2 = 98,
    GPIO_PIN_RG3 = 99,
    GPIO_PIN_RG6 = 102,
    GPIO_PIN_RG7 = 103,
    GPIO_PIN_RG8 = 104,
    GPIO_PIN_RG9 = 105,
    GPIO_PIN_RG12 = 108,
    GPIO_PIN_RG13 = 109,
    GPIO_PIN_RG14 = 110,
    GPIO_PIN_RG15 = 111,

    GPIO_PIN_NONE = -1

} GPIO_PIN;

3、引脚序号

typedef enum
{
  CN0_PIN = 1 << 0,
  CN1_PIN = 1 << 1,
  CN2_PIN = 1 << 2,
  CN3_PIN = 1 << 3,
  CN4_PIN = 1 << 4,
  CN5_PIN = 1 << 5,
  CN6_PIN = 1 << 6,
  CN7_PIN = 1 << 7,
  CN8_PIN = 1 << 8,
  CN9_PIN = 1 << 9,
  CN10_PIN = 1 << 10,
  CN11_PIN = 1 << 11,
  CN12_PIN = 1 << 12,
  CN13_PIN = 1 << 13,
  CN14_PIN = 1 << 14,
  CN15_PIN = 1 << 15,
  CN16_PIN = 1 << 16,
  CN17_PIN = 1 << 17,
  CN18_PIN = 1 << 18,
  CN19_PIN = 1 << 19,
  CN20_PIN = 1 << 20,
  CN21_PIN = 1 << 21,
}CN_PIN;

5、库函数

1、端口操作,可同时对多个IO口设置

//读取端口电平状态
uint32_t GPIO_PortRead(GPIO_PORT port)
{
    return (*(volatile uint32_t *)(&PORTA + (port * 0x10)));
}

//写端口电平
void GPIO_PortWrite(GPIO_PORT port, uint32_t mask, uint32_t value)
{
    *(volatile uint32_t *)(&LATA + (port * 0x10)) = (*(volatile uint32_t *)(&LATA + (port * 0x10)) & (~mask)) | (mask & value);
}

//读取端口锁存器值
uint32_t GPIO_PortLatchRead(GPIO_PORT port)
{
    return (*(volatile uint32_t *)(&LATA + (port * 0x10)));
}

//设置端口
void GPIO_PortSet(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&LATASET + (port * 0x10)) = mask;
}

//清除端口
void GPIO_PortClear(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&LATACLR + (port * 0x10)) = mask;
}

//端口电平翻转
void GPIO_PortToggle(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&LATAINV + (port * 0x10))= mask;
}

//端口输入使能
void GPIO_PortInputEnable(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&TRISASET + (port * 0x10)) = mask;
}

//端口输出使能
void GPIO_PortOutputEnable(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&TRISACLR + (port * 0x10)) = mask;
}

2、对单个IO口操作

//写引脚电平
static inline void GPIO_PinWrite(GPIO_PIN pin, bool value)
{
    GPIO_PortWrite((GPIO_PORT)(pin>>4), (uint32_t)(0x1) << (pin & 0xF), (uint32_t)(value) << (pin & 0xF));
}

//读取引脚电平
static inline bool GPIO_PinRead(GPIO_PIN pin)
{
    return (bool)(((GPIO_PortRead((GPIO_PORT)(pin>>4))) >> (pin & 0xF)) & 0x1);
}

//读引脚寄存器值
static inline bool GPIO_PinLatchRead(GPIO_PIN pin)
{
    return (bool)((GPIO_PortLatchRead((GPIO_PORT)(pin>>4)) >> (pin & 0xF)) & 0x1);
}

//引脚电平翻转
static inline void GPIO_PinToggle(GPIO_PIN pin)
{
    GPIO_PortToggle((GPIO_PORT)(pin>>4), 0x1 << (pin & 0xF));
}

//设置引脚
static inline void GPIO_PinSet(GPIO_PIN pin)
{
    GPIO_PortSet((GPIO_PORT)(pin>>4), 0x1 << (pin & 0xF));
}

//清除引脚
static inline void GPIO_PinClear(GPIO_PIN pin)
{
    GPIO_PortClear((GPIO_PORT)(pin>>4), 0x1 << (pin & 0xF));
}

//引脚输入使能
static inline void GPIO_PinInputEnable(GPIO_PIN pin)
{
    GPIO_PortInputEnable((GPIO_PORT)(pin>>4), 0x1 << (pin & 0xF));
}

//引脚输出使能
static inline void GPIO_PinOutputEnable(GPIO_PIN pin)
{
    GPIO_PortOutputEnable((GPIO_PORT)(pin>>4), 0x1 << (pin & 0xF));
}

LED翻转程序

int main(void)
{
    GPIO_PortOutputEnable(GPIO_PORT_B,CN0_PIN);  //RB0设置为输出

    while(1)
    {
        GPIO_PortToggle(GPIO_PORT_B,CN0_PIN);
        delay(1000);
    }
}

6、实验验证

程序编译后 烧录到开发板中,LED灯闪烁显示。

时间:2021.07.15

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Huangtop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值