单片机中NRST引脚复用为GPIO

多数单片机引脚较多,一般为48Pin,但也有许多引脚少的单片机以低廉的成本在某些应用上具有较大的优势。

这里以20Pin的PY32F003F18P6TU和8Pin的PY32F002BL15S7为例说明少量引脚单片机的特殊引脚复用。

20Pin的PY32F003F18P6TU的NRST引脚复用为普通GPIO

  • 首先我们需要知道的是NRST引脚的端口类型是I/O,并且具有通道引脚号PF2,同时在引脚定义表格的下方说明了通过设置option bytes即可将引脚转为普通GPIO引脚PF2

  • option bytes是什么呢?Option Bytes(选项字节)是 微控制器(MCU)中用于存储硬件配置参数的非易失性存储区域,决定芯片上电后的基础工作模式。也就是说它是FLASH中存储上电后单片机如何工作的控制参数。

  • 如何修改option bytes?请看如下代码

    复制代码
    static void ConfigurePF2AsGPIO(void)
    {
    	// 解锁 FLASH
    	HAL_FLASH_Unlock();
    	// 解锁 Option Bytes
    	HAL_FLASH_OB_Unlock();
    
    	// 配置 Option Bytes
    	FLASH_OBProgramInitTypeDef OBInitCfg;
    	
    	OBInitCfg.OptionType = OPTIONBYTE_USER;		  // 选项类型 用户OB字节
    	OBInitCfg.USERType = OB_USER_NRST_MODE; 	  // 修改 NRST_MODE
    	OBInitCfg.USERConfig = OB_RESET_MODE_GPIO;    // 设置NRST 为 GPIO
    
    	HAL_FLASH_OBProgram(&OBInitCfg);		//写入配置
    
    	// 锁定 FLASH
    	HAL_FLASH_Lock();
    	// 锁定 Option Bytes
    	HAL_FLASH_OB_Lock();
    
    	// 重新加载 Option Bytes,触发 MCU 重启
    	HAL_FLASH_OB_Launch();
    }
  • 为避免重复运行导致的重启,在main函数开始前检查设置的对应数值是否为NRST配置数值,如果是则进入修改。也可以检查是否为GPIO配置数值。

    复制代码
    // 检查 PF2 NRST 是否已配置为 GPIO
    if (READ_BIT(FLASH->OPTR, FLASH_OPTR_NRST_MODE) == OB_RESET_MODE_RESET)
    {
    	ConfigurePF2AsGPIO(); // 如果未配置,则调用函数进行修改
    }

