单片机中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);
    }
相关推荐
CODECOLLECT1 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen2 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠4 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_5 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技7 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计7 小时前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
小龙报8 小时前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业8 小时前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件
Industio_触觉智能8 小时前
瑞芯微RK3566开发板规格书,详细参数配置,型号EVB3566-V1,基于RK3566核心板SOM3566邮票孔封装
嵌入式硬件·开发板·rk3568·rk3566·核心板·瑞芯微
czwxkn9 小时前
4STM32(stdl)TIM定时器
stm32·单片机·嵌入式硬件