最近在调试STM32的I2S,偶然发现其GPIO的AF配置有问题,进一步追踪发现问题不那么简单,具体描述如下:
1. 从GPIO的管脚结构图中我们得知,如果启用GPIO_Mode_AF_PP的设置,该管脚的电平将被内部电平强制推拉,因此这种状态不可以用于输入功能,除了功能可能不正常外,甚至有拉坏自己的管脚以及外设备管脚的危险,当然长期工作一定是不可能的。
2. 看到我以前的程序里面使用SPI的管脚设置是这样的, GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
显然把MISO输入脚配置为GPIO_Mode_AF_PP,吓得我一声冷汗。这个代码使用了N多年生产了N多产品,都带有严重的问题出厂了?
3.回头想追踪这个配置方法的来源,大家都是STM的学生,原始来源毋庸置疑是谁,关键是STM对这个问题有没有认识?
我的代码来源于2009年的V3.00的代码库。
找到2011年出的V3.50代码库,找到SPI部分发现人家已经改了(中间的版本没有找到,大家有兴趣可以追一下从那时开始改的):
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Confugure MISO pin as Input Floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
但是同一库内的I2S例程中,还是把输入按照GPIO_Mode_AF_PP配置:
(I2S_SPI_I2S_Switch SPI_I2S_Switch example,I2S2 is configured as master transmitter and I2S3 as slave receiver)
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef USE_STM3210E_EVAL
/* Disable the JTAG interface and enable the SWJ interface
This operation is not necessary for Connectivity Line devices since
SPI3 I/Os can be remapped on other GPIO pins */
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
#endif /* USE_STM3210E_EVAL */
/* Configure SPI2 pins: CK, WS and SD ---------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#ifdef USE_STM3210C_EVAL
/* Remap SPI3 on PC10-PC11-PC12-PA4 GPIO pins ------------------------*/
GPIO_PinRemapConfig(GPIO_Remap_SPI3, ENABLE);
/* Configure SPI3 pins: CK and SD ------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_12;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure SPI3 pins: WS -------------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#elif defined (USE_STM3210E_EVAL)
/* Configure SPI3 pins: CK and SD ------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure SPI3 pins: WS -------------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif /* USE_STM3210C_EVAL */
}
4. 疑问: 从STM的例程有改正来看,1的观点是正确的。但是为什么错误的配置不出错,而且长期工作没有问题呢?难道STM给我们的GPIO示意图不是那么回事?
|