为什么STM32中SPI的MISO引脚设置成复用推挽输出原子哥这个MISO,方向由SPI硬件控制,所以设置为复用推挽输出,也是可以的

原子论坛:今天看了一下战舰开发板试验23的SPI实验,发现GPIO_PIN_14口,也就是SPI的MISO口,实验中设置的复用推挽输出,而查了中文参考手册,手册里面写的是在主模式下,MISO引脚应该设置成浮空或者带上拉输入才对,我把实验代码下载到了开发板,测试又是正常的,这个好奇怪???另外我还发现一个现象,MISO这个引脚就算你不对这个IO口进行设置(也就是说:不设置MISO引脚的GPIO_InitStructure.GPIO_Pin这个参数,也不设置初始的高低电平状态,发现传输也是正常。有人能解释一下这两种情况下为什么还能正常工作吗?
void SPI2_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能 
 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB

  GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
SPI_Cmd(SPI2, ENABLE); //使能SPI外设

SPI2_ReadWriteByte(0xff);//启动传输  
 

 

在复用SPI总线时,必须先设置总线端口。读取其他ARM芯片(如NXP)一般很容易看出芯片的设置是否正确。不过对于STM32就容易让人迷惑了。例如,我们在使用SPI总线进行通信时,可以这样设置:

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     // 复用的推挽输出

       恐怕大家对MISO端口的设置就会产生疑惑了,MISO不是应该设置成为输入端口(GPIO_Mode_IN_FLOATING)才行的吗?

      答题是肯定的,对于STM32的这一类管脚来说(如USART_RX)即可以设置成为输入模式,也可以设置成为复用的推挽输出。其工作都是正常的,不过建议大家还是设置成为输入端口的好,容易理解。

      具体产生这一问题的原因是:从功能上来说,MISO应该配置为输入模式才对,但为什么也可以配置为GPIO_Mode_AF_PP?请看下面的GPIO复用功能配置框图。当一个GPIO端口配置为GPIO_Mode_AF_PP是,这个端口的内部结构框图如下:图中可以看到,片上外设的复用功能输出信号会连接到输出控制电路,然后在端口上产生输出信号。但是在芯片内部,MISO是SPI模块的输入引脚,而不是输出引脚,也就是说图中的"复用功能输出信号"根本不存在,因此"输出控制电路"不能对外产生输出信号。而另一方面看,即使在GPIO_Mode_AF_PP模式下,复用功能输入信号却与外部引脚之间相互连接,既MISO得到了外部信号的电平,实现了输入的功能。

http://www.openedv.com/forum.php?mod=viewthread&tid=21805&highlight=MISO

GPIO(通用输入/输出)的几种工作模式: 1. **推挽输出**[^1]:这种模式下,GPIO引脚可以驱动电路直接到逻辑高(Vcc)或低(GND),通过两个互补的MOSFET实现,使得信号具有较强的驱动能力,适合于需要强电流驱动的场合。 2. **开漏输出**:在这种模式下,GPIO不会主动维持一个电压极性,而是当被外部拉低时,输出低电平;当无外部拉低时,它呈现高阻态,即不向负载提供电源,仅作为连接其他电路的一个点。这对于需要与其他电路共地的情况非常有用。 3. **复用推挽输出**:这是针对某些微控制器设计的,其一些GPIO引脚不仅可用于基本的推挽输出,还可以通过配置复用功能,用于高级接口,如SPI、I2C或USART等,但仍然保留了推挽输出的能力。 4. **复用开漏输出**:与复用推挽类似,这些GPIO可以在保留其基础功能的同时,通过外设控制转换为开漏模式,以支持特定接口的线驱动需求。 举例来说,如果你有一个GPIO引脚设置复用开漏输出,你可以这样操作: ```python # 假设我们有GPIO Pin X配置复用输出 pin_x = GPIO.setup(X, GPIO.OUT | GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # 当需要驱动接口时 if pin_x.value == GPIO.HIGH: # 推挽模式,直接驱动负载 GPIO.output(pin_x, GPIO.LOW) else: # 外设控制下的开漏模式,保持高阻态 pass # 当需要使用接口时,比如SPI/I2C spi.begin() spi.transfer(data) spi.end() ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值