1、問題背景
近前,使用STM32F4 HAL庫的SPI讀取MPU6500出現異常。
現象:讀取ID失敗,返回0,以為硬件焊接問題,各種排查,最后為了示波器測試方便,把讀取ID的函數放到While(1)里,反復的讀然后抓波形,奇跡出現了,第一次讀取出現錯誤,后面的都返回了正常的ID號。既然問題已經清楚,能夠反復重現,那么排查起來也就容易多了,為了找到這個問題,花費了1天的時間,搞得都毛了,真是服了自己,之前想過反復讀抓波形,但是不想改代碼,每次都點擊復位然后再抓波形,竟然完美的錯過了后面的正常數據。
硬件連接如下:
/**SPI1 GPIO Configuration PA15 ------> SPI1_NSS PB3 ------> SPI1_SCK PB4 ------> SPI1_MISO PB5 ------> SPI1_MOSI */
2、解決之路
根據手冊MPU6500設備ID寄存器WHO AM I, 地址0x75,默認值0x70。 第1次讀取的波形。MOSI輸入地址:0x75正確,但是MISO設備沒有返回數據。
第2次讀取的波形。MOSI輸入地址:0x75正確,MISO設備返回數據0x70,一切正常。
對比2個圖,發現第一次讀取CLK為低,並不是高電平,明顯不符合datasheet的時序圖規定。
查看初始化,發現所有IO都是NOPULL模式,改為GPIO_PULLUP模式后所有讀取都正常。
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訪問正常。