1、PIC32参考资源
PIC32系列参考手册 中文版 链接地址:PIC系列参考手册-中文版 第12章IO端口.pdf(https://download.csdn.net/download/Huangtop/20299186)
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灯闪烁显示。
————————————————
版权声明:本文为CSDN博主「Huangtop」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Huangtop/article/details/118755418