OpenEdv-开源电子网

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

高度提炼的模拟I2C程序 --- 正点原子例程多I2C主机的改进建议

[复制链接]

3

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-1-13
在线时间
8 小时
发表于 2016-1-13 11:45:18 | 显示全部楼层 |阅读模式
本帖最后由 nicholasldf 于 2016-1-13 11:45 编辑

使用了一段时间正点原子例程,,很多地方用到了模拟I2C,如运动传感器、触摸屏,EEPROM等等,,但是每个驱动都实现了一套start、stop、readbyte,writebyte等函数,,,显得比较重复和冗余。
下面是我实现的I2C模拟驱动,,只要赋值好结构体,,,这一套程序可以实现无数个I2C模拟主机,,提供给大家参考。




以下是模拟I2C高度提炼的程序,只要提供GPIO端口、SCL和SDA引脚号、从设备addr,就可以开始使用,基于STM32,对于其他CPU,稍作修改即可。


优点:如果系统中用到了多个模拟I2C通信实例,,就不用每一个模拟I2C实例都编写一套几乎一摸一样的代码,,以下代码对于所有实例都通用。

就像我的系统,很多地方用到了模拟I2C,至少3-4个,有EEPROM,motion运动传感器、ADC等等,,都在不同的引脚上面,但是只用这一套代码。
对于单个I2C,下面也是实用的。

当然:以下代码是根据I2C协议标准编写的,,所有的延时函数都是根据标准所定,,如果不符合您的系统,,可以将delay_us延时加大。


//-------------------------------------------------------------------------------头文件-----------------------------------------------------------------------------------------
/*
*********************************************************************************************************
*    \'-.__.-'/      | Company  : o--Shen Zhen xxxxx Technology Co,.Ltd--o
*    / (o)(o) \     | Website    : o--http://www.xxxxx .com.cn--o
*     \   \/   /      | Copyright  :
*     /'------'\      | Product     :  
*   /,   ....  , \     | File            : bsp_SimulateI2C.h
*  /// .::::. \\\    | Descript     : use GPIOs to Simulate I2C communication
* ///\ :::::: /\\\  | Version      : V0.10
*  ''   ).''''.(   ``  | Author      : nicholasldf
*=(((====)))= | EditTime : 2015-09-06-10:00
*********************************************************************************************************
*/

#ifndef  __BSP_SIMULATE_I2C__
#define  __BSP_SIMULATE_I2C__

#include  "stm32f4xx_hal.h"

//模拟I2C结构体声明
//Simulate I2C Port struct define
struct   SimuI2cPortType   {
        GPIO_TypeDef         *SCLPort;//GPIO PORT
        uint32_t                    SCLPin;  //GPIO PIN
        GPIO_TypeDef         *SDAPort;//GPIO PORT
        uint32_t                    SDAPin;  //GPIO PIN
        uint8_t                      address; //slave address
};

//模拟I2C的SCL、SDA管脚控制宏定义
//SCL output hardware operate
#define SIMUI2C_SCL_SET                HAL_GPIO_WritePin(pSimuI2cPort->SCLPort, pSimuI2cPort->SCLPin, GPIO_PIN_SET)
#define SIMUI2C_SCL_CLR                HAL_GPIO_WritePin(pSimuI2cPort->SCLPort, pSimuI2cPort->SCLPin, GPIO_PIN_RESET)
//SDA output hardware operate
#define SIMUI2C_SDA_SET                HAL_GPIO_WritePin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin, GPIO_PIN_SET)
#define SIMUI2C_SDA_CLR                HAL_GPIO_WritePin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin, GPIO_PIN_RESET)
//SDA input hardware operate
#define SIMUI2C_SDA_IN                   HAL_GPIO_ReadPin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin)

