一、芯片简介
QN9080 是一款超低功耗蓝牙无线 MCU,集成了片上存储器、USB2.0 全速兼容设备接口和 16 bit ADC,适合蓝牙智能应用。QN9080 集成了一个 32 位 ARM Cortex-M4F内核,支持 BLE V5.0 的无线电、支持多种 GATT Profile 和 Host 协议栈。
二、PB00/01 引脚说明
我们查看芯片数据手册可知,PB00/01 引脚分别默认配置是外部 32.768KHz 晶振输入和输出引脚,但引脚功能中是可以把这两个引脚配置成通用数字输入输出引脚的,接下来将为大家讲解如何将 PB00/01 引脚配置成 GPIO。
下图为 PB00/01 引脚说明:
图一
下图为 QN9080 原理图,可发现 PB00/01 引脚分别对应外部晶振 32.768KHz 的 XTAL32_IN 和 XTAL32_OUT。
图二
- 关闭外部 32.768KHz 晶振的宏定义:
/* Configure high frequency XTAL according to board design: 16MHz, 32MHz or 0U (no XTAL crystal on board) */
#define BOARD_XTAL0_CLK_HZ 32000000U
/* Configure low frequency XTAL according to board design: 32768U or 0U (no 32K crystal on board) */
#define BOARD_XTAL1_CLK_HZ 0U//32768U
通过配置和宏的位置可知,将宏设置为 0 说明不使用外部 32K 的晶振。
- 屏蔽外部 32KHz 时钟配置成 32K 时钟的代码,将内部 RCO 32K 配置为 32K 时钟:
void BOARD_BootClockRUN(void)
{
/* Power up/Power down the module. */
/* Set up clock selectors - Attach clocks to the peripheries */
CLOCK_AttachClk(k32M_to_XTAL_CLK); /* Switch XTAL_CLK to 32M */
CLOCK_AttachClk(kRCO32K_to_32K_CLK); /* Switch 32K_CLK to RCO 32KHz clock */
// CLOCK_AttachClk(kXTAL32K_to_32K_CLK); /* Switch 32K_CLK to XTAL32K */
CLOCK_AttachClk(kXTAL_to_SYS_CLK); /* Switch SYS_CLK to XTAL */
CLOCK_AttachClk(kAPB_to_WDT_CLK); /* Switch WDT_CLK to APB */
/* Set up dividers */
CLOCK_SetClkDiv(kCLOCK_DivOsc32mClk, 1U); /* Set OSC32M_DIV divider to value 2 */
CLOCK_SetClkDiv(kCLOCK_DivXtalClk, 1U); /* Set XTAL_DIV divider to value 2 */
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 0U); /* Set AHB_DIV divider to value 1 */
CLOCK_SetClkDiv(kCLOCK_DivFrg1, 0U); /* Set FRG_MULT1 to value 0, Set FRG_DIV1 to value 255 */
CLOCK_SetClkDiv(kCLOCK_DivFrg0, 0U); /* Set FRG_MULT0 to value 0, Set FRG_DIV0 to value 255 */
CLOCK_SetClkDiv(kCLOCK_DivApbClk, 0U); /* Set APB_DIV divider to value 1 */
/* Enable/Disable clock out source and pins.*/
/* Enable/Disable the specified peripheral clock.*/
}
时钟源选择:
typedef enum _clock_attach_id
{
kXTAL32K_to_32K_CLK = MUX_A(CM_32KCLKSEL, 0), /*!< XTAL 32K clock */
kRCO32K_to_32K_CLK = MUX_A(CM_32KCLKSEL, 1), /*!< RCO 32KHz clock */
kOSC32M_to_SYS_CLK = MUX_A(CM_SYSCLKSEL, 0), /*!< OSC 32MHz clock */
kXTAL_to_SYS_CLK = MUX_A(CM_SYSCLKSEL, 1), /*!< XTAL 16MHz/32MHz clock */
k32K_to_SYS_CLK = MUX_A(CM_SYSCLKSEL, 2), /*!< 32KHz clock */
k32K_to_WDT_CLK = MUX_A(CM_WDTCLKSEL, 0), /*!< 32KHz clock */
kAPB_to_WDT_CLK = MUX_A(CM_WDTCLKSEL, 1), /*!< APB clock */
k8M_to_BLE_CLK = MUX_A(CM_BLECLKSEL, 0), /*!< 8M CLOCK */
k16M_to_BLE_CLK = MUX_A(CM_BLECLKSEL, 1), /*!< 16M CLOCK */
k16M_to_XTAL_CLK = MUX_A(CM_XTALCLKSEL, 0), /*!< 16M XTAL */
k32M_to_XTAL_CLK = MUX_A(CM_XTALCLKSEL, 1), /*!< 32M XTAL */
kNONE_to_NONE = 0x80000000U,
} clock_attach_id_t;
- 设置 PIO_CFG_MISC 寄存器,将 PB00,PB01 设置成普通 GPIO 引脚:
我们查看芯片用户手册可知,PB00/PB01 引脚功能可通过寄存器 PIO_CFG_MISC 来选择,可通过对特定 bit 位设置 0或 1 来使能或失能时钟引脚功能。
图三
下图为寄存器 PIO_CFG_MISC 的每个 bit 位具体对应功能描述:
图四
将寄存器 PIO_CFG_MISC 的 bit 0,bit 1 分别设置为 0,即关闭 PB00,PB01 时钟引脚功能。如下所示:
void BOARD_BootClockRUN(void)
{
/* Power up/Power down the module. */
/* Set up clock selectors - Attach clocks to the peripheries */
CLOCK_AttachClk(k32M_to_XTAL_CLK); /* Switch XTAL_CLK to 32M */
CLOCK_AttachClk(kRCO32K_to_32K_CLK); /* Switch 32K_CLK to RCO 32KHz clock */
// CLOCK_AttachClk(kXTAL32K_to_32K_CLK); /* Switch 32K_CLK to XTAL32K */
CLOCK_AttachClk(kXTAL_to_SYS_CLK); /* Switch SYS_CLK to XTAL */
CLOCK_AttachClk(kAPB_to_WDT_CLK); /* Switch WDT_CLK to APB */
/* Set up dividers */
CLOCK_SetClkDiv(kCLOCK_DivOsc32mClk, 1U); /* Set OSC32M_DIV divider to value 2 */
CLOCK_SetClkDiv(kCLOCK_DivXtalClk, 1U); /* Set XTAL_DIV divider to value 2 */
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 0U); /* Set AHB_DIV divider to value 1 */
CLOCK_SetClkDiv(kCLOCK_DivFrg1, 0U); /* Set FRG_MULT1 to value 0, Set FRG_DIV1 to value 255 */
CLOCK_SetClkDiv(kCLOCK_DivFrg0, 0U); /* Set FRG_MULT0 to value 0, Set FRG_DIV0 to value 255 */
CLOCK_SetClkDiv(kCLOCK_DivApbClk, 0U); /* Set APB_DIV divider to value 1 */
/* Enable/Disable clock out source and pins.*/
/* Enable/Disable the specified peripheral clock.*/
SYSCON->PIO_CFG_MISC &= 0xFFFC; /* Set PB00,PB01 as GPIO pin */
CLOCK_EnableClock(kCLOCK_Gpio); /* Enable Gpio Clock */
}
- GPIO 初始化配置:
将 PB00,PB01 进行普通 GPIO 初始化配置:
void BOARD_InitPB00_PB01Pins(void)
{
const uint32_t portb_pin00_config = {
IOCON_FUN0 | /* Selects pin function 0 */
IOCON_MODE_PULLUP | /* Selects pull-up function */
IOCON_DRIVE_LOW /* Enable low drive strength */
};
const uint32_t portb_pin01_config = {
IOCON_FUN0 | /* Selects pin function 0 */
IOCON_MODE_PULLUP | /* Selects pull-up function */
IOCON_DRIVE_LOW /* Enable low drive strength */
};
IOCON_PinMuxSet(IOCON, PORTB_IDX, 0, portb_pin00_config); /* PORTB PIN0 (coords: 3) is configured as PB00 */
IOCON_PinMuxSet(IOCON, PORTB_IDX, 1, portb_pin01_config); /* PORTB PIN1 (coords: 2) is configured as PB01 */
}
按照以上配置后,PB01 可正常设置成 GPIO 输入输出引脚,上下拉都正常,PB00 引脚可设置成输出上下拉功能,无法正常配置成 GPIO 输入,它的输入一直为低电平,需要外部引脚配合改动,因此并不建议客户使用 PB00 引脚用作输入引脚。
四、总结
通过以上讲解,我们就可以完全掌握如何将 QN9080 的 PB00,PB01 引脚配置成 GPIO 功能了,其他特殊引脚的配置也可以通过查看数据手册和用户手册来进行,所以我们要熟练利用好芯片的手册文档,对于使用不熟悉的芯片也会显得轻车熟路。
五、参考资料
【1】QN908x user manual_Rev. 1.1.PDF
【2】QN908x_datasheet.PDF
评论