SylixOS 基於STM32平臺的GPIO模仿I2C總線的驅動開發流程
阿新 • • 發佈:2018-02-27
STM32 GPIO模仿I2C 1.概述
本文檔以STM32F767平臺為例,詳細介紹SylixOS上GPIO模仿I2C總線的驅動開發流程。
2.初始化
GPIO模仿的I2C總線的初始化,實際上是I2C總線的SDA和SCL的GPIO管腳初始化。初始化流程如圖 2.1所示。
圖 2.1 I2C初始化流程圖
代碼實現,如程序清單 2.1所示。I2C總線的SDA和SCL兩個GPIO管腳的GPIO速度要設置成快速模式,輸出模式需要設置成推挽輸出模式。
程序清單 2.1 I2C初始化代碼
/* * 申請 I2C 1 通道的 SCL 的 GPIO */ if (ERROR_NONE != API_GpioRequest(I2C1_CHANNEL_SCL, I2C1_SCL_GPIO_NAME)) { return (PX_ERROR); } /* * 設置上拉 */ if (ERROR_NONE != API_GpioSetPull(I2C1_CHANNEL_SCL, GPIO_PUPD_PU)) { return (PX_ERROR); } /* * 設置為推挽輸出模式,且 GPIO 速度為快速 */ if (ERROR_NONE != API_GpioDirectionOutput(I2C1_CHANNEL_SCL, (GPIO_SPEED_SET | GPIO_OTYPE_SET | LW_GPIOF_INIT_HIGH))) { return (PX_ERROR); } /* * 申請 I2C 1 通道的 SDA 的 GPIO */ if (ERROR_NONE != API_GpioRequest(I2C1_CHANNEL_SDA, I2C1_SDA_GPIO_NAME)) { return (PX_ERROR); } if (ERROR_NONE != API_GpioSetPull(I2C1_CHANNEL_SDA, GPIO_PUPD_PU)) { return (PX_ERROR); } if (ERROR_NONE != API_GpioDirectionOutput(I2C1_CHANNEL_SDA, (GPIO_SPEED_SET | GPIO_OTYPE_SET | LW_GPIOF_INIT_HIGH))) { return (PX_ERROR); }
3.傳輸流程
GPIO模擬I2C總線驅動和普通的I2C總線驅動的最大區別是普通的I2C總線驅動的數據傳輸只要將要傳輸的數據寫入寄存器即可,而GPIO模擬I2C總線驅動的數據傳輸是直接通過GPIO管腳將電平拉高拉低(拉高是1,拉低是0)傳輸數據。
3.1寫數據流程
如程序清單 3.1所示,I2C的寫數據流程如下:
主設備發送開始信號;
主設備發送7位從設備地址和1位寫操作位;
從設備發送應答信號;
主設備發送要寫的8位從設備內部地址;
從設備發送應答信號;
主設備開始對從設備寫操作;
主設備發送結束信號。
程序清單 3.1 I2C的寫數據流程
static INT __i2cXferWrite (UINT uiChannel, PLW_I2C_MESSAGE pI2cMsg, INT iLength) { INT iIndex; __i2cStart(uiChannel); /* 發送開始信號 */ /* * 發送 7 位器件地址和 1 位寫操作位 */ __i2cSendByte((pI2cMsg->I2CMSG_usAddr & I2C_ADDR_MASK), uiChannel); if (__i2cWaitAck(uiChannel)) { /* 等待設備的 ACK 信號 */ return (PX_ERROR); } /* * 發送要寫的設備的內部地址 */ __i2cSendByte(((pI2cMsg->I2CMSG_usAddr) & I2C_INTER_ADDR_MASK), uiChannel); if (__i2cWaitAck(uiChannel)) { /* 等待設備的 ACK 信號 */ return (PX_ERROR); } for (iIndex = 0; iIndex < iLength; iIndex++) { __i2cSendByte(*(pI2cMsg->I2CMSG_pucBuffer)++, uiChannel); /* 發送字節 */ if (__i2cWaitAck(uiChannel)) { /* 等待設備的 ACK 信號 */ return (PX_ERROR); } } __i2cStop(uiChannel); /* 產生一個停止信號 */ udelay(I2C_WRITE_BYTE_DELAY); return (ERROR_NONE); }
3.2讀數據流程
如程序清單 3.2所示,I2C的讀數據流程如下:
寫模式,主設備發送開始信號;
主設備發送7位從設備地址和1位寫操作位;
從設備發送應答信號;
主設備發送要寫的8位從設備內部地址;
從設備發送應答信號;
進入讀取模式,設備再次發送開始信號;
主設備發送7位從設備地址和1位讀操作位;
從設備發送應答信號;
主設備開始對從設備讀操作;
主設備發送結束信號。
程序清單 3.2 I2C讀數據流程
static INT __i2cXferRead (UINT uiChannel, PLW_I2C_MESSAGE pI2cMsg, INT iLength) { INT iIndex; __i2cStart(uiChannel); /* 發送開始信號 */ /* * 發送 7 位器件地址和 1 位寫操作位,(I2CMSG_usAddr 中的 9-15 位為器件地址) */ __i2cSendByte(((pI2cMsg->I2CMSG_usAddr >> 8) & I2C_ADDR_MASK), uiChannel); if (__i2cWaitAck(uiChannel)) { /* 等待設備的 ACK 信號 */ return (PX_ERROR); } /* * 發送要讀的設備的內部地址 */ __i2cSendByte(((pI2cMsg->I2CMSG_usAddr) & I2C_INTER_ADDR_MASK), uiChannel); if (__i2cWaitAck(uiChannel)) { /* 等待設備的 ACK 信號 */ return (PX_ERROR); } /* * 進入讀取模式 */ __i2cStart(uiChannel); /* 發送開始信號 */ /* * 發送 7 位器件地址和 1 位讀操作位,(I2CMSG_usAddr 中的 8-15 位為器件地址和讀寫位) */ __i2cSendByte(((pI2cMsg->I2CMSG_usAddr >> 8) & I2C_ADDR_MASK) | LW_I2C_M_RD, uiChannel); if (__i2cWaitAck(uiChannel)) { /* 等待設備的 ACK 信號 */ return (PX_ERROR); } for (iIndex = 0; iIndex < iLength - 1; iIndex++) { /* * 讀取設備發來的 1 個字節數據 */ *(pI2cMsg->I2CMSG_pucBuffer)++ = __i2cReadByte(I2C_ACK_SEND, uiChannel); } *(pI2cMsg->I2CMSG_pucBuffer) = __i2cReadByte(I2C_NACK_SEND, uiChannel); __i2cStop(uiChannel); /* 產生停止信號 */ return (ERROR_NONE); }
SylixOS 基於STM32平臺的GPIO模仿I2C總線的驅動開發流程