博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SylixOS 基于STM32平台的GPIO模仿I2C总线的驱动开发流程
阅读量:6939 次
发布时间:2019-06-27

本文共 5306 字,大约阅读时间需要 17 分钟。

hot3.png

  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)传输数据。

  4. 写数据流程

    如程序清单 3.1所示,I2C的写数据流程如下:

    1. 主设备发送开始信号;

    2. 主设备发送7位从设备地址和1位写操作位;

    3. 从设备发送应答信号;

    4. 主设备发送要写的8位从设备内部地址;

    5. 从设备发送应答信号;

    6. 主设备开始对从设备写操作;

    7. 主设备发送结束信号。

    程序清单 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 信号         */        _DebugHandle(__ERRORMESSAGE_LEVEL, "__i2cXferWrite(): Timeout to wait ack!\r\n");        return  (PX_ERROR);    }    /*     *  发送要读的设备的内部地址     */    __i2cSendByte(((pI2cMsg->I2CMSG_usAddr) & I2C_INTER_ADDR_MASK), uiChannel);    if (__i2cWaitAck(uiChannel)) {                                      /*  等待设备的 ACK 信号         */        _DebugHandle(__ERRORMESSAGE_LEVEL, "__i2cXferWrite(): Timeout to wait ack!\r\n");        return  (PX_ERROR);    }    for (iIndex = 0; iIndex < iLength; iIndex++) {        __i2cSendByte(*(pI2cMsg->I2CMSG_pucBuffer)++, uiChannel);       /*  发送字节                    */        if (__i2cWaitAck(uiChannel)) {                                  /*  等待设备的 ACK 信号         */            _DebugHandle(__ERRORMESSAGE_LEVEL, "__i2cXferWrite(): Timeout to wait ack!\r\n");            return  (PX_ERROR);        }    }    __i2cStop(uiChannel);                                               /*  产生一个停止信号            */    udelay(I2C_WRITE_BYTE_DELAY);    return (ERROR_NONE);}
  5. 读数据流程

    如程序清单 3.2所示,I2C的读数据流程如下:

    1. 写模式,主设备发送开始信号;

    1. 主设备发送7位从设备地址和1位写操作位;

    2. 从设备发送应答信号;

    3. 主设备发送要写的8位从设备内部地址;

    4. 从设备发送应答信号;

    5. 进入读取模式,设备再次发送开始信号;

    6. 主设备发送7位从设备地址和1位读操作位;

    7. 从设备发送应答信号;

    8. 主设备开始对从设备读操作;

    9. 主设备发送结束信号。

    程序清单 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 信号         */        _DebugHandle(__ERRORMESSAGE_LEVEL, "__i2cXferWrite(): Timeout to wait ack!\r\n");        return  (PX_ERROR);    }    /*     *  发送要读的设备的内部地址     */    __i2cSendByte(((pI2cMsg->I2CMSG_usAddr) & I2C_INTER_ADDR_MASK), uiChannel);    if (__i2cWaitAck(uiChannel)) {                                      /*  等待设备的 ACK 信号         */        _DebugHandle(__ERRORMESSAGE_LEVEL, "__i2cXferWrite(): Timeout to wait ack!\r\n");        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 信号         */        _DebugHandle(__ERRORMESSAGE_LEVEL, "__i2cXferWrite(): Timeout to wait ack!\r\n");        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);}

转载于:https://my.oschina.net/u/3249576/blog/1625162

你可能感兴趣的文章
2019年大数据发展将走向何方
查看>>
中国六个漂亮的古镇风景名胜区网站欣赏
查看>>
set IDENTITY_INSERT on 和 off 的设置
查看>>
javascript 基础4
查看>>
HTTPS背后的加密算法
查看>>
VMware虚拟机清除登录密码
查看>>
中国禁止电视剧插播广告 营销商受打击
查看>>
TCP连接建立和终止及TCP状态转换
查看>>
据报道微软将从明年一月份起推行Windows RT平板发行许可政策
查看>>
Linux权限命令之umask和mktemp
查看>>
objective c:循环引用
查看>>
计算label的高度:boundingRectWithSize的使用
查看>>
我的友情链接
查看>>
shell脚本
查看>>
linux命令学习(30)-parted
查看>>
SSHD连接操作
查看>>
foundation-datepicker-1.5.6 的使用
查看>>
HTML5应用与原生应用之间的差异
查看>>
写更好的代码,还是写更少的代码?
查看>>
行如风 Angular 初识5
查看>>