一、问题背景函数
近前,使用STM32F4 HAL库的SPI读取MPU6500出现异常。 测试
现象:读取ID失败,返回0,觉得硬件焊接问题,各类排查,最后为了示波器测试方便,把读取ID的函数放到While(1)里,反复的读而后抓波形,奇迹出现了,第一次读取出现错误,后面的都返回了正常的ID号。既然问题已经清楚,可以反复重现,那么排查起来也就容易多了,为了找到这个问题,花费了1天的时间,搞得都毛了,真是服了本身,以前想过反复读抓波形,可是不想改代码,每次都点击复位而后再抓波形,居然完美的错过了后面的正常数据。spa
硬件链接以下:3d
/**SPI1 GPIO Configuration PA15 ------> SPI1_NSS PB3 ------> SPI1_SCK PB4 ------> SPI1_MISO PB5 ------> SPI1_MOSI */
二、解决之路 code
根据手册MPU6500设备ID寄存器WHO AM I, 地址0x75,默认值0x70。 第1次读取的波形。MOSI输入地址:0x75正确,可是MISO设备没有返回数据。blog
第2次读取的波形。MOSI输入地址:0x75正确,MISO设备返回数据0x70,一切正常。it
对比2个图,发现第一次读取CLK为低,并非高电平,明显不符合datasheet的时序图规定。io
查看初始化,发现全部IO都是NOPULL模式,改成GPIO_PULLUP模式后全部读取都正常。class
1 __HAL_RCC_GPIOB_CLK_ENABLE(); 2 /**SPI1 GPIO Configuration 3 PB3 ------> SPI1_SCK 4 PB4 ------> SPI1_MISO 5 PB5 ------> SPI1_MOSI 6 */
7 GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5; 8 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 9 GPIO_InitStruct.Pull = GPIO_NOPULL; 10 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 11 GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; 12 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
可是出现新的问题,MOSI平时都是低电平,一旦强行拉高,每次发送地址时候就会出现一个边低的脉冲,而后再次拉高。因此改成只把SCK设置为GPIO_PULLUP模式,其余的不变,波形正常。 至此,MPU6500经过SPI访问正常。硬件