背景
最近,在使用 STM32F030C8T6 做 I2C Slave 設備接口。在網上查了好多的資料,使用 STM32 硬體 I2C 的例程少之又少,對 STM32 硬體 I2C 的批判巨多,只能硬著頭皮,自己一步一步摸索。
實際上,在這次硬體 I2C 調試之前,其實我已經通過 IO 模擬的方式實現了 I2C,但速率僅能實現 Standard-mode(up to 100 kbit/s)。對於 Fast-mode(up to 400 kbit/s),IO 模擬方式簡直是無能為力。同時,由於 IO 模擬 I2C 時並沒有充分的考慮架構,最終的實現結果是功能單一,客戶滿意度不好。
I2C 實現方式
經過多次糾結和考慮,我決定採用Dummy Write + Register 方式進行 I2C 通訊。這樣的好處,在於用戶使用方便,對於後續的功能增加或需求變化,對客戶接口完全無影響,只需要修改寄存器列表就 OK。這個也是參考了幾個 I2C接口的晶片決定的。
Dummy Write
Dummy Write 要求 Master 訪問 Slave 時,必須發送兩次的從機地址。同時對於 STM32 HAL 的 Slave Receive 或 Write ,都必須指定長度,因此,在 第一次寫操作中, Master 發送了 寄存器地址和寫入數據的長度。時序圖如下圖所示。
程序源碼位於:https://github.com/CherryXiuHuaWoo/STM32F030C8-IIC-Slave 。
記錄各種坑爹
第 1 次調試結果:總線掛了
第一次 Master Write 時,通訊完成。
第二次 Master Write 時,在 Address + Write 後, SDA 被置為 Low,導致總線被佔用,無法再繼續通訊。
第 2 次調試結果:基本調通了 Write/Read
通過在每次地址中斷回調函數HAL_I2C_AddrCallback處理完成後,增加 HAL_I2C_EnableListen_IT(&hi2c1),不再出現第一次調試問題,可反覆通訊。
Bug 分析:
通過查看調用HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode) 的代碼部分。
發現,在I2C_ITAddrCplt 函數中,在調用 HAL_I2C_AddrCallback 回調函數前,有調用 I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT)把中斷關了!!!!!!之後也沒有恢復中斷,所以用戶必須自行把中斷打開!!!!!!
第 3 次調試:DUMMYWrite 後,總線掛了
這個總線掛了是我還沒有編寫DuMMYWrite後的處理代碼所導致。
第 4 次調試:DUMMYWrtie 讀寫正常
讀時序:
寫時序:
推薦閱讀
CUBE配置CAN參數配置配置引腳PD0 PD1為CAN功能。在Connectivity->CAN1中勾選Master Mode。在ParameterSettings中配置:NVIC Settings中勾選RX0中斷在NVIC中配置CAN1中斷組為2 2修改代碼添加bsp_can.c文件,代碼如下:#include "bsp_can.h" #include "main.h"#define CAN1FIFO CAN_RX_FIFO0#define CAN1FIF1 CAN_RX_FIFO1CAN_TxHeaderTypeDef TxMeg;CAN_RxHeaderTypeDef
發表於 2020-05-14
BSP_W25Qx_WriteEnable(void){ uint8_t cmd[] = {WRITE_ENABLE_CMD}; uint32_t tickstart = HAL_GetTick(); /*Select the FLASH: Chip Select low */ W25Qx_Enable(); /* Send the read ID command */ HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE); /*Deselect the FLASH: Chip Select high */ W25Qx_Disable(); /* Wait the end of
發表於 2020-05-14
-------------------------------------------------------------*//* USER CODE BEGIN PV *//* Private variables ---------------------------------------------------------*//* USER CODE END PV *//** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @brief Usb device. * @{ *//** @defgroup USBD_STORAGE * @brief Usb mass storage device module * @{ *//** @defgroup
發表於 2020-05-14
運行環境Windows10STM32CubeMX___Version 5.0.0Keil5(MDK5)___Version 5.15簡介本例程主要講解如何通過串口發送數據和重定向printfSTM32CubeMx基本配置基礎配置過程請參考 STM32CubeMx(Keil5)開發之路—1配置第一個項目STM32CubeMx USART1配置1——點擊USART1進行設置2——模式選擇Asynchronous異步傳輸3——可以看到右邊自動出現了Tx和Rx4——可以自行設置波特率,停止位,校驗位等參數代碼修改1——選擇main.c文件2——在USER CODE中添加如下代碼,重定向printfint fputc(int ch
發表於 2020-05-13
開發環境:開發板:正點原子F407探索者代碼生成工具:STM32CubeMX v5.4.0IDE: eclipse + ac6工具鏈實現功能:單片機可以通過usb接口和EC20的AT指令虛擬串口通訊。為了方便測試,配置串口2,將 模塊->單片機 方向的數據通過串口2發送到電腦,將電腦通過串口工具發送到單片機的數據,轉發給模塊。開始1、使用STM32CubeMX配置工程,生成基礎代碼1.1.1 配置晶振1.1.2 配置時鐘1.2.1 配置串口21.2.2 配置DMA1.2.3 開串口中斷1.3.1 配置USB Host_Only,不使用VBUS SOF1.3.2 在Middleware中選擇USB_HOST將Class for
發表於 2020-05-13
NVIC(嵌套向量中斷控制器)NVIC就是控制中斷響應的。主要由三個參數,一個是中斷使能,一個是搶佔優先級,還有一個就是響應優先級。(優先級數值越小,優先級別越高)中斷使能:很好理解,就是是否開啟中斷,如果開啟中斷,則滿足中斷觸發條件時程序會跳到中斷服務程序運行,否則不響應中斷主程序繼續運行。搶佔優先級:是用來判斷一個中斷是否可以打斷另外一個中斷的中斷服務程序搶先運行。例如A中斷觸發,正在運行A中斷的服務程序,此時B中斷也觸發,如果B中斷的搶佔優先級比A的高,則程序會打斷A的中斷服務程序,去運行B的中斷服務程序,即中斷嵌套。等B的中斷服務程序運行完後繼續運行A的中斷服務程序。如果B的搶佔優先級沒有高過A的搶佔優先級,則程序不會打斷A
發表於 2020-05-13