//simulate i2c APIs
void bsp_SimuI2C_start(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_stop(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_SandAck(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_SandNack(struct  SimuI2cPortType   *pSimuI2cPort);
uint32_t bsp_SimuI2C_ReadAck(struct  SimuI2cPortType   *pSimuI2cPort);
uint8_t bsp_SimuI2C_read_byte(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_write_byte(struct  SimuI2cPortType   *pSimuI2cPort,    uint8_t   data);

#endif /* End of module include */








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

使用道具 举报

3

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-1-13
在线时间
8 小时
 楼主| 发表于 2016-1-13 11:45:19 | 显示全部楼层
//-------------------------------------------------------------------------------源文件-----------------------------------------------------------------------------------------
/*
*********************************************************************************************************
*    \'-.__.-'/      | Company  : o--Shen Zhen xxxxx Technology Co,.Ltd--o
*    / (o)(o) \     | Website    : o--http://www.xxxxx .com.cn--o
*     \   \/   /      | Copyright  :  
*     /'------'\      | Product     :  
*   /,   ....  , \     | File            : bsp_SimulateI2C.c
*  /// .::::. \\\    | Descript     : use GPIOs to Simulate I2C communication
* ///\ :::::: /\\\  | Version      : V0.10
*  ''   ).''''.(   ``  | Author      : nicholasldf
*=(((====)))= | EditTime : 2015-09-06-10:00
*********************************************************************************************************
*/

#include  "bsp_SimulateI2C.h"
#include  "bsp_common.h"

/*  配置SDA管脚为输入方式
*********************************************************************************************************
* function    :  config_sda_in
* Description : config SDA GPIO for input
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
static void config_sda_in(struct SimuI2cPortType *pSimuI2cPort)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        
        /* Configure SDA GPIO pin */
        GPIO_InitStruct.Pin = pSimuI2cPort->SDAPin;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        HAL_GPIO_Init(pSimuI2cPort->SDAPort, &GPIO_InitStruct);
}

/*  配置SDA管脚为输出方式
*********************************************************************************************************
* function    : config_sda_out
* Description : config SDA GPIO for output
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
static void config_sda_out(struct SimuI2cPortType *pSimuI2cPort)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        
        /* Configure SDA GPIO pin */
        GPIO_InitStruct.Pin = pSimuI2cPort->SDAPin;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        HAL_GPIO_Init(pSimuI2cPort->SDAPort, &GPIO_InitStruct);
}

/*  生成一个I2C的start开始条件,或者restart重新开始条件
*********************************************************************************************************
* function    : bsp_SimuI2C_start
* Description : generate a i2c start or restart
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_start(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //here may be a stop
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL setup time for STOP condition, 0.6uS
        SIMUI2C_SDA_SET;
        delay_us(2);//the bus must be free before a new transmission can start, 1.2uS
        
        //start
        SIMUI2C_SDA_CLR;
        delay_us(1);//SCL hold time for START condition, 0.6uS
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}

/*  生成一个I2C的stop停止条件
*********************************************************************************************************
* function    : bsp_SimuI2C_stop
* Description : generate a i2c stop
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_stop(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //set SCL and SDA low first
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        SIMUI2C_SDA_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        
        //stop
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL setup time for STOP condition
        SIMUI2C_SDA_SET;
        delay_us(2);//Time the bus must be free before a new transmission can start, 1.2uS
}

/*  给从设备发送一个ack应答信号
*********************************************************************************************************
* function    : bsp_SimuI2C_SandAck
* Description : generate a i2c ack to slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_SandAck(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //set sda=0
        //delay_us(1);//SCL low period * 0.5 = 0.65uS
        SIMUI2C_SDA_CLR;//SDA=0
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        
        //scl pulse
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL high period, 0.6uS
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}



回复 支持 反对

使用道具 举报

3

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-1-13
在线时间
8 小时
 楼主| 发表于 2016-1-13 11:45:20 | 显示全部楼层
/*   给从设备发送一个no ack非应答信号
*********************************************************************************************************
* function    : bsp_SimuI2C_SandNack
* Description : generate a i2c noack to slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_SandNack(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //set sda=1
        //delay_us(1);//SCL low period * 0.5 = 0.65uS
        SIMUI2C_SDA_SET;//SDA=1
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        
        //scl pulse
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL high period, 0.6uS
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}

/*   读取从设备的ack应答信号状态, 0表示应答, 1表示非应答
*********************************************************************************************************
* function    : bsp_SimuI2C_ReadAck
* Description : check i2c ack from slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : 0: ack, 1: nack
*********************************************************************************************************
*/
uint32_t bsp_SimuI2C_ReadAck(struct SimuI2cPortType *pSimuI2cPort)
{
        uint32_t ack;

        //config sda pin input
        config_sda_in(pSimuI2cPort);
        
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL high period, 0.6uS
        ack = SIMUI2C_SDA_IN;
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        
        return ack;
}

/*   主机读取从设备,返回一个8bit数据
*********************************************************************************************************
* function    : bsp_SimuI2C_read_byte
* Description : read a byte from i2c slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : the read data
*********************************************************************************************************
*/
uint8_t bsp_SimuI2C_read_byte(struct SimuI2cPortType *pSimuI2cPort)
{
        uint32_t i;
        uint8_t  data;
        
        //config sda pin input
        config_sda_in(pSimuI2cPort);
        
        data = 0;
        for(i=0; i<8; i++) {
                delay_us(1);//SCL low period * 0.5 = 0.65uS
                SIMUI2C_SCL_SET;
                delay_us(1);//SCL high period, 0.6uS
                //read data in
                data<<=1;
                if(GPIO_PIN_SET == SIMUI2C_SDA_IN)        data |= 0x01;
                SIMUI2C_SCL_CLR;
                delay_us(1);//SCL low period * 0.5 = 0.65uS
        }

        return data;
}

/*  主机写8bit数据到从设备
*********************************************************************************************************
* function    : bsp_SimuI2C_write_byte
* Description : write a byte to i2c slave
* Argument(s) : pSimuI2cPort: point to struct SimuI2cPortType, data: data to write
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_write_byte(struct SimuI2cPortType *pSimuI2cPort, uint8_t data)
{
        uint32_t i;
        
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        for(i=0; i<8; i++) {
                delay_us(1);//SCL low period * 0.5 = 0.65uS
                //sda bit output
                if(data & 0x80)
                        SIMUI2C_SDA_SET;
                else
                        SIMUI2C_SDA_CLR;
                delay_us(1);//SCL low period * 0.5 = 0.65uS
                //scl pulse
                SIMUI2C_SCL_SET;               
                delay_us(1);//SCL high period, 0.6uS
                SIMUI2C_SCL_CLR;
                //next bit
                data <<= 1;
        }
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}

/**  End of bsp_SimulateI2C.c **/


//-------------------------------------------------------------------------------如何使用-----------------------------------------------------------------------------------------
        使用方法:定义一个模拟I2C结构体,初始化IO口,设置好GPIO端口和pin引脚号,,即可开始使用        
        //定义好模拟I2C结构体
        struct SimuI2cPortType  TouchI2cPort;

        //管脚初始化,设置SCL、SDA为普通IO口,输出方式
        //SCL
        /* Configure SCL PIN - PB0 */
        GPIO_InitStruct.Pin = GPIO_PIN_0;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);


        //SDA
        /* Configure SDA PIN - PF11 */
        GPIO_InitStruct.Pin = GPIO_PIN_11;
        HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
        HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_SET);
        
        
        //设置好模拟I2C结构体的端口号和引脚号:SimuI2C PORT, SCL-PB0, SDA-PF11
        //SCL的端口号和引脚号
        TouchI2cPort.SCLPort = GPIOB;
        TouchI2cPort.SCLPin  = GPIO_PIN_0;
        //SDA的端口号和引脚号
        TouchI2cPort.SDAPort = GPIOF;
        TouchI2cPort.SDAPin  = GPIO_PIN_11;
        
       //设置该模拟I2C结构体对应从设备的地址
       TouchI2cPort.address  =  xxxx; //slave address

       //let‘s  go   ^_^
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2016-1-13 12:38:24 | 显示全部楼层
正准备写呢,楼主抢我前面去了,牛逼
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2016-1-13 12:38:48 | 显示全部楼层
先收藏了,等忙完再来写,谢谢分享!
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2016-1-13 14:05:48 | 显示全部楼层
强悍.....
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2016-1-13 18:19:29 | 显示全部楼层
费了三四个小时终于移植成寄存器版本(如下),也是自己能力有限导致的,像楼主学习了~~~~~

