端口结构介绍 无论使用MCU实现什么功能,只要是有意义的功能必然会涉及到IO口的操作。IO口的操作也是MCU的入门操作,按国际惯例一般上手MCU的第一个程序点灯程序就是通过IO口的输出来实现的。 华大M0+系列单片机的端口电路有两种结构,这两种电路结构大体相同,只是存在三个微小的差别。HC32F(L)x3x、HC32F(L)x7x和HC32F(L)x9x系列芯片的端口电路是一种结构,为了便于说明我们称这种结构为结构一,框图如下:
HC32F003、HC32F005和HC32L110芯片是一种结构,我们称这种结构为结构二,框图如下:
由上面两个构图我们可以很清楚地知道两种结构的区别如下:
1.结构一的PxOUT(寄存器中出现的x=A,B,C,D,E,F代表芯片含有的端口组,后面的亦是同样的意思)可以通过操作位寄存器(PxBSET、PxBCLR、PxBSETCLR)来直接控制某一位的输出,而不会影响这组寄存器中的其余的位,结构二没有相关的位操作。
2.结构一输出/输入数据寄存器(PxOUT/PxIN)支持AHB/FAST IO总线访问(通过寄存器 GPIO_CTRL2.ahb_sel 位控制),其他寄存器支持AHB总线访问。结构二端口输入值/输出值寄存器(PxIN/PxOUT)只支持 AHB 总线读写。对于这两种不同的总线,系统时钟(HCLK)对这两种总线的处理周期并不相同。下面两幅图为对于两种总线端口翻转的最快时序:
对于 AHB 总线,每两个 HCLK 周期,IO 翻转一次,而对于 FAST IO 总线,每个 HCLK周期,IO 翻转一次。
3.结构二对应芯片的RST引脚可以复用成带有内部上拉电阻的数字输入引脚,结构一对应的芯片RST引脚不可以复用为IO引脚。 重点来了,说完两种结构的差**进入正题,说下两种结构和共性。
每个端口都可以配置成数字或模拟端口,并且可以实现内部上拉(pull up)/下拉(pull down)的输入,高阻输入(floating input),推挽输出(CMOS output),开漏输出(open drain output),两档驱动能力输出。 数字端口被配置成模拟端口后,数字功能被隔离,不能输出数字“1”和“0”,CPU 读取端口输入值寄存器的结果为“0”。
每个数字端口被配置为输入时,都可以提供外部中断,中断类型可以配置成高电平触发、低电平触发、上升沿触发、下降沿触发 4 种,查询 Px_STAT[n]的中断标志位即可知道相应的中断触发端口。另外,每个数字端口的中断都可以把芯片从睡眠模式/深度睡眠模式唤醒到工作模式。
芯片复位后端口为高阻输入(floating input),目的是防止芯片被异常复位时,对外部器件产生异常动作。
当端口配置为数字端口的时候可以通过设置Px_SEL寄存器接受各功能模块(如 SPI,UART,I2C,Timer 等)的输入输出信号,此内容放到相应外设模块内容来讲解。 端口相关配置介绍端口相关配置如下:
数字端口(PxADS对应位为0);
模拟端口(PxADS对应位为1);
端口引脚为输入(PxDIR对应位为1);
端口引脚为输出(PxDIR对应位为0);
输入电平状态(PxIN 对应引脚获得高电平对应位为1,获得低电平对应位为0);
输出电平选择(PxOUT 对应位为1相应引脚输出高电平,为0相应引脚输出低电平);
内部上拉(PxPU对应位为1);
内部下拉(PxPD对应位为1);
高阻(PxPU对应位为0且PxPD对应位为0);
推挽输出(PxOD对应位为0);
开漏输出(PxOD对应位为1);
低驱动能力输出(PxDR对应位为1);
高驱动能力输出(PxDR对应位为0);
端口高电平中断使能(PxHIE对应位为1);
端口低电平中断使能(PxLIE对应位为1);
端口上升沿中断使能(PxRIE对应位为1);
端口下降沿中断使能(PxFIE对应位为1); 对于结构一的芯片特有寄存器
端口置位(PxBSET对应位为1置位,为0保持);
端口清零(PxBCLR对应位为1清零,为0保持);
端口置位清零(PxBSETCLR (PxBSET对应位为1置位,为0保持;PxBCLR对应位为1清零,为0保持))。PxBSET 和 PxBCLR 相同位同时置 1 时,PxBCLR 具有高优先级。即该端口被清零。 端口配置操作流程端口复用配置为模拟端口操作流程a)设置寄存器 PxADS[n]为 1 端口复用配置为数字通用端口操作流程a) 设置寄存器 PxADS[n]为 0
b) 设置寄存器 Px_SEL 为 0
c) 设置寄存器 PxDIR[n]为 1:端口方向为输入,CPU 可以读取端口的状态 PxIN[n]。
d) 设置寄存器 PxDIR[n]为 0:端口方向为输出
e) 设置寄存器 PxOUT[n]为 1:端口输出高电平
f) 设置寄存器 PxOUT[n]为 0:端口输出低电平 端口上拉使能配置操作流程a)设置寄存器 PxPU[n]为 1 端口下拉使能配置操作流程a) 设置寄存器 PxPU[n]为 0
b) 设置寄存器 PxPD[n]为 1
注:当 PxPU[n],PxPD[n]同时置 1 时,PxPU[n]优先级高,PxPD[n]无效。 端口增强驱动配置操作流程a)设置寄存器 PxDR[n]为 0 端口开漏输出配置操作流程a)设置寄存器 PxOD[n]为 1 配置代码无上下拉输入配置 stc_gpio_cfg_t stcGpioCfg; Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //打开GPIO外设时钟 stcGpioCfg.enDir = GpioDirIn; //端口方向配置->输入 stcGpioCfg.enDrv = GpioDrvL; //驱动能力配置->高驱动能力 stcGpioCfg.enPu = GpioPuDisable; //端口上下拉配置->无 stcGpioCfg.enPd = GpioPdDisable; stcGpioCfg.enOD = GpioOdDisable; //开漏输出配置->开漏输出关闭 stcGpioCfg.enCtrlMode = GpioAHB; //总线控制模式配置->AHB Gpio_Init(STK_USER_PORT, STK_USER_PIN, &stcGpioCfg); // GPIO IO USER KEY初始化推挽输出配置 stc_gpio_cfg_t stcGpioCfg; Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //打开GPIO外设时钟 stcGpioCfg.enDir = GpioDirOut; //端口方向配置->输出 stcGpioCfg.enDrv = GpioDrvL; //驱动能力配置->高驱动能力 stcGpioCfg.enPu = GpioPuDisable; //端口上下拉配置->无 stcGpioCfg.enPd = GpioPdDisable; stcGpioCfg.enOD = GpioOdDisable; //开漏输出配置->开漏输出关闭 stcGpioCfg.enCtrlMode = GpioAHB; //总线控制模式配置->AHB Gpio_Init(STK_LED_PORT, STK_LED_PIN, &stcGpioCfg); // GPIO IO LED端口初始化 Gpio_ClrIO(STK_LED_PORT, STK_LED_PIN); // LED关闭常用的端口操作库函数单端口操作单个IO口输出低电平原型 en_result_t Gpio_ClrIO(en_gpio_port_t enPort, en_gpio_pin_t enPin)举例 Gpio_ClrIO(GpioPortA ,GpioPin1 ); //PA01端口输出低电平单个IO口输出高电平原型 en_result_t Gpio_SetIO(en_gpio_port_t enPort, en_gpio_pin_t enPin)举例 Gpio_SetIO(GpioPortA ,GpioPin1 ); //PA01端口输出高电平获得IO口输入值原型 boolean_t Gpio_GetInputIO(en_gpio_port_t enPort, en_gpio_pin_t enPin)举例 u8PA1Stat = Gpio_GetInputIO(GpioPortA ,GpioPin1); //u8PA1Stat 为PA1端口输入电平状态获得IO口输出值原型 boolean_t Gpio_ReadOutputIO(en_gpio_port_t enPort, en_gpio_pin_t enPin)举例 u8PA1Stat = Gpio_ReadOutputIO(GpioPortA ,GpioPin1); //u8PA1Stat 为PA1端口输出电平状态多端口操作同时让一组端口中的多个引脚输出低电平原型 en_result_t Gpio_ClrPort(en_gpio_port_t enPort, uint16_t u16ValMsk)举例 Gpio_ClrPort(GpioPortA , 0x000F); //PA0~PA3输出低电平,其余保持同时让一组端口中的多个引脚输出高电平原型 en_result_t Gpio_SetPort(en_gpio_port_t enPort, uint16_t u16ValMsk)举例 Gpio_SetPort(GpioPortA , 0x000F); //PA0~PA3输出高电平,其余保持获取一组IO口的输入数据原型 uint16_t Gpio_GetInputData(en_gpio_port_t enPort)举例 u16PAInputData = Gpio_GetInputData(GpioPortA ); //u16PAInputData的值为PA组输入数据同时让一组端口输出多个高低电平原型 en_result_t Gpio_SetClrPort(en_gpio_port_t enPort, uint32_t u32ValMsk)举例 Gpio_SetClrPort(GpioPortA , 0x00f0000f); //PA4 ~ PA7输出高电平PA0 ~ PA3输出低电平
|