OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9897|回复: 18

一种通用性IIC接口的实现

[复制链接]

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
566
金钱
566
注册时间
2016-9-28
在线时间
158 小时
发表于 2017-4-22 10:47:41 | 显示全部楼层 |阅读模式
本帖最后由 mftang2016 于 2017-4-22 10:55 编辑

在工程设计中,有时需要使用IO模拟多个iic接口, 而IIC接口的模拟和硬件关系很大,怎么能使用一种方法将硬件层完全抽象出来呢?这篇文章就来解决这个问题。
Step 1: 建立一个和IIC硬件相关的结构体

typedef struct _i2c {
        void     (*IIC_InitPort)( void );     //硬件驱动初始化
        void     (*IIC_SDA_H)();              //SDA置高
        void     (*IIC_SDA_L)();              //SDA置低
        void     (*IIC_SCL_H)();             //SCL置高
        void     (*IIC_SCL_L)();              //SCL置高
        INT8U    (*IIC_READ)();          //读SDA
        INT8U    (*IIC_READ_SCL)();   //读SCL
} I2C;


要实现的IIC 函数如下(I2C.c 中实现):
void i2c_Start( I2C *i2c );
void i2c_Stop( I2C *i2c );
void i2c_SendByte( I2C *i2c, INT8U _ucByte);
INT8U i2c_ReadByte( I2C *i2c );
INT8U i2c_WaitAck( I2C *i2c );
void i2c_Ack( I2C *i2c );
void i2c_NAck( I2C *i2c );
INT8U i2c_CheckDevice(I2C *i2c, INT8U _Address);
具体文件头如下:
[mw_shl_code=c,true]#ifndef __I2C_H
#define __I2C_H

#define I2C_WR        0                /* 写控制bit */
#define I2C_RD        1                /* 读控制bit */

typedef struct _i2c {
        void     (*IIC_InitPort)( void );
        void     (*IIC_SDA_H)();
        void     (*IIC_SDA_L)();
        void     (*IIC_SCL_H)();
        void     (*IIC_SCL_L)();
        INT8U    (*IIC_READ)();
        INT8U    (*IIC_READ_SCL)();
} I2C;

void i2c_Start( I2C *i2c );
void i2c_Stop( I2C *i2c );
void i2c_SendByte( I2C *i2c, INT8U _ucByte);
INT8U i2c_ReadByte( I2C *i2c );
INT8U i2c_WaitAck( I2C *i2c );
void i2c_Ack( I2C *i2c );
void i2c_NAck( I2C *i2c );
INT8U i2c_CheckDevice(I2C *i2c, INT8U _Address);


#endif /*__I2C_H  */[/mw_shl_code]




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
566
金钱
566
注册时间
2016-9-28
在线时间
158 小时
 楼主| 发表于 2017-4-22 10:49:52 | 显示全部楼层
本帖最后由 mftang2016 于 2017-4-22 10:54 编辑

Step 2 I2C.c 中实现 接口函数
[mw_shl_code=c,true]/*******************************************************************************
** File name:         I2C.c
** Created by:         Mingfei Tang               
** Created date: 2017/4/19               
** Version:         V1.00                        
** Descriptions: for I2C driver
** Details:      
**------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
*******************************************************************************/
#include "includes.h"


static void i2c_Delay(void)
{
        uint8_t i;

        /* 
                CPU主频168MHz时,在内部Flash运行, MDK工程不优化。用台式示波器观测波形。
                循环次数为5时,SCL频率 = 1.78MHz (读耗时: 92ms, 读写正常,但是用示波器探头碰上就读写失败。时序接近临界)
                循环次数为10时,SCL频率 = 1.1MHz (读耗时: 138ms, 读速度: 118724B/s)
                循环次数为30时,SCL频率 = 440KHz, SCL高电平时间1.0us,SCL低电平时间1.2us
                上拉电阻选择2.2K欧时,SCL上升沿时间约0.5us,如果选4.7K欧,则上升沿约1us
                实际应用选择400KHz左右的速率即可
        */
        for (i = 0; i < 30; i++);
}