头文件如下,在楼主基础上知识定义了一个变量IICSone作为示例:
[mw_shl_code=c,true]#ifndef  __IICS__H
#define  __IICS__H

#include "sys.h"

//模拟I2C结构体声明
struct   SimuI2cPortType   {
        GPIO_TypeDef         *SCLPort;//GPIO PORT
        uint32_t              SCLPin;  //GPIO PIN
        GPIO_TypeDef         *SDAPort;//GPIO PORT
        uint32_t              SDAPin;  //GPIO PIN
        uint8_t               address; //slave address
};
extern struct SimuI2cPortType IICSone;

//模拟I2C的SCL、SDA管脚控制宏定义
//SCL output hardware operate
#define SIMUI2C_SCL_SET      HAL_GPIO_WritePin(pSimuI2cPort->SCLPort, pSimuI2cPort->SCLPin, 1)
#define SIMUI2C_SCL_CLR      HAL_GPIO_WritePin(pSimuI2cPort->SCLPort, pSimuI2cPort->SCLPin, 0)
//SDA output hardware operate
#define SIMUI2C_SDA_SET      HAL_GPIO_WritePin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin, 1)
#define SIMUI2C_SDA_CLR      HAL_GPIO_WritePin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin, 0)
//SDA input hardware operate
#define SIMUI2C_SDA_IN       HAL_GPIO_ReadPin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin)

//simulate i2c APIs
void bsp_SimuI2C_start(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_stop(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_SendAck(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_SendNack(struct  SimuI2cPortType   *pSimuI2cPort);
uint32_t bsp_SimuI2C_ReadAck(struct  SimuI2cPortType   *pSimuI2cPort);
uint8_t bsp_SimuI2C_read_byte(struct  SimuI2cPortType   *pSimuI2cPort);
void bsp_SimuI2C_write_byte(struct  SimuI2cPortType   *pSimuI2cPort,    uint8_t   data);

void IICS_Init(void);

#endif /* End of module include */[/mw_shl_code]

.c文件实现如下
[mw_shl_code=c,true]#include  "IICS.h"
#include  "delay.h"

/*配置SCL管脚输出模式函数*/
static void config_scl_out(struct SimuI2cPortType *pSimuI2cPort)
{
        if(pSimuI2cPort->SCLPin<8)
        {
                pSimuI2cPort->SCLPort->CRL &= ~(0X0000000F << (pSimuI2cPort->SCLPin*4));
                pSimuI2cPort->SCLPort->CRL |= (u32)3 << (pSimuI2cPort->SCLPin*4);
        }
        else
        {
                pSimuI2cPort->SCLPort->CRH &= ~(0X0000000F << (pSimuI2cPort->SCLPin%8*4));
                pSimuI2cPort->SCLPort->CRH |= (u32)3 << (pSimuI2cPort->SCLPin%8*4);
        }
}

/*配置SDA管脚输出模式函数*/
static void config_sda_out(struct SimuI2cPortType *pSimuI2cPort)
{
        if(pSimuI2cPort->SDAPin<8)
        {
                pSimuI2cPort->SDAPort->CRL &= ~(0X0000000F << (pSimuI2cPort->SDAPin*4));
                pSimuI2cPort->SDAPort->CRL |= (u32)3 << (pSimuI2cPort->SDAPin*4);
        }
        else
        {
                pSimuI2cPort->SDAPort->CRH &= ~(0X0000000F << (pSimuI2cPort->SDAPin%8*4));
                pSimuI2cPort->SDAPort->CRH |= (u32)3 << (pSimuI2cPort->SDAPin%8*4);
        }
}

/*配置SDA管脚输入模式函数*/
static void config_sda_in(struct SimuI2cPortType *pSimuI2cPort)
{
        if(pSimuI2cPort->SDAPin<8)
        {
                pSimuI2cPort->SDAPort->CRL &= ~(0X0000000F << (pSimuI2cPort->SDAPin*4));
                pSimuI2cPort->SDAPort->CRL |= (u32)8 << (pSimuI2cPort->SDAPin*4);
        }
        else
        {
                pSimuI2cPort->SDAPort->CRH &= ~(0X0000000F << (pSimuI2cPort->SDAPin%8*4));
                pSimuI2cPort->SDAPort->CRH |= (u32)8 << (pSimuI2cPort->SDAPin%8*4);
        }
}

/*输出0 1*/
static void HAL_GPIO_WritePin(GPIO_TypeDef *Port, uint32_t Pin, u8 Value)
{
        if(Value == 1)     //SET
        {
                Port->ODR |= 1 << Pin;
        }
        else if(Value == 0)     //RESET
        {
                Port->ODR &= ~(0x01 << Pin);
        }
}

/*读取端口状态*/
static u16 HAL_GPIO_ReadPin(GPIO_TypeDef *Port, uint32_t Pin)
{
        if(Port->IDR & (1 << Pin))
        {
                return 1;
        }               
        else
        {
                return 0;
        }
}

/*  生成一个I2C的start开始条件,或者restart重新开始条件
*********************************************************************************************************
* function    : bsp_SimuI2C_start
* Description : generate a i2c start or restart
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_start(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //here may be a stop
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL setup time for STOP condition, 0.6uS
        SIMUI2C_SDA_SET;
        delay_us(4);//the bus must be free before a new transmission can start, 1.2uS
        
        //start
        SIMUI2C_SDA_CLR;
        delay_us(4);//SCL hold time for START condition, 0.6uS
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}

/*  生成一个I2C的stop停止条件
*********************************************************************************************************
* function    : bsp_SimuI2C_stop
* Description : generate a i2c stop
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_stop(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //set SCL and SDA low first
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        SIMUI2C_SDA_CLR;
        delay_us(4);//SCL low period * 0.5 = 0.65uS
        
        //stop
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL setup time for STOP condition
        SIMUI2C_SDA_SET;
        delay_us(4);//Time the bus must be free before a new transmission can start, 1.2uS
}

/*  给从设备发送一个ack应答信号
*********************************************************************************************************
* function    : bsp_SimuI2C_SandAck
* Description : generate a i2c ack to slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_SendAck(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //set sda=0
        //delay_us(1);//SCL low period * 0.5 = 0.65uS
        SIMUI2C_SDA_CLR;//SDA=0
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        
        //scl pulse
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL high period, 0.6uS
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}

/*   给从设备发送一个no ack非应答信号
*********************************************************************************************************
* function    : bsp_SimuI2C_SandNack
* Description : generate a i2c noack to slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_SendNack(struct SimuI2cPortType *pSimuI2cPort)
{
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        //set sda=1
        //delay_us(1);//SCL low period * 0.5 = 0.65uS
        SIMUI2C_SDA_SET;//SDA=1
        delay_us(1);//SCL low period * 0.5 = 0.65uS
        
        //scl pulse
        SIMUI2C_SCL_SET;
        delay_us(1);//SCL high period, 0.6uS
        SIMUI2C_SCL_CLR;
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}

/*   读取从设备的ack应答信号状态, 0表示应答, 1表示非应答
*********************************************************************************************************
* function    : bsp_SimuI2C_ReadAck
* Description : check i2c ack from slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : 0: ack, 1: nack
*********************************************************************************************************
*/
uint32_t bsp_SimuI2C_ReadAck(struct SimuI2cPortType *pSimuI2cPort)
{
//        uint32_t ack;
//        //config sda pin input
//        config_sda_in(pSimuI2cPort);
//        
//        delay_us(1);//SCL low period * 0.5 = 0.65uS
//        SIMUI2C_SCL_SET;
//        delay_us(1);//SCL high period, 0.6uS
//        ack = SIMUI2C_SDA_IN;
//        SIMUI2C_SCL_CLR;
//        delay_us(1);//SCL low period * 0.5 = 0.65uS        
//        return ack;
        u8 ucErrTime=0;
        config_sda_in(pSimuI2cPort);     //SDA设置为输入  
        SIMUI2C_SDA_SET;
        delay_us(1);          
        SIMUI2C_SCL_SET;
        delay_us(1);         
        while(SIMUI2C_SDA_IN)
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        bsp_SimuI2C_stop(pSimuI2cPort);
                        return 1;
                }
        }
        SIMUI2C_SCL_CLR;//时钟输出0           
        return 0;  
}

/*   主机读取从设备,返回一个8bit数据
*********************************************************************************************************
* function    : bsp_SimuI2C_read_byte
* Description : read a byte from i2c slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s)   : the read data
*********************************************************************************************************
*/
uint8_t bsp_SimuI2C_read_byte(struct SimuI2cPortType *pSimuI2cPort)
{
        uint32_t i;
        uint8_t  data;
        
        //config sda pin input
        config_sda_in(pSimuI2cPort);
        
        data = 0;
        for(i=0; i<8; i++)
                {
                        SIMUI2C_SCL_CLR;
                        delay_us(2);//SCL low period * 0.5 = 0.65uS
                        SIMUI2C_SCL_SET;
                        delay_us(1);//SCL high period, 0.6uS
                        //read data in
                        data<<=1;
                        if(1 == SIMUI2C_SDA_IN)        data |= 0x01;
                        delay_us(1);//SCL low period * 0.5 = 0.65uS
        }
                bsp_SimuI2C_SendNack(pSimuI2cPort);

        return data;
}

/*  主机写8bit数据到从设备
*********************************************************************************************************
* function    : bsp_SimuI2C_write_byte
* Description : write a byte to i2c slave
* Argument(s) : pSimuI2cPort: point to struct SimuI2cPortType, data: data to write
* Return(s)   : none
*********************************************************************************************************
*/
void bsp_SimuI2C_write_byte(struct SimuI2cPortType *pSimuI2cPort, uint8_t data)
{
        uint32_t i;
        
        //config sda pin output
        config_sda_out(pSimuI2cPort);
        
        for(i=0; i<8; i++) {
                delay_us(1);//SCL low period * 0.5 = 0.65uS
                //sda bit output
                if(data & 0x80)
                        SIMUI2C_SDA_SET;
                else
                        SIMUI2C_SDA_CLR;
                delay_us(1);//SCL low period * 0.5 = 0.65uS
                //scl pulse
                SIMUI2C_SCL_SET;               
                delay_us(1);//SCL high period, 0.6uS
                SIMUI2C_SCL_CLR;
                //next bit
                data <<= 1;
        }
        delay_us(1);//SCL low period * 0.5 = 0.65uS
}

/**  End of bsp_SimulateI2C.c **/

/*----------------------------------------------------------------------------------------------------------------------*/

struct SimuI2cPortType IICSone;

void IICS_Init(void)
{
        RCC->APB2ENR|=1<<3;     //使能GPIOB时钟
       
        IICSone.SCLPort = GPIOB;
        IICSone.SCLPin = 6;
        IICSone.SDAPort = GPIOB;
        IICSone.SDAPin = 7;
        IICSone.address = 0;
       
        config_scl_out(&IICSone);     //配置SCL工作模式       
        config_sda_out(&IICSone);
}
[/mw_shl_code]
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

294

主题

1414

帖子

12

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
7791
金钱
7791
注册时间
2015-10-15
在线时间
2858 小时
发表于 2016-1-13 20:51:05 | 显示全部楼层
感谢楼主分享。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

83

主题

349

帖子

1

精华

高级会员

Rank: 4

积分
908
金钱
908
注册时间
2012-8-10
在线时间
13 小时
发表于 2016-1-13 22:06:43 | 显示全部楼层
赞一个
回复 支持 反对

使用道具 举报

7

主题

103

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
311
金钱
311
注册时间
2015-8-18
在线时间
63 小时
发表于 2016-1-13 22:48:12 | 显示全部楼层
本帖最后由 feisheng168 于 2016-1-13 23:01 编辑

呵呵,不错,学习的挺快的。
回复 支持 反对

使用道具 举报

2

主题

56

帖子

0

精华

高级会员

Rank: 4

积分
509
金钱
509
注册时间
2015-12-22
在线时间
85 小时
发表于 2016-1-15 09:39:13 | 显示全部楼层
谢谢分享,mark
回复 支持 反对

使用道具 举报

10

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
459
金钱
459
注册时间
2016-7-7
在线时间
110 小时
发表于 2016-7-22 09:56:10 | 显示全部楼层
谢谢分享,mark
回复 支持 反对

使用道具 举报

4

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
162
金钱
162
注册时间
2013-7-30
在线时间
31 小时
发表于 2016-8-2 17:57:58 | 显示全部楼层
挺好的!
回复 支持 反对

使用道具 举报

3

主题

548

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1383
金钱
1383
注册时间
2015-2-3
在线时间
197 小时
发表于 2016-8-3 12:35:39 | 显示全部楼层
请问楼主对IIC多主机冲突做了测试吗?
回复 支持 反对

使用道具 举报

1

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2016-11-11
在线时间
12 小时
发表于 2016-11-18 17:15:41 | 显示全部楼层
不错 谢谢分享 学习了
回复 支持 反对

使用道具 举报

5

主题

40

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
229
金钱
229
注册时间
2016-7-30
在线时间
82 小时
发表于 2016-11-18 18:03:48 | 显示全部楼层
mark  谢谢楼主
回复 支持 反对

使用道具 举报

2

主题

33

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
377
金钱
377
注册时间
2015-10-19
在线时间
173 小时
发表于 2016-11-23 15:24:27 | 显示全部楼层
做個記號謝謝樓主

也感謝 7樓 龙之谷 大改寫的寄存器版

回复 支持 反对

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2016-8-13
在线时间
14 小时
发表于 2016-12-13 09:29:17 | 显示全部楼层
66666666666666666666666666666666
回复 支持 反对

使用道具 举报

0

主题

32

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
379
金钱
379
注册时间
2017-1-4
在线时间
129 小时
发表于 2018-10-18 10:03:15 | 显示全部楼层
学习了,谢谢
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-23 04:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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