STM32模拟IIC

IIC.h

#ifndef _MD_IIC_h_
#define _MD_IIC_h_

#include "stm32f10x.h"

/* Pin Definiton ---------- */

#define IIC_GPIO (GPIOC)
#define IIC_GOIO_SDA (GPIOC)
#define IIC_GPIO_SCL (GPIOC)
#define IIC_SDA (GPIO_Pin_2)
#define IIC_SCL (GPIO_Pin_1)

//初始化调用IIC_GPIO_Configuration( IIC_GOIO_SDA , IIC_SDA , IIC_GPIO_SCL , IIC_SCL );
extern void IIC_GPIO_Configuration( GPIO_TypeDef * GPIOx_SDA , uint16_t SDA_Pin , GPIO_TypeDef * GPIOx_SCL , uint16_t SCL_Pin );

//使用软件模拟I2C
#define SET_SDA          { GPIO_SetBits  ( IIC_GPIO , IIC_SDA ); }
#define RESET_SDA        { GPIO_ResetBits( IIC_GPIO , IIC_SDA ); }

#define SET_SCL          { GPIO_SetBits  ( IIC_GPIO , IIC_SCL ); }
#define RESET_SCL        { GPIO_ResetBits( IIC_GPIO , IIC_SCL) ; }

#define IIC_SDA_STATE    (IIC_GPIO->IDR&IIC_SDA)
#define IIC_SCL_STATE    (IIC_GPIO->IDR&IIC_SDA)

#define IIC_DELAY        { IIC_Delay(); }

enum IIC_REPLAY_ENUM
{
    IIC_NACK = 0,
    IIC_ACK = 1
};

enum IIC_BUS_STATE_ENUM
{
    IIC_BUS_READY = 0,
    IIC_BUS_BUSY=1,
    IIC_BUS_ERROR=2
};

//IIC 延时
extern void IIC_Delay(void);
//IIC 启动函数
extern u8 IIC_Start(void);
//IIC 停止函数
extern void IIC_Stop(void);
//IIC 发送动作
extern void IIC_SendACK(void);
//IIC 停止动作
extern void IIC_SendNACK(void);
//IIC 发送单字节
extern u8 IIC_SendByte(u8 Data);
//IIC 接收单字节
extern u8 IIC_RecvByte(void);
//IIC 写入单字节
extern void Single_Write_IIC(u8 SlaveAddress,u8 REG_Address,u8 REG_data);
//IIC 读取单字节
extern u8 Single_Read_IIC(u8 SlaveAddress, u8 REG_Address);


//GPIO 过滤器
extern uint16_t GPIO_Filter( GPIO_TypeDef * GPIOx );

#endif /* _MD_IIC_H_ */

/* End of file ------------------------------------------------------------- */

IIC.c

#include "stm32f10x.h"
#include "MD_IIC.h"

void IIC_GPIO_Configuration( GPIO_TypeDef * GPIOx_SDA , uint16_t SDA_Pin , GPIO_TypeDef * GPIOx_SCL , uint16_t SCL_Pin )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    uint32_t RCC_GPIOx_SDA = 0;
    uint32_t RCC_GPIOx_SCL = 0;

    //得到滤波后的引脚端口
    RCC_GPIOx_SDA = GPIO_Filter( GPIOx_SDA );
    RCC_GPIOx_SCL = GPIO_Filter( GPIOx_SCL );

    //使能时钟
    RCC_APB2PeriphClockCmd(RCC_GPIOx_SDA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_GPIOx_SCL,ENABLE);

    //配置引脚
    GPIO_InitStructure.GPIO_Pin = SDA_Pin;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
    GPIO_Init(GPIOx_SDA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SCL_Pin;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
    GPIO_Init(GPIOx_SCL, &GPIO_InitStructure);

    //初始化ICC的模式
    SET_SDA;
    SET_SCL;  
}

void IIC_Delay(void)
{
    u32 i = 5;
    while( i-- );
}

u8 IIC_Start(void)
{
    SET_SDA;
    IIC_DELAY;

    SET_SCL;
    IIC_DELAY;

    if( IIC_SDA_STATE == RESET )
    {
        return IIC_BUS_BUSY;
    }

    RESET_SDA;
    IIC_DELAY;

    RESET_SCL;
    IIC_DELAY;

    if( IIC_SDA_STATE == SET )
    {
        return IIC_BUS_ERROR;
    }

    return IIC_BUS_READY;
}

void IIC_Stop(void)
{
    RESET_SDA;
    IIC_DELAY;

    SET_SCL;
    IIC_DELAY;

    SET_SDA;
    IIC_DELAY;
}

/* 收到数据,发送NACK - */
void IIC_SendNACK(void)
{
    RESET_SDA;
    IIC_DELAY;
    SET_SCL;
    IIC_DELAY;
    RESET_SCL; 
    IIC_DELAY; 
}

/* 收到数据,发送ACK -- */
void IIC_SendACK(void)
{
    SET_SDA;
    IIC_DELAY;
    SET_SCL;
    IIC_DELAY;
    RESET_SCL; 
    IIC_DELAY;
}

/* 发送一个字节 ----------------------------------------------------------- */
u8 IIC_SendByte(u8 Data)
{
     u8 i;
     RESET_SCL;
     for(i=0;i<8;i++)
     {  
        //数据建立
        if(Data&0x80)
        {
            SET_SDA;
        }
        else
        {
            RESET_SDA;
        } 
        Data<<=1;
        IIC_DELAY;    //数据建立保持一定延时
        SET_SCL;      //产生一个上升沿[正脉冲] 
        IIC_DELAY;
        RESET_SCL;
        IIC_DELAY;    //延时,防止SCL还没变成低时改变SDA,从而产生START/STOP信号 
     }
     //接收从机的应答 
     SET_SDA; 
     IIC_DELAY;
     SET_SCL;
     IIC_DELAY;   
     if(IIC_SDA_STATE)
     {
        RESET_SCL;
        return IIC_NACK;
     }
     else
     {
        RESET_SCL;
        return IIC_ACK;  
     }    
}


/* 接收一个字节 ----------------------------------------- */
u8 IIC_RecvByte(void)
{
     u8 i,Dat = 0;
     SET_SDA;
     RESET_SCL; 
     Dat=0;
     for(i=0;i<8;i++)
     {
        SET_SCL;           //产生时钟上升沿[正脉冲],让从机准备好数据 
        IIC_DELAY; 
        Dat<<=1;
        if(IIC_SDA_STATE)  //读引脚状态
        {
            Dat|=0x01; 
        }   
        RESET_SCL;         //准备好再次接收数据  
        IIC_DELAY;         //等待数据准备好         
     }
     return Dat;
}

/* 单字节写入 -------------------------------------------------------- */
void Single_Write_IIC(u8 SlaveAddress,u8 REG_Address,u8 REG_data)
{
    IIC_Start();                  //起始信号
    IIC_SendByte(SlaveAddress);   //发送设备地址+写信号
    IIC_SendByte(REG_Address);    //内部寄存器地址, //请参考中文pdf22页 
    IIC_SendByte(REG_data);       //内部寄存器数据, //请参考中文pdf22页 
    IIC_Stop();                   //发送停止信号
}

/* 单字节读取 --------------------------------------------------------- */
u8 Single_Read_IIC(u8 SlaveAddress, u8 REG_Address)
{  
    u8 REG_data;
    IIC_Start();                          //起始信号
    IIC_SendByte(SlaveAddress);           //发送设备地址+写信号
    IIC_SendByte(REG_Address);            //发送存储单元地址,//从0开始 
    IIC_Start();                          //起始信号
    IIC_SendByte(SlaveAddress+1);         //发送设备地址+读信号
    REG_data = IIC_RecvByte();            //读出寄存器数据
    IIC_SendACK();   
    IIC_Stop();                           //停止信号
    return REG_data; 
}


//引脚端口过滤器 返回值为 引脚端口的时钟编号
uint16_t GPIO_Filter( GPIO_TypeDef * GPIOx )
{    
    uint32_t RCC_GPIOx = 0; 

    if( GPIOx == GPIOA )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOA;
    }
    else if( GPIOx == GPIOA )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOA;
    }
    else if( GPIOx == GPIOB )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOB;
    }
    else if( GPIOx == GPIOC )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOC;
    }
    else if( GPIOx == GPIOD )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOD;
    }
    else if( GPIOx == GPIOE )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOE;
    }
    else if( GPIOx == GPIOF )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOF;
    }
    else if( GPIOx == GPIOG )
    {
        RCC_GPIOx = RCC_APB2Periph_GPIOG;
    }

    return RCC_GPIOx;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值