void i2c_Start( I2C *i2c )
{
        i2c->IIC_SDA_H();
        i2c->IIC_SDA_H();
        i2c->IIC_SCL_H();
        i2c_Delay();
        i2c->IIC_SDA_L();
        i2c_Delay();
        i2c->IIC_SCL_L();
        i2c_Delay();   
}


void i2c_Stop( I2C *i2c )
{
        i2c->IIC_SDA_L();
        i2c->IIC_SCL_H();
        i2c_Delay();
        i2c->IIC_SDA_H();
}

void i2c_SendByte( I2C *i2c, INT8U _ucByte)
{
        INT8U i;

        /* 先发送字节的高位bit7 */
        for (i = 0; i < 8; i++)
        {
                if (_ucByte & 0x80)
                {
                        i2c->IIC_SDA_H();
                }
                else
                {
                        i2c->IIC_SDA_L();
                }
                i2c_Delay();
                i2c->IIC_SCL_H();
                i2c_Delay();
                i2c->IIC_SCL_L();
                if (i == 7)
                {
                         i2c->IIC_SDA_H(); // 释放总线
                }
                _ucByte <<= 1;        /* 左移一个bit */
                i2c_Delay();
        }
}

INT8U i2c_ReadByte( I2C *i2c )
{
        INT8U i;
        INT8U value;

        /* 读到第1个bit为数据的bit7 */
        value = 0;
        for (i = 0; i < 8; i++)
        {
                value <<= 1;
                i2c->IIC_SCL_H();
                i2c_Delay();
               
                if ( i2c->IIC_READ() )
                {
                        value++;
                }
               
                i2c->IIC_SCL_L();
                i2c_Delay();
        }
        
        return value;
}

INT8U i2c_WaitAck( I2C *i2c )
{
        INT8U re;

        i2c->IIC_SDA_H();        /* CPU释放SDA总线 */
        i2c_Delay();
        i2c->IIC_SCL_H();        /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
        i2c_Delay();
        
        if ( i2c->IIC_READ() )        /* CPU读取SDA口线状态 */
        {
                re = 1;
        }
        else
        {
                re = 0;
        }
        i2c->IIC_SCL_L();
        i2c_Delay();
        
        return re;
}

void i2c_Ack( I2C *i2c )
{
        i2c->IIC_SDA_L();        /* CPU驱动SDA = 0 */
        i2c_Delay();
        i2c->IIC_SCL_H();        /* CPU产生1个时钟 */
        i2c_Delay();
        i2c->IIC_SCL_L();
        i2c_Delay();
        i2c->IIC_SDA_H();        /* CPU释放SDA总线 */
}

void i2c_NAck( I2C *i2c )
{
        i2c->IIC_SDA_H();        /* CPU驱动SDA = 1 */
        i2c_Delay();
        i2c->IIC_SCL_H();        /* CPU产生1个时钟 */
        i2c_Delay();
        i2c->IIC_SCL_L();
        i2c_Delay();
}

INT8U i2c_CheckDevice(I2C *i2c, INT8U _Address)
{
        INT8U ucAck;

        if ( i2c->IIC_READ() && i2c->IIC_READ_SCL())
        {
                i2c_Start( i2c );                        /* 发送启动信号 */

                /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
                i2c_SendByte( i2c, _Address | I2C_WR);
                ucAck = i2c_WaitAck( i2c );                        /* 检测设备的ACK应答 */

                i2c_Stop( i2c );                                /* 发送停止信号 */

                return ucAck;
        }
        return 1;        /* I2C总线异常 */
}



/* End of this file */[/mw_shl_code]

回复 支持 反对

使用道具 举报

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
566
金钱
566
注册时间
2016-9-28
在线时间
158 小时
 楼主| 发表于 2017-4-22 10:53:34 | 显示全部楼层
函数文件如下:
IIC.zip (1.75 KB, 下载次数: 719)
回复 支持 反对

使用道具 举报

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
566
金钱
566
注册时间
2016-9-28
在线时间
158 小时
 楼主| 发表于 2017-4-22 11:05:26 | 显示全部楼层
Step 3: 使用范例(驱动 BMP085气压传感器), 和硬件相关的代码如下:

#define GPIO_PORT_I2C                GPIOH                                /* GPIO端口 */
#define RCC_I2C_PORT                 RCC_AHB1Periph_GPIOH                /* GPIO端口时钟 */
#define I2C_SCL_PIN                        GPIO_Pin_4                        /* 连接到SCL时钟线的GPIO */
#define I2C_SDA_PIN                GPIO_Pin_5                        /* 连接到SDA数据线的GPIO */

/* 定义读写SCL和SDA的宏 */
#define I2C_SCL_1()             GPIO_PORT_I2C->BSRRL = I2C_SCL_PIN        /* SCL = 1 */
#define I2C_SCL_0()             GPIO_PORT_I2C->BSRRH = I2C_SCL_PIN        /* SCL = 0 */

#define I2C_SDA_1()             GPIO_PORT_I2C->BSRRL = I2C_SDA_PIN        /* SDA = 1 */
#define I2C_SDA_0()             GPIO_PORT_I2C->BSRRH = I2C_SDA_PIN        /* SDA = 0 */

#define I2C_SDA_READ()          ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0)        /* 读SDA口线状态 */
#define I2C_SCL_READ()          ((GPIO_PORT_I2C->IDR & I2C_SCL_PIN) != 0)        /* 读SCL口线状态 */

I2C I2C_Bmp085;
BMP085_T g_tBMP085;

static INT8U bsp_i2cRead( void )
{
    return I2C_SDA_READ();
}

static INT8U bsp_i2cReadSCL( void )
{
    return I2C_SCL_READ();
}

static void bsp_i2c_SclHigh( void )
{
    I2C_SCL_1();
}

static void bsp_i2c_SclLow( void )
{
    I2C_SCL_0();
}

static void bsp_i2c_SdaHigh( void )
{
    I2C_SDA_1();
}

static void bsp_i2c_SdaLow( void )
{
    I2C_SDA_0();
}

static void bsp_InitI2C(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_I2C_PORT, ENABLE);        /* 打开GPIO时钟 */

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                /* 设为输出口 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;                /* 设为开漏模式 */
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        /* 上下拉电阻不使能 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        /* IO口最大速度 */

    GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
    GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
}


void Bmp085_Init( void )
{
    I2C *pI2C;

    pI2C = &I2C_Bmp085;

    pI2C->IIC_InitPort = bsp_InitI2C;
    pI2C->IIC_READ = bsp_i2cRead;
    pI2C->IIC_READ_SCL = bsp_i2cReadSCL;

    pI2C->IIC_SCL_H = bsp_i2c_SclHigh;
    pI2C->IIC_SCL_L = bsp_i2c_SclLow;

    pI2C->IIC_SDA_H =  bsp_i2c_SdaHigh;
    pI2C->IIC_SDA_L =  bsp_i2c_SdaLow;

    i2c_Stop( pI2C );   /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */

    bsp_InitI2C();    //初始化IO
}



回复 支持 反对

使用道具 举报

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
566
金钱
566
注册时间
2016-9-28
在线时间
158 小时
 楼主| 发表于 2017-4-22 11:06:20 | 显示全部楼层
本帖最后由 mftang2016 于 2017-4-22 11:08 编辑

全部代码如下:
[mw_shl_code=c,true]/*******************************************************************************
** File name:         Bmp085.c
** Created by:         Mingfei Tang               
** Created date: 2017/4/19               
** Version:         V1.00                        
** Descriptions: for I2C driver
** Details:      
**------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**           安富莱STM32-V5开发板 i2c总线GPIO:
             PH4 --  I2C2_SCL
             PH5 --  I2C2_SDA
*******************************************************************************/
#include "includes.h"

#define GPIO_PORT_I2C                GPIOH                                /* GPIO端口 */
#define RCC_I2C_PORT                 RCC_AHB1Periph_GPIOH                /* GPIO端口时钟 */
#define I2C_SCL_PIN                GPIO_Pin_4                        /* 连接到SCL时钟线的GPIO */
#define I2C_SDA_PIN                GPIO_Pin_5                        /* 连接到SDA数据线的GPIO */

/* 定义读写SCL和SDA的宏 */
#define I2C_SCL_1()             GPIO_PORT_I2C->BSRRL = I2C_SCL_PIN        /* SCL = 1 */
#define I2C_SCL_0()             GPIO_PORT_I2C->BSRRH = I2C_SCL_PIN        /* SCL = 0 */

#define I2C_SDA_1()             GPIO_PORT_I2C->BSRRL = I2C_SDA_PIN        /* SDA = 1 */
#define I2C_SDA_0()             GPIO_PORT_I2C->BSRRH = I2C_SDA_PIN        /* SDA = 0 */

#define I2C_SDA_READ()          ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0)        /* 读SDA口线状态 */
#define I2C_SCL_READ()          ((GPIO_PORT_I2C->IDR & I2C_SCL_PIN) != 0)        /* 读SCL口线状态 */

I2C I2C_Bmp085;
BMP085_T g_tBMP085;

static INT8U bsp_i2cRead( void )
{
    return I2C_SDA_READ();
}

static INT8U bsp_i2cReadSCL( void )
{
    return I2C_SCL_READ();
}

static void bsp_i2c_SclHigh( void )
{
    I2C_SCL_1();
}

static void bsp_i2c_SclLow( void )
{
    I2C_SCL_0();
}

static void bsp_i2c_SdaHigh( void )
{
    I2C_SDA_1();
}

static void bsp_i2c_SdaLow( void )
{
    I2C_SDA_0();
}

static void bsp_InitI2C(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_I2C_PORT, ENABLE);        /* 打开GPIO时钟 */

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                /* 设为输出口 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;                /* 设为开漏模式 */
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        /* 上下拉电阻不使能 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        /* IO口最大速度 */

    GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
    GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
}


void Bmp085_Init( void )
{
    I2C *pI2C;
   
    pI2C = &I2C_Bmp085;
   
    pI2C->IIC_InitPort = bsp_InitI2C;
    pI2C->IIC_READ = bsp_i2cRead;
    pI2C->IIC_READ_SCL = bsp_i2cReadSCL;
   
    pI2C->IIC_SCL_H = bsp_i2c_SclHigh;
    pI2C->IIC_SCL_L = bsp_i2c_SclLow;
   
    pI2C->IIC_SDA_H =  bsp_i2c_SdaHigh;
    pI2C->IIC_SDA_L =  bsp_i2c_SdaLow;
   
    i2c_Stop( pI2C );   /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
   
    bsp_InitI2C();    //初始化IO
}

static void BMP085_WriteReg(uint8_t _ucRegAddr, uint8_t _ucRegValue)
{
      I2C *pI2C;
      
      pI2C = &I2C_Bmp085;
      
      i2c_Start( pI2C );                                /* 总线开始信号 */

      i2c_SendByte( pI2C, BMP085_SLAVE_ADDRESS);        /* 发送设备地址+写信号 */
      i2c_WaitAck( pI2C );

      i2c_SendByte(pI2C, _ucRegAddr);                        /* 发送寄存器地址 */
      i2c_WaitAck( pI2C );

      i2c_SendByte( pI2C, _ucRegValue);                /* 发送寄存器数值 */
      i2c_WaitAck( pI2C );

      i2c_Stop( pI2C );                           /* 总线停止信号 */
}

static uint16_t BMP085_Read2Bytes(uint8_t _ucRegAddr)
{
      I2C *pI2C;

      pI2C = &I2C_Bmp085;

      uint8_t ucData1;
      uint8_t ucData2;
      uint16_t usRegValue;

      i2c_Start( pI2C );                                          /* 总线开始信号 */
      i2c_SendByte( pI2C, BMP085_SLAVE_ADDRESS);                /* 发送设备地址+写信号 */
      i2c_WaitAck( pI2C );
      i2c_SendByte( pI2C, _ucRegAddr);                         /* 发送地址 */
      i2c_WaitAck( pI2C );

      i2c_Start( pI2C );                                          /* 总线开始信号 */
      i2c_SendByte( pI2C, BMP085_SLAVE_ADDRESS + 1);         /* 发送设备地址+读信号 */
      i2c_WaitAck( pI2C );

      ucData1 = i2c_ReadByte( pI2C );                              /* 读出高字节数据 */
      i2c_Ack( pI2C );

      ucData2 = i2c_ReadByte( pI2C );                             /* 读出低字节数据 */
      i2c_NAck( pI2C );
      i2c_Stop( pI2C );                                       /* 总线停止信号 */

      usRegValue = (ucData1 << 8) + ucData2;

      return usRegValue;
}