8Pin的PY32F002BL15S7的NRST引脚复用为普通GPIO

  • 首先和上面的20Pin的PY32F003F18P6TU一样,我们也可以在手册上看到相似的内容,但因为引脚较少,有些不一样的东西,如下图,单片机的6号引脚既具备PA6的功能,也具备PC0的NRST功能:

  • 那一个引脚具有多个通道的功能如何使用呢?我们先看7号引脚。7号引脚既可以作为PA7使用,也可以作为PC1使用。如果我们需要使用PA7的USART_RX功能,则只需要GPIO初始化PA7引脚,并使用AF3复用功能,PC1不初始化即可 (用哪个初始化那个)。

    复制代码
    void HAL_UART_MspInit(UART_HandleTypeDef *huart)
    {
    	GPIO_InitTypeDef  GPIO_InitStruct = {0};
    
    	/* Clock Enable */
    	__HAL_RCC_GPIOA_CLK_ENABLE();
    	__HAL_RCC_USART1_CLK_ENABLE();
    
    	/* GPIO initialization
    	PA06:TX,
    	PA07:RX
    	*/
    	GPIO_InitStruct.Pin       = GPIO_PIN_6;
    	GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    	GPIO_InitStruct.Pull      = GPIO_PULLUP;
    	GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    	GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
    	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    	GPIO_InitStruct.Pin = GPIO_PIN_7;
    	GPIO_InitStruct.Alternate = GPIO_AF3_USART1;
    	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    	/* USART1 interrupt enable */
    	HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
    	HAL_NVIC_EnableIRQ(USART1_IRQn);
    }
  • 回到我们的问题,NRST复用为普通GPIO。这里既有1个引脚连接多通道问题,也有NRST与通道复用的问题。因此需要先将NRST功能禁用,再初始化为PA6,才能正常使用USART_TX功能。如果不禁用NRST功能,直接初始化PA6,则程序异常,系统不断重启。

  • 禁用NRST,与20Pin的PY32F003F18P6TU相似,但有不同,由于8Pin的单片机引脚少,因此她的下载接口SWDIO与NRST功能的Option Bytes在hal库中由同一字段控制,需要选择合适的控制字写入。
    控制字OBInitCfg.USERConfig可设置为:

    示例代码:

    复制代码
    static void ConfigurePF2AsGPIO(void)
    {
    	// 解锁 FLASH 和 Option Bytes
    	HAL_FLASH_Unlock();
    	HAL_FLASH_OB_Unlock();
    
    	// 配置 Option Bytes
    	FLASH_OBProgramInitTypeDef OBInitCfg;
    	OBInitCfg.OptionType = OPTIONBYTE_USER;
    	OBInitCfg.USERType = OB_USER_SWD_NRST_MODE; // 修改 SWD 和 NRST MODE
    	OBInitCfg.USERConfig = OB_SWD_PB6_GPIO_PC0; // 设置PB6为SWD,PC0为GPIO 模式
    
    	HAL_FLASH_OBProgram(&OBInitCfg);
    
    	// 锁定 FLASH 和 Option Bytes
    	HAL_FLASH_Lock();
    	HAL_FLASH_OB_Lock();
    
    	// 重新加载 Option Bytes,触发 MCU 重启
    	HAL_FLASH_OB_Launch();
    
    	NVIC_SystemReset();
    }
  • 此时PC0被设置为普通GPIO,再GPIO初始化PA6为AF1的USART_TX即可。

    复制代码
    void HAL_UART_MspInit(UART_HandleTypeDef *huart)
    {
    	GPIO_InitTypeDef  GPIO_InitStruct = {0};
    
    	/* Clock Enable */
    	__HAL_RCC_GPIOA_CLK_ENABLE();
    	__HAL_RCC_USART1_CLK_ENABLE();
    
    	/* GPIO initialization
    	PA06:TX,
    	PA07:RX
    	*/
    	GPIO_InitStruct.Pin       = GPIO_PIN_6;
    	GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    	GPIO_InitStruct.Pull      = GPIO_PULLUP;
    	GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    	GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
    	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    	GPIO_InitStruct.Pin = GPIO_PIN_7;
    	GPIO_InitStruct.Alternate = GPIO_AF3_USART1;
    	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    	/* USART1 interrupt enable */
    	HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
    	HAL_NVIC_EnableIRQ(USART1_IRQn);
    }
相关推荐
清风66666617 小时前
基于单片机与DAC0832的双路波形信号发生系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
azwsm18 小时前
电路元器件和GPIO控制器
单片机·嵌入式硬件
kebidaixu21 小时前
FreeRTOS 移植到 STM32F407VETX 记录(一)
stm32·单片机·嵌入式硬件
CSDN官方博客1 天前
「谁说嵌入式只是调包和焊板子?」—— 2026嵌入式全栈技术征锋令
嵌入式硬件·物联网·embedding
点灯小铭1 天前
基于单片机的数码管定时插座设计与定时开关功能实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
云栖梦泽1 天前
玩转RK3506SDK
linux·嵌入式硬件
数智工坊1 天前
机器人四大主控板系统分层选型指南:树莓派、ESP32、STM32与Arduino的能力边界与实战定位
stm32·嵌入式硬件·机器人
进击的小头1 天前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
点灯小铭1 天前
基于单片机的多模式智能洗衣机设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
项目題供诗1 天前
STM32-AD单通道&AD多通道(十九)
stm32·单片机·嵌入式硬件