一、問題背景函數
近前,使用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訪問正常。硬件