对于STM32 GPIO模式不理解造成的问题解释

来源:互联网 发布:mac book air 11寸 编辑:程序博客网 时间:2024/06/06 12:29

今天在编写Flash的程序时候,在最后,所有的程序都已经编写完成,经过测试,没有问题。接下来就是整理程序,自己将一些函数封装,可以便于自己以后移植,但是问题就出现在了这儿。

我在封装的过程中,突然发现自己如果将SPI模式初始化函数放置在 CS引脚初始化后面,接下来直接读取 Flash芯片ID的时候使用Jlink读取的数据就不能显示正常,显示数据为0xFFFF,但是,如果我将SPI模式初始化函数放置在 CS引脚初始化前面,整个程序运行是正常的。

真的是百思不得其解,我当时在想,不应该是CS初始化的影响,但是自己真的是没找见问题,最后,就到21IC上面去求助,当时我写完问题之后,接下来做什么?  接着自己找问题呗,还能做什么。

当时我又重新阅读我写的程序,突然发现我好像在初始化CS引脚的时候,没有设置输出速率(当时的我是这么认为 端口x的模式位的),唉,那就初始化呗,结果我初始化之后,我再将SPI模式初始化函数放置在 CS引脚初始化后面。结果程序正常运行!

当时就傻眼了,自己觉的这个输出速率不应该影响这么大吧,自己查找数据手册,仔细阅读关于GPIO设置这块的资料。结果才发现,原来自己以前真的是想错了。

下面上图,数据手册中关于GPIO模式初始化函数的说明:


看到这张表的时候我就知道自己是错了,原来,这个MODE是GPIO的输出模式位,只有选择了这个位,才能确定GPIO的输入输出特性。只有选择为输出模式,才能接下来配置为推挽、开漏、推挽复用、开漏复用模式。同样,配置为输入模式,才能配置为模拟、浮空、上拉、下拉输入模式。

STM32在上电复位之后,默认的输出模式时 00(也就是输入模式),所以,我上面没有设置CS引脚的输出模式,才造成了CS引脚不起作用。

在仔细阅读关于STM32库函数实现方法之后,我发现,STM32库函数中对于GPIO使用的是一种更为精妙的方法。

先上源码:首先是看一下关于STM32 GPIO结构体内部:

分为三个结构体变量:GPIO_Pin,GPIO_Speed,GPIO_Mode。

其中,GPIO_Speed和GPIO_Mode同时也是一个结构体。分别初始化GPIO引脚的输出速率和模式。

接下来,看一下GPIO_Speed可以选择的取值,明显发现这个的参数的设置,就是关于STM32 GPIO引脚的输出速率设置。

typedef enum

  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz, 
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

接下来,看一下GPIO_Mode的取值:

typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;

在阅读数据手册的时候发现,如果是直接才做寄存器,对于GPIO模式的控制位只有2位,所以,是不会出现0x14,0x10,0x1C,0x18这些取值的。这里,如果想知道为什么库函数中会这样的设置,就必须接着看GPIO_Init函数。

  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
  { 
    /* Check the parameters */
    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
    /* Output mode */
    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
  }

对于GPIO_Init函数,传递进来的参数,先通过mode参数,设置了GPIO模式参数,再接着根据传递的mode的值,判断此GPIO设置为输入模式还是输出模式,如果是输出模式,才会进行设置GPIO的速率,如果是输入模式,忽略掉速率的设置。


0 0
原创粉丝点击