目录
- 普冉PY32系列(一 PY32F0系列32位Cortex M0+ MCU简介
- 普冉PY32系列(二 Ubuntu GCC Toolchain和VSCode开发环境
- 普冉PY32系列(三 PY32F002A资源实测 - 这个型号不简单
- 普冉PY32系列(四 PY32F002A/003/030的时钟设置
- 普冉PY32系列(五 使用JLink RTT代替串口输出日志
- 普冉PY32系列(六 通过I2C接口驱动PCF8574扩展的1602LCD
- 普冉PY32系列(七 SOP8,SOP10,SOP16封装的PY32F002A/PY32F003管脚复用
PY32F0系列的封装
- 20PIN, 24PIN 和 32PIN, 带有独立的 NRST 和 BOOT0, PIN脚互相独立不复用;
- 8PIN, 10PIN 和 16PIN, 没有 BOOT0, 存在多个PIN脚共用同一个物理管脚的情况
这篇主要介绍没有BOOT0的情况如何修改Option Bytes, 以及如何在物理管脚上使用不同的PIN
PY32F002A 的封装
PY32F002AL15S, PY32F002AA15M, PY32F002AW15S
PY32F002AW15U, PY32F002AF15P
PY32F003 的封装
PY32F003L1xS, PY32F003L2XD, PY32F003L2xS
PY32F003A18N, PY32F003W1XS
PY32F002A/PY32F003 管脚复用
在 OB(Option Bytes中禁用和启用 PF2/RESET
PF2/NRST这个PIN是比较麻烦的一个功能脚, 因为默认启用了RESET功能, 不受PIN模式的影响, 所以无论你把它设置成INPUT, OUTPUT 还是 ANALOG, RESET永远生效, 和这个PIN同处于同一个物理管脚的PIN就没法正常使用。
对于正常带 PF4/BOOT0 的型号, 在上电时拉高 BOOT0, 就可以从 system memory 启动 boot loader, 通过 ISP 工具连接后在工具里修改 OB, 但是 SOP8 和 SOP16 这些封装没有 BOOT0, 所以没法使用 ISP 工具修改. 只能通过代码或第三方工具(例如JLink修改. 以下以LL库为例, 说明在代码中修改OB的方法
static void APP_FlashSetOptionBytes(void
{
FLASH_OBProgramInitTypeDef OBInitCfg;
LL_FLASH_Unlock(;
LL_FLASH_OB_Unlock(;
OBInitCfg.OptionType = OPTIONBYTE_USER;
OBInitCfg.USERType = OB_USER_BOR_EN | OB_USER_BOR_LEV | OB_USER_IWDG_SW | OB_USER_WWDG_SW | OB_USER_NRST_MODE | OB_USER_nBOOT1;
/*
* 默认的值: OB_BOR_DISABLE | OB_BOR_LEVEL_3p1_3p2 | OB_IWDG_SW | OB_WWDG_SW | OB_RESET_MODE_RESET | OB_BOOT1_SYSTEM;
*/
OBInitCfg.USERConfig = OB_BOR_DISABLE | OB_BOR_LEVEL_3p1_3p2 | OB_IWDG_SW | OB_WWDG_SW | OB_RESET_MODE_GPIO | OB_BOOT1_SYSTEM;
LL_FLASH_OBProgram(&OBInitCfg;
LL_FLASH_Lock(;
LL_FLASH_OB_Lock(;
/* 重新载入OB, 这会触发软复位, MCU重启 */
LL_FLASH_OB_Launch(;
}
注意, 上面这个方法执行后会重启MCU, 所以在调用前要做个判断, 否则它会一直循环重启下去
/* 检查 PF2 是否已经关闭了复位 */
if(READ_BIT(FLASH->OPTR, FLASH_OPTR_NRST_MODE == OB_RESET_MODE_RESET
{
/* 如果没关闭则调用 */
APP_FlashSetOptionBytes(;
}
// 否则继续正常执行
这样执行完之后, RESET按钮就失效了, 如果要恢复, 要再将OB改回默认的值
OB_BOR_DISABLE | OB_BOR_LEVEL_3p1_3p2 | OB_IWDG_SW | OB_WWDG_SW | OB_RESET_MODE_RESET | OB_BOOT1_SYSTEM;
同一物理管脚的其它PIN, 设为模拟(ANALOG模式
以下以SOP16封装的为例, 启用 PF1, PF0, 禁用对应同一管脚的 PA14 和 PF2
static void APP_GPIO_Config(void
{
//...
// PF1 SCL
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
LL_GPIO_Init(GPIOF, &GPIO_InitStruct;
// PF0 SDA
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
LL_GPIO_Init(GPIOF, &GPIO_InitStruct;
/**
* 根据数据手册第20页, 同管脚的其它PIN应当设为 ANALOG.
*/
// PA14
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_14, LL_GPIO_MODE_ANALOG;
// PF2
LL_GPIO_SetPinMode(GPIOF, LL_GPIO_PIN_2, LL_GPIO_MODE_ANALOG;
//...
}
电路连线避免干扰
管脚复用之后, 一些功能脚带的开关按钮和电阻电容就会对其它PIN造成影响。
启动增加延时, 确保上电烧录
因为小封装没有 BOOT0, 所以在 SWD 口烧录失败的情况下, 没法用 ISP 工具救场, 如果你的程序加电后没有预留足够长时间的 delay, 又把 SWD 口的 PA13 PA14 给关掉了, 那下一次烧录就会干瞪眼。
int main(void
{
uint8_t i;
BSP_RCC_HSI_24MConfig(;
/**
* 在SWD口关闭前停留2秒, 保证上电后有足够长的烧录等待时间
*/
LL_mDelay(2000;
//...
代码示例
以 SOP16 封装的 PY32F003W18S 为例, 依然使用 1602LCD 作为参考。
源代码已经提交到 GitHub 仓库, 地址: https://github.com/IOsetting/py32f0-template/tree/main/Examples/LL/I2C/PCF8574_1602LCD_PY32F003W_PF0_PF1
编程笔记 » 普冉PY32系列(七) SOP8, SOP10和SOP16封装的PY32F003/PY32F002A管脚复用