资讯详情

配置MM32微控制器引脚复用功能

配置MM32微控制器引脚复用功能

文章目录

  • 配置MM32微控制器引脚复用功能
    • Introduction
    • Algorithm
      • GPIOx_CR寄存器
      • GPIOx_AFR寄存器
      • GPIOx_CR & GPIOx_AFR寄存器
        • TIM
        • UART
        • SPI_MASTER
        • SPI_SLAVE
        • I2C
        • CAN
        • ADC
        • FSMC
        • QSPI
        • DAC
        • COMP
        • SDIO
        • USB
    • Practice
    • Conclusion

Introduction

使用过NXP(FSL)微控制器的开发者只配置引脚复用功能PORT在模块中,引脚对应PCR寄存器的MUX在字段中选择引脚的复用功能。但是作者最近在用MM32微控制器(MM32F3270)在配置引脚复用功能时遇到了一些麻烦。MM在用户界面的设计上,32微控制器走得很近ST相对于风格NXP将GPIO(一般控制GPIO的外设)和PORT(与具体芯片相关的复用功能)两个模块分开管理,仅用作数字IO端口的信号输入输出和电气特性,MM32的GPIO外设混合了GPIO和PORT的功能,并把PORT引脚异步中断的功能再次分散到EXTI模块和SYSCFG模块(SYSCFG_EXTICRn)中。

如何整理本文MM引脚复用功能配置在32微控制器上。

现在看来,后续需要整理如何使用MM32中断引脚,混合GPIO、EXTI、SYSCFG等三个模块中断引脚。

Algorithm

配置MM32引脚复用功能需要同时配置GPIO相关寄存器模块的电气特性(CR)寄存器和复用功能选择(AFR),为了正常工作,需要根据具体情况设置句柄两部分。

GPIOx_CR寄存器

这里的x指代A、B、… 、H,每个端口都有。CR寄存器分为高8位(CRH)和低8位(CRL),一个端口总共有16个引脚。CRH和CRL合起来的64个bit位,每4个bit对应一个引脚,但在手册中,这四个bit分为两个区域(CNFn和MODEn)进行描述。

在这里插入图片描述 本文以更清爽的方式描述:

MODE Description
0b0000 模拟输入模式(Analog Input)
0b0100 浮空输入模式(Floating Input),可用于模拟信号、数字信号
0b1000 数字上拉/下拉输入模式ODR将寄存器输出到端口,选择上拉或下拉。(Pull-Up or Pull-Down)
0b1100 未使用
0b0001 数字推拉输出模式(Digital Push-Pull Output)
0b0101 数字泄漏输出模式(Digital Open-Drain Output)
0b1001 复用功能推拉输出模式(Mux Push-Pull Output)
0b1101 复用功能开漏输出模式(Mux Open-Drain Output)

根据手册中的描述,当选择数字上拉/下拉输入模式时,用户需要通过ODR将电平控制信号写在输出端口上。GPIO_ODR当指定寄存器时GPIO引脚为GPIO输出时,控制输出引脚的电平。看来这里的上下拉配置其实是需要的GPIO模块自己的输出电路(虽然软件上没有使用)拉动自己的输入信号。这让我想起了多年前51单片机端口电路的使用,51单片机P0上所有的引脚都是泄漏的,没有输入输出配置,需要外部拉电路,默认为输出功能,但当需要使用输入功能时,必须先写1,然后读数,也用自己的输出电路拉输入。

GPIOx_AFR寄存器

GPIOx_AFR寄存器也寄存器(AFRH)和低8位(AFRL),总共64个bit位,每4位对应一个引脚。每个引脚可以配置成16个复用功能中的一个。其中可选的复用功能,就要在datasheet查阅了文档中引脚复用功能表。

这里要注意:

  • 如果要使用GPIO功能必须对应引脚AFRn写成0xF,哪怕GPIOx_CR数字输入输出模式不能在寄存器中配置引脚。下一节将讨论这种映射关系的约束。
  • 并非所有的引脚AFRn默认值是0xF。例如JTAG(还包含SWD未使用的引脚),BOOT0和ISP相关功能引脚,上电后的默认值是相应的功能引脚。因此,建议使用它GPIO功能,也例行对应AFRn值指定为0xF

GPIOx_CR & GPIOx_AFR寄存器

前面提到的只有一个引脚CR[MODE]AFR[AFRn]只有按照特定的配置组合才能工作。

关于这些特定的配置组合,请注意,不要主观地认为这是理所当然的AFR[AFRn]选选为复用功能,复用功能的信号可以正常工作。必须明确复用输出功能模式和输入模式:

  • 对于复用功能的输出信号,应指定复用推拉输出模式
  • 复用功能的输入信号应指定浮动输入模式。请注意,这种浮动输入模式不仅用于复用功能,也用于复用功能GPIO还将使用功能。
  • 复用功能的输入信号也可以指定为数字上拉/下拉输入模式。这种模式应该只支持GPIO功能。

事实上,这也是一个迷惑我,严重影响开发效率的问题。这种映射关系不是通用的,只能通过具体的特例来表现。

TIM

TIM引脚 TIM功能(AFR[AFRn] 引脚电气特性(CR[MODE])
TIM_CHn 输入捕获通道n 浮空输入模式
TIM_CHn 输出比较通道n 复用推挽输出模式
TIM_CHnN 互补输出比较通道n 复用推挽输出模式
TIM_BKIN 刹车输入 浮空输入模式
TIM_ETR 输入外部时钟 浮空输入模式

UART

UART引脚 UART功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
UART_TX 串行发送 复用推挽输出模式
UART_RX 串行接收 浮空输入模式(或数字上拉输入模式)
UART_RTS 硬件流控 复用推挽输出模式
UART_CTS 硬件流控 浮空输入模式(或数字上拉输入模式)

SPI_MASTER

SPI引脚 SPI功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
SPI_CLK 发送时钟 复用推挽输出模式
SPI_MOSI 串行发送 复用推挽输出模式
SPI_MISO 串行接收 浮空输入模式(或数字上拉输入模式)
SPI_NSS 片选 复用推挽输出模式

SPI_SLAVE

SPI引脚 SPI功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
SPI_CLK 接收时钟 浮动输入模式
SPI_MOSI 串行接收 浮空输入模式(或数字上拉输入模式)
SPI_MISO 串行发送 复用推挽输出模式
SPI_NSS 片选 浮空输入模式(或数字上/下拉输入模式)

I2C

I2C引脚 I2C功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
I2C_SCL 串行时钟 开漏复用输出模式
I2C_SDA 串行数据 开漏复用输出模式

CAN

CAN引脚 CAN功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
CAN_TX CAN发送(对接收发器) 复用推挽输出模式
CAN_RX CAN接收(对接收发器) 浮空输入模式(或数字上拉输入模式)

ADC

ADC引脚 ADC功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
ADC_CHn ADC输入通道n 模拟输入模式

FSMC

所有FSMC信号,无论实际信号的方向,全部设定为“复用推挽输出模式”。

FSMC引脚 FSMC功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
FMC_A[0…25] 数据总线信号 复用推挽输出模式
FMC_DA[0…15] 地址总线信号 复用推挽输出模式
FMC_NCS[0…3] 输出使能信号 复用推挽输出模式
FMC_NBS[0…1] 选高低半字(可为16位字,32位字) 复用推挽输出模式
FMC_NOE 输出读使能信号 复用推挽输出模式
FMC_NWE 输出写使能信号 复用推挽输出模式
FMC_NADV 当数据线也能作为地址线时,选择地址有效信号 复用推挽输出模式
FMC_NWAIT 地址有效信号 复用推挽输出模式

QSPI

所有QSPI信号,无论实际信号的方向,全部设定为“复用推挽输出模式”。

QSPI引脚 QSPI功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
QSPI_SCK 串行时钟 复用推挽输出模式
QSPI_DA[0…3] 双向数据总线 复用推挽输出模式
QSPI_NSS 设备片选线 复用推挽输出模式

DAC

DAC输出也使用“模拟输入模式”?!!,没错,是的。实际上这里应该将“模拟输入模式”,理解成为“模拟信号模式”,模拟输入和模拟输出都用这个选项。

DAC引脚 DAC功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
DAC_OUTn DAC输出信号总线 模拟输入模式

COMP

COMP引脚 DAC功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
COMP_INP COMP正极输入端 模拟输入模式
COMP_INM COMP负极输入端 模拟输入模式

SDIO

SDIO所有引脚的功能均需配置成复用推挽输出模式。

SDIO引脚 SDIO功能(AFR[AFRn]) 引脚电气特性(CR[MODE])
SDIO_CMD SDIO命令数据线 复用推挽输出模式
SDIO_CLK SDIO同步时钟线 复用推挽输出模式
SDIO_D[0 … 3] SDIO数据总线引脚 复用推挽输出模式

USB

一旦启用USB外设模块,USB相关引脚自动切换为USB功能,此时对应引脚的GPIO配置全部失效。USB功能高于GPIO的配置。例如在MM32F3270芯片上,USB功能的引脚也可以被复用成UART的功能,一旦启用USB功能,原本工作的UART引脚就会失效。

也有常见的做法,是将USB引脚单独拿出来,固定为USB功能,不做复用配置。

Practice

考虑到跟手册尽量保持一致,在SDK的驱动中,对应将复用功能的配置也纳入到gpio驱动中。

typedef enum
{ 
        
    GPIO_PinMode_In_Analog      = 0x00u,  /*!< Analog input. */
    GPIO_PinMode_In_Floating    = 0x04u,  /*!< Floating input. */
    GPIO_PinMode_In_PullDown    = 0x28u,  /*!< Pull down input. */
    GPIO_PinMode_In_PullUp      = 0x48u,  /*!< Pull up input. */
    GPIO_PinMode_Out_OpenDrain  = 0x14u,  /*!< Universal open drain output. */
    GPIO_PinMode_Out_PushPull   = 0x10u,  /*!< Universal push-pull output. */
    GPIO_PinMode_AF_OpenDrain   = 0x1Cu,  /*!< Multiplex open drain output. */
    GPIO_PinMode_AF_PushPull    = 0x18u,  /*!< Multiplex push-pull output. */
} GPIO_PinMode_Type;

在SDK的工程结构中,将配置引脚的程序统一放入pin_init.c文件中的Board_InitPins()函数中,通过GPIO_Initf()GPIO_PinAFConf()两个API配置一个引脚的复用功能。现在看来,既然这两部分的功能都放在同一个外设模块中,也可以考虑把这两个功能合并成一个API,相当于这两部分的功能,就对应PORT模块配置引脚复用功能。

void BOARD_InitPins(void)
{ 
        
    GPIO_Init_Type gpio_init;

    /* PB6 - UART1_TX. */
    gpio_init.Pins  = GPIO_PIN_6;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_7);

    /* PB7 - UART1_RX. */
    gpio_init.Pins  = GPIO_PIN_7;
    gpio_init.PinMode  = GPIO_PinMode_In_Floating;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_7);

    /* PC12 - SDIO_CLK. */
    gpio_init.Pins  = GPIO_PIN_12;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, GPIO_PIN_12, GPIO_AF_12);

    /* PD2 - SDIO_CMD. */
    gpio_init.Pins  = GPIO_PIN_2;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &gpio_init);
    GPIO_PinAFConf(GPIOD, GPIO_PIN_2, GPIO_AF_12);

    /* PC8 - SDIO_DAT0. */
    gpio_init.Pins  = GPIO_PIN_8;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, GPIO_PIN_8, GPIO_AF_12);

    /* PC9 - SDIO_DAT1. */
    gpio_init.Pins  = GPIO_PIN_9;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, GPIO_PIN_9, GPIO_AF_12);

    /* PC10 - SDIO_DAT2. */
    gpio_init.Pins  = GPIO_PIN_10;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, GPIO_PIN_10, GPIO_AF_12);

    /* PC11 - SDIO_DAT3. */
    gpio_init.Pins  = GPIO_PIN_11;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, GPIO_PIN_11, GPIO_AF_12);
}

Conclusion

。。。

标签: ckcagnl液位继电器afr

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台