STM32 軟件IIC接口,支持虛擬多個IIC接口,需要自己對底層進行移植,比如IO口時鐘使能,初始化,寫1,寫0,讀取進行移植,移植到自己的硬件平臺。
//SoftwareIIC.c
/*************************************************************************************************************
?*?文件名: SoftwareIIC.c
?*?功能: STM32?軟件IIC接口
?*?作者: cp1300@139.com
?*?創(chuàng)建時間: 2017-07-10
?*?最后修改時間: 2017-07-10
?*?詳細(xì): 軟件IIC接口
*************************************************************************************************************/
#include?"system.h"
#include?"GPIO_INIT.h"
#include?"delay.h"
#include?"SoftwareIIC.h"
//調(diào)試宏開關(guān)
#define?SIIC_DBUG 1
#if?SIIC_DBUG
#include?"system.h"
#define?SIIC_Debug(format,...) uart_printf(format,##__VA_ARGS__)
#else
#define?SIIC_Debug(format,...) /
/
#endif //SIIC_DBUG
//相關(guān)底層操作接口
#define?SIIC_DelayUS(x) Delay_US(x) //延時US
#define?SDA_OUT_MODE(GPIOx,bit) GPIOx_OneInit(GPIOx,bit,OUT_PP,SPEED_2M) //SDA輸出模式
#define?SDA_IN_MODE(GPIOx,bit) GPIOx_OneInit(GPIOx,bit,IN_IPU,IN_IN) //SDA輸入模式
#define?SCL_OUT_MODE(GPIOx,bit) GPIOx_OneInit(GPIOx,bit,OUT_PP,SPEED_2M) //SCL輸出模式
#define?SDA_OUT_H(GPIOx,bit) (GPIOx->ODR|=(1<ODR&=~(1<ODR|=(1<ODR&=~(1<IDR&(1<<bit))?1:0) //SDA輸入
/*************************************************************************************************************************
*函數(shù)???????? : bool?SIIC_Init(SIIC_HANDLE?*pHandle,?GPIO_TypeDef?*SDA_GPIOx,?GPIO_TypeDef?*SCL_GPIOx,u8?SDA_GPIO_BITx,?u8?SCL_GPIO_BITx,u8?DelayUS)
*功能???????? : 軟件IIC初始化
*參數(shù)???????? : pHandle:句柄;SDA_GPIOx:SDA?IO;SCL_GPIOx:SCL?GPIO;SDA_GPIO_BITx:SDA?IO位數(shù);SCL_GPIO_BITx:SCL?IO位數(shù);DelayUS:通信延時,單位us(1-100us)
*返回???????? : TRUE:初始化成功;FALSE:初始化失敗
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
bool?SIIC_Init(SIIC_HANDLE?*pHandle,?GPIO_TypeDef?*SDA_GPIOx,?GPIO_TypeDef?*SCL_GPIOx,u8?SDA_GPIO_BITx,?u8?SCL_GPIO_BITx,u8?DelayUS)
{
u8?DEV_GPION;
if(pHandle?==?NULL)?
{
SIIC_Debug("初始化軟件IIC失敗,pHandle句柄為空rn");
return?FALSE;
}
if(DelayUS?<?1)?DelayUS?=?1;
if(DelayUS?>100)?DelayUS?=?100;
pHandle->DelayUS?=?DelayUS;
pHandle->SDA_GPIOx?=?SDA_GPIOx; //SDA數(shù)據(jù)線IO
pHandle->SCL_GPIOx?=?SCL_GPIOx; //SCL時鐘線IO
if(SDA_GPIO_BITx?>?15)?
{
SIIC_Debug("初始化軟件IIC失敗,SDA_GPIO_BITx不能超過15rn");
return?FALSE;
}
pHandle->SDA_GPIO_BITx?=?SDA_GPIO_BITx; //SDA數(shù)據(jù)線位,0-15
if(SCL_GPIO_BITx?>?15)?
{
SIIC_Debug("初始化軟件IIC失敗,SCL_GPIO_BITx不能超過15rn");
return?FALSE;
}
pHandle->SCL_GPIO_BITx?=?SCL_GPIO_BITx; //SCL時鐘線位,0-15
//判斷SDA?IO組,進行時鐘初始化
switch((u32)SDA_GPIOx)
{
case?(u32)GPIOA:
{
DEV_GPION?=?DEV_GPIOA;
}break;
case?(u32)GPIOB:
{
DEV_GPION?=?DEV_GPIOB;
}break;
case?(u32)GPIOC:
{
DEV_GPION?=?DEV_GPIOC;
}break;
case?(u32)GPIOD:
{
DEV_GPION?=?DEV_GPIOD;
}break;
case?(u32)GPIOE:
{
DEV_GPION?=?DEV_GPIOE;
}break;
case?(u32)GPIOF:
{
DEV_GPION?=?DEV_GPIOF;
}break;
case?(u32)GPIOG:
{
DEV_GPION?=?DEV_GPIOG;
}break;
default:?
{
SIIC_Debug("初始化軟件IIC失敗,SDA_GPIOx無效rn");
return?FALSE;
}
}
DeviceClockEnable(DEV_GPION,?ENABLE); //使能SDA?IO時鐘
//判斷SCL?IO組,進行時鐘初始化
switch((u32)SCL_GPIOx)
{
case?(u32)GPIOA:
{
DEV_GPION?=?DEV_GPIOA;
}break;
case?(u32)GPIOB:
{
DEV_GPION?=?DEV_GPIOB;
}break;
case?(u32)GPIOC:
{
DEV_GPION?=?DEV_GPIOC;
}break;
case?(u32)GPIOD:
{
DEV_GPION?=?DEV_GPIOD;
}break;
case?(u32)GPIOE:
{
DEV_GPION?=?DEV_GPIOE;
}break;
case?(u32)GPIOF:
{
DEV_GPION?=?DEV_GPIOF;
}break;
case?(u32)GPIOG:
{
DEV_GPION?=?DEV_GPIOG;
}break;
default:
{
SIIC_Debug("初始化軟件IIC失敗,SCL_GPIOx無效rn");
return?FALSE;
}
}
DeviceClockEnable(DEV_GPION,?ENABLE); //使能SCL?IO時鐘
SDA_OUT_MODE(SDA_GPIOx,SDA_GPIO_BITx); //SDA輸出模式
SCL_OUT_MODE(SCL_GPIOx,SCL_GPIO_BITx); //SCL輸出模式
SDA_OUT_H(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=1
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
return?TRUE;
}
/*************************************************************************************************************************
*函數(shù)???????? : void?SIIC_Start(SIIC_HANDLE?*pHandle)
*功能???????? : 產(chǎn)生IIC起始信號
*參數(shù)???????? : pHandle:句柄
*返回???????? : 無
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
void?SIIC_Start(SIIC_HANDLE?*pHandle)
{
SDA_OUT_MODE(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA設(shè)置為輸出
SDA_OUT_H(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=1
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
SIIC_DelayUS(pHandle->DelayUS); //延時
? SDA_OUT_L(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=0?START:when?CLK?is?high,DATA?change?form?high?to?low?
SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0,鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)?
SIIC_DelayUS(pHandle->DelayUS); //延時
}
/*************************************************************************************************************************
*函數(shù)???????? : void?SIIC_Stop(SIIC_HANDLE?*pHandle)
*功能???????? : 產(chǎn)生IIC停止信號
*參數(shù)???????? : pHandle:句柄
*返回???????? : 無
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
void?SIIC_Stop(SIIC_HANDLE?*pHandle)
{
SDA_OUT_MODE(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA設(shè)置為輸出
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0
SDA_OUT_L(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=0?//STOP:when?CLK?is?high?DATA?change?form?low?to?high
SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
SDA_OUT_H(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=1
SIIC_DelayUS(pHandle->DelayUS); //延時 ???
}
/*************************************************************************************************************************
*函數(shù)???????? : bool?SIIC_WaitAck(SIIC_HANDLE?*pHandle)
*功能???????? : IIC等待應(yīng)答信號到來
*參數(shù)???????? : pHandle:句柄
*返回???????? : TRUE:應(yīng)答成功;FALSE:應(yīng)答失敗
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
bool?SIIC_WaitAck(SIIC_HANDLE?*pHandle)
{
u8?ucErrTime=0;
SDA_IN_MODE(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA設(shè)置為輸入
SDA_OUT_H(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=1
SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
SIIC_DelayUS(pHandle->DelayUS); //延時 ?
while(SDA_IN(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx)) //等待低電平
{
ucErrTime++;
if(ucErrTime>50)
{
SIIC_Stop(pHandle);
return?FALSE;
}
SIIC_DelayUS(1);
}
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0 ???
return?TRUE;??
}?
/*************************************************************************************************************************
*函數(shù)???????? : void?SIIC_Ack(SIIC_HANDLE?*pHandle)
*功能???????? : IIC產(chǎn)生ACK應(yīng)答
*參數(shù)???????? : pHandle:句柄
*返回???????? : 無
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
void?SIIC_Ack(SIIC_HANDLE?*pHandle)
{
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0 ???
SDA_OUT_MODE(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA設(shè)置為輸出
SDA_OUT_L(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=0
SIIC_DelayUS(pHandle->DelayUS); //延時 ?
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0 ?
SIIC_DelayUS(pHandle->DelayUS); //延時
}
/*************************************************************************************************************************
*函數(shù)???????? : void?SIIC_NAck(SIIC_HANDLE?*pHandle)
*功能???????? : SIIC產(chǎn)生NACK應(yīng)答
*參數(shù)???????? : pHandle:句柄
*返回???????? : 無
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/ ????
void?SIIC_NAck(SIIC_HANDLE?*pHandle)
{
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0 ???
SDA_OUT_MODE(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA設(shè)置為輸出
SDA_OUT_H(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=1
SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0 ??
SIIC_DelayUS(pHandle->DelayUS); //延時
}
/*************************************************************************************************************************
*函數(shù)???????? : bool?SIIC_SendByte(SIIC_HANDLE?*pHandle,?u8?data)
*功能???????? : SIIC發(fā)送一個字節(jié)
*參數(shù)???????? : pHandle:句柄;data:要發(fā)送的數(shù)據(jù)
*返回???????? : TRUE:有應(yīng)答;FALSE:無應(yīng)答
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/ ????
bool?SIIC_SendByte(SIIC_HANDLE?*pHandle,?u8?data)
{????????????????????????
????u8?t;?
SDA_OUT_MODE(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA設(shè)置為輸出 ????
????SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0?拉低時鐘開始數(shù)據(jù)傳輸
????for(t=0;tSDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=1
}
else
{
SDA_OUT_L(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA=0
}
????????data?<DelayUS); //延時
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_L(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0
SIIC_DelayUS(pHandle->DelayUS); //延時
????}
return?SIIC_WaitAck(pHandle); //等待應(yīng)答
}?
/*************************************************************************************************************************
*函數(shù)???????? : u8?SIIC_ReadByte(SIIC_HANDLE?*pHandle,bool?isAck)
*功能???????? : SIIC讀取一個字節(jié)
*參數(shù)???????? : pHandle:句柄;isAck:是否發(fā)送ACK
*返回???????? : 讀取到的數(shù)據(jù)
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/?
u8?SIIC_ReadByte(SIIC_HANDLE?*pHandle,bool?isAck)
{
u8?i,receive=0;
SDA_IN_MODE(pHandle->SDA_GPIOx,?pHandle->SDA_GPIO_BITx); //SDA設(shè)置為輸入
????for(i=0;iSCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=0
????????SIIC_DelayUS(pHandle->DelayUS); //延時
SCL_OUT_H(pHandle->SCL_GPIOx,?pHandle->SCL_GPIO_BITx); //SCL=1
????????receive<SDA_GPIOx,?pHandle->SDA_GPIO_BITx))receive++;???
SIIC_DelayUS(pHandle->DelayUS); //延時
????} ?
????if?(!isAck)
????????SIIC_NAck(pHandle);//發(fā)送nACK
????else
????????SIIC_Ack(pHandle);?//發(fā)送ACK??
????return?receive;
}
//SoftwareIIC.H
/*************************************************************************************************************
?*?文件名: SoftwareIIC.H
?*?功能: STM32?軟件IIC接口
?*?作者: cp1300@139.com
?*?創(chuàng)建時間: 2017-07-10
?*?最后修改時間: 2017-07-10
?*?詳細(xì): 軟件IIC接口
*************************************************************************************************************/
#ifndef?_SOFTWARE_IIC_H_
#define?_SOFTWARE_IIC_H_
#include?"system.h"
//軟件IIC接口句柄結(jié)構(gòu)
typedef?struct?
{
GPIO_TypeDef *SDA_GPIOx; //SDA數(shù)據(jù)線IO
GPIO_TypeDef *SCL_GPIOx; //SCL時鐘線IO
u8 SDA_GPIO_BITx; //SDA數(shù)據(jù)線位,0-15
u8 SCL_GPIO_BITx; //SCL時鐘線位,0-15
u8? DelayUS; //通信延時US
}SIIC_HANDLE;
bool?SIIC_Init(SIIC_HANDLE?*pHandle,?GPIO_TypeDef?*SDA_GPIOx,?GPIO_TypeDef?*SCL_GPIOx,u8?SDA_GPIO_BITx,?u8?SCL_GPIO_BITx,u8?DelayUS); //軟件IIC初始化
void?SIIC_Start(SIIC_HANDLE?*pHandle); //產(chǎn)生IIC起始信號
void?SIIC_Stop(SIIC_HANDLE?*pHandle); //產(chǎn)生IIC停止信號
bool?SIIC_WaitAck(SIIC_HANDLE?*pHandle); //IIC等待應(yīng)答信號到來
void?SIIC_Ack(SIIC_HANDLE?*pHandle); //IIC產(chǎn)生ACK應(yīng)答
void?SIIC_NAck(SIIC_HANDLE?*pHandle); //SIIC產(chǎn)生NACK應(yīng)答
bool?SIIC_SendByte(SIIC_HANDLE?*pHandle,?u8?data); //SIIC發(fā)送一個字節(jié)
u8?SIIC_ReadByte(SIIC_HANDLE?*pHandle,bool?isAck); //SIIC讀取一個字節(jié)
#endif?/*_SOFTWARE_IIC_H_*///初始化測試
static?SIIC_HANDLE?IIC_Handel;
#define?PCF8563_SDA_GPIOx? GPIOB
#define?PCF8563_SCL_GPIOx? GPIOB
#define?PCF8563_SDA_Bit? 9
#define?PCF8563_SCL_Bit ? 8
if(SIIC_Init(&IIC_Handel,PCF8563_SDA_GPIOx,?PCF8563_SCL_GPIOx,?PCF8563_SDA_Bit,?PCF8563_SCL_Bit,?1)?==?FALSE)
{
PCF8563_Debug("**********************PCF8563?初始化失敗,IIC接口初始化失敗!rn");
return?FALSE;
}
//讀寫測試
SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_W_ADDR)==FALSE) //發(fā)送寫地址
{
PCF8563_Debug("PCF8563?發(fā)送寫地址?ACK錯誤rn");
return?FALSE;
}
if(SIIC_SendByte(&IIC_Handel,?RegIndex)==FALSE) //發(fā)送要讀取的寄存器地址
{
PCF8563_Debug("PCF8563?發(fā)送要讀取的寄存器地址2?ACK錯誤rn");
return?FALSE;
}
SIIC_Start(&IIC_Handel); //發(fā)送起始信號 