static uint32_t BMP085_Read3Bytes(uint8_t _ucRegAddr)
{
      uint8_t ucData1;
      uint8_t ucData2;
      uint8_t ucData3;
      uint32_t uiRegValue;
      I2C *pI2C;

      pI2C = &I2C_Bmp085;        

      i2c_Start( pI2C );                                          /* 总线开始信号 */
      i2c_SendByte( pI2C, BMP085_SLAVE_ADDRESS);                /* 发送设备地址+写信号 */
      i2c_WaitAck( pI2C );
      i2c_SendByte( pI2C, _ucRegAddr);                                /* 发送地址 */
      i2c_WaitAck( pI2C );

      i2c_Start( pI2C );                                          /* 总线开始信号 */
      i2c_SendByte( pI2C, BMP085_SLAVE_ADDRESS + 1);/* 发送设备地址+读信号 */
      i2c_WaitAck( pI2C );

      ucData1 = i2c_ReadByte( pI2C );                       /* 读出高字节数据 */
      i2c_Ack( pI2C );

      ucData2 = i2c_ReadByte( pI2C );                       /* 读出中间字节数据 */
      i2c_Ack( pI2C );

      ucData3 = i2c_ReadByte( pI2C );                       /* 读出最低节数据 */
      i2c_NAck( pI2C );
      i2c_Stop( pI2C );                                          /* 总线停止信号 */

      uiRegValue = (ucData1 << 16) + (ucData2 << 8) + ucData3;

      return uiRegValue;
}

static void BMP085_WaitConvert(void)
{
      if (g_tBMP085.OSS == 0)
      {
              TimeActDelayMs(6);                /* 4.5ms  7.5ms  13.5ms   25.5ms */
      }
      else if (g_tBMP085.OSS == 1)
      {
              TimeActDelayMs(9);                /* 4.5ms  7.5ms  13.5ms   25.5ms */
      }
      else if (g_tBMP085.OSS == 2)
      {
              TimeActDelayMs(15);                /* 4.5ms  7.5ms  13.5ms   25.5ms */
      }
      else if (g_tBMP085.OSS == 3)
      {
              TimeActDelayMs(27);                /* 4.5ms  7.5ms  13.5ms   25.5ms */
      }
}

void bsp_InitBMP085(void)
{
      Bmp085_Init();
      /* 读出芯片内部的校准参数(每个芯片不同,这是BOSCH出厂前校准好的数据) */
      g_tBMP085.AC1 = (int16_t)BMP085_Read2Bytes(0xAA);
      g_tBMP085.AC2 = (int16_t)BMP085_Read2Bytes(0xAC);
      g_tBMP085.AC3 = (int16_t)BMP085_Read2Bytes(0xAE);
      g_tBMP085.AC4 = (uint16_t)BMP085_Read2Bytes(0xB0);
      g_tBMP085.AC5 = (uint16_t)BMP085_Read2Bytes(0xB2);
      g_tBMP085.AC6 = (uint16_t)BMP085_Read2Bytes(0xB4);
      g_tBMP085.B1 =  (int16_t)BMP085_Read2Bytes(0xB6);
      g_tBMP085.B2 =  (int16_t)BMP085_Read2Bytes(0xB8);
      g_tBMP085.MB =  (int16_t)BMP085_Read2Bytes(0xBA);
      g_tBMP085.MC =  (int16_t)BMP085_Read2Bytes(0xBC);
      g_tBMP085.MD =  (int16_t)BMP085_Read2Bytes(0xBE);

      g_tBMP085.OSS = 0;        /* 过采样参数,0-3 */
}


void BMP085_ReadTempPress(void)
{
      long UT, X1, X2, B5, T;
      long UP, X3, B3, B6, B7, p;
      unsigned long B4;

      /* 流程见 pdf page 12 */
      /* 读温度原始值 */
      BMP085_WriteReg(0xF4, 0x2E);
      BMP085_WaitConvert();        /* 等待转换结束 */
      UT = BMP085_Read2Bytes(0xF6);

      /* 读压力原始值 */
      BMP085_WriteReg(0xF4, 0x34 + (g_tBMP085.OSS << 6));
      BMP085_WaitConvert();        /* 等待转换结束 */
      UP = BMP085_Read3Bytes(0xF6) >> (8 - g_tBMP085.OSS);

      /* 计算真实温度(单位 0.1摄氏度) */
      X1 = ((long)(UT - g_tBMP085.AC6) * g_tBMP085.AC5) >> 15;
      X2 = ((long)g_tBMP085.MC << 11) / (X1 + g_tBMP085.MD);
      B5 = X1 + X2;        /* 该系数将用于压力的温度补偿计算 */
      T = (B5 + 8) >> 4;
      g_tBMP085.Temp = T;                /* 将计算结果保存在全局变量 */

      /* 计算真实压力值(单位 Pa) */
      B6 = B5 - 4000;
      X1 = (g_tBMP085.B2 * (B6 * B6) >> 12) >> 11;
      X2 = (g_tBMP085.AC2 * B6) >> 11;
      X3 = X1 + X2;
      B3 = (((((long)g_tBMP085.AC1) * 4 + X3) << g_tBMP085.OSS) + 2) >> 2;

      X1 = (g_tBMP085.AC3 * B6) >> 13;
      X2 = (g_tBMP085.B1 * ((B6 * B6) >> 12)) >> 16;
      X3 = ((X1 + X2) + 2) >> 2;
      B4 = (g_tBMP085.AC4 * (unsigned long)(X3 + 32768)) >> 15;

      B7 = ((unsigned long)(UP - B3) * (50000 >> g_tBMP085.OSS));
      if ( B7 < 0x80000000 )
      {
              p = (B7 << 1) / B4;
      }
      else
      {
              p = (B7 / B4) << 1;
      }

      X1 = (p >> 8) * (p >> 8);
      X1 = (X1 * 3038) >> 16;
      X2 = (-7357 * p) >> 16;
      p =  p + ((X1 + X2 + 3791) >> 4);

      g_tBMP085.Press = p;                /* 将计算结果保存在全局变量 */
}



/* End of this file */
[/mw_shl_code]
Bmp085.zip (2.89 KB, 下载次数: 384)
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-4-23 14:59:36 | 显示全部楼层
大神,膜拜
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2016-4-29
在线时间
9 小时
发表于 2017-5-18 11:37:21 | 显示全部楼层
谢谢大神啦,我正好要用到,爱死你了
回复 支持 反对

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
发表于 2018-7-19 09:16:26 | 显示全部楼层
不错不错
回复 支持 反对

使用道具 举报

15

主题

109

帖子

0

精华

高级会员

Rank: 4

积分
826
金钱
826
注册时间
2016-6-28
在线时间
160 小时
发表于 2018-8-9 16:54:20 | 显示全部楼层
你好,这边SDA脚在slave设备应答或者读数据时不用考虑把IO口设置成输入模式吗?
回复 支持 反对

使用道具 举报

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
566
金钱
566
注册时间
2016-9-28
在线时间
158 小时
 楼主| 发表于 2018-8-11 08:20:08 | 显示全部楼层
zhanming1990 发表于 2018-8-9 16:54
你好,这边SDA脚在slave设备应答或者读数据时不用考虑把IO口设置成输入模式吗?

设置如下模式就不用即可:
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;                /* 设为开漏模式 */
回复 支持 反对

使用道具 举报

0

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2015-11-16
在线时间
22 小时
发表于 2018-8-16 16:19:54 | 显示全部楼层
有才华 ,用c实现了C++类似的功能,把数据和操作有效的通过结构体搞定 ,聪明啊
回复 支持 反对

使用道具 举报

10

主题

80

帖子

0

精华

高级会员

Rank: 4

积分
514
金钱
514
注册时间
2017-5-21
在线时间
82 小时
发表于 2018-8-26 00:31:22 | 显示全部楼层
厉害呀,楼主很强
回复 支持 反对

使用道具 举报

