您的位置:首页 > 其它

STM32模拟IIC

2017-07-23 17:21 288 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: