1. 程式人生 > >SylixOS 基於STM32平臺的GPIO模仿I2C總線的驅動開發流程

SylixOS 基於STM32平臺的GPIO模仿I2C總線的驅動開發流程

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總線的驅動開發流程