6

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2018-8-23
在线时间
12 小时
发表于 2018-10-17 22:35:57 | 显示全部楼层
老哥,请问你一个问题,比如我I2C总线上挂了一个24C02,在主机等待应答阶段,我看你的代码和原子的代码都是主机释放总线后等待从机的信号,下边是你的代码
123.jpg 这个时候的应答信号时24C02自己处理之后控制了一下SDA吗,是不是这个器件的I2C模块可以自动处理并给出反馈,不需要再进行编程?(貌似这个器件也没法编程)

请不吝赐教
回复 支持 反对

使用道具 举报

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
566
金钱
566
注册时间
2016-9-28
在线时间
158 小时
 楼主| 发表于 2018-10-20 22:50:42 | 显示全部楼层
GAOSIY 发表于 2018-10-17 22:35
老哥,请问你一个问题,比如我I2C总线上挂了一个24C02,在主机等待应答阶段,我看你的代码和原子的代码都是 ...

注释上有啊,等待从设备应答信号,具体还是参考i2c顺序理解代码吧
回复 支持 反对

使用道具 举报

19

主题

97

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
313
金钱
313
注册时间
2017-9-5
在线时间
78 小时
发表于 2019-1-29 11:52:45 | 显示全部楼层

厉害呀,楼主很强
回复 支持 反对

使用道具 举报

0

主题

32

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
379
金钱
379
注册时间
2017-1-4
在线时间
129 小时
发表于 2019-4-15 13:47:12 | 显示全部楼层
这个好,我试试去
回复 支持 反对

使用道具 举报

18

主题

155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3919
金钱
3919
注册时间
2016-7-8
在线时间
821 小时
发表于 2020-1-21 17:17:01 | 显示全部楼层
你好,请问如果我需要模拟6个IIC,是不是需要定义6个这样的宏定义

Step 3: 使用范例(驱动 BMP085气压传感器), 和硬件相关的代码如下:

#define GPIO_PORT_I2C                GPIOH                                /* GPIO端口 */
#define RCC_I2C_PORT                 RCC_AHB1Periph_GPIOH                /* GPIO端口时钟 */
#define I2C_SCL_PIN                        GPIO_Pin_4                        /* 连接到SCL时钟线的GPIO */
#define I2C_SDA_PIN                GPIO_Pin_5                        /* 连接到SDA数据线的GPIO */

/* 定义读写SCL和SDA的宏 */
#define I2C_SCL_1()             GPIO_PORT_I2C->BSRRL = I2C_SCL_PIN        /* SCL = 1 */
#define I2C_SCL_0()             GPIO_PORT_I2C->BSRRH = I2C_SCL_PIN        /* SCL = 0 */

#define I2C_SDA_1()             GPIO_PORT_I2C->BSRRL = I2C_SDA_PIN        /* SDA = 1 */
#define I2C_SDA_0()             GPIO_PORT_I2C->BSRRH = I2C_SDA_PIN        /* SDA = 0 */

#define I2C_SDA_READ()          ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0)        /* 读SDA口线状态 */
#define I2C_SCL_READ()          ((GPIO_PORT_I2C->IDR & I2C_SCL_PIN) != 0)        /* 读SCL口线状态 */
回复 支持 反对

使用道具 举报

18

主题

155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3919
金钱
3919
注册时间
2016-7-8
在线时间
821 小时
发表于 2020-1-21 17:21:06 | 显示全部楼层
楼主,每个IIC的需要分别写出了对应的这几个函数,是吗
static INT8U bsp_i2cRead( void )
{
    return I2C_SDA_READ();
}

static INT8U bsp_i2cReadSCL( void )
{
    return I2C_SCL_READ();
}

static void bsp_i2c_SclHigh( void )
{
    I2C_SCL_1();
}

static void bsp_i2c_SclLow( void )
{
    I2C_SCL_0();
}

static void bsp_i2c_SdaHigh( void )
{
    I2C_SDA_1();
}

static void bsp_i2c_SdaLow( void )
{
    I2C_SDA_0();
}
回复 支持 反对

使用道具 举报

1

主题

42

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
320
金钱
320
注册时间
2017-7-5
在线时间
96 小时
发表于 2020-1-27 10:09:08 | 显示全部楼层
学习学习~~~~~~~~~~~~~~~~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-19 23:23

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表