|
要用到IIC程序網(wǎng)上找了許多參考大多不完整,或不完善,不盡如意。參考他人程序?qū)懥艘环菽M程序,通用性強(qiáng),略做修改引腳即可移植到51單片機(jī)平臺,測試可使用多種芯片,功能完善可單個(gè)程序讀寫一個(gè)數(shù)據(jù),也可連續(xù)讀寫一組數(shù)據(jù),速度快,具有速度調(diào)節(jié)。可靠具有超時(shí)檢測,故障重啟功能。目前使用它驅(qū)動(dòng)4線OLED顯示和讀寫時(shí)鐘,達(dá)到設(shè)計(jì)目標(biāo),使用過程可以任意通斷一條線,線路恢復(fù),顯示和時(shí)鐘讀寫恢復(fù)正常。有需要高可靠性讀寫EEPRAM的可以,進(jìn)一步采用寫后復(fù)讀比對。
單片機(jī)代碼
//=====================MRI2C.h===========================
#ifndef __MRI2C_H
#define __MRI2C_H
#include "stm32f10x.h"
#include "wei_bit.h" //位帶操作
#define W_SCL PBout(8) // 定義輸出SCL引腳
#define W_SDA PBout(9) //定義輸出SDA引腳
#define R_SDA PBin(9) //定義SDA輸入用于讀取狀態(tài)
// 如果要啟用高速 I2C,則定義 IIC_HS 注釋掉下面一行降速
#define IIC_HS
// 條件編譯的代碼
#ifdef IIC_HS //電平改變后無延時(shí) 最高速度 約300Khz
#define W_SCL_H W_SCL=1
#define W_SCL_L W_SCL=0
#define W_SDA_H W_SDA=1
#define W_SDA_L W_SDA=0
#else //電平改變后延時(shí)達(dá)到減低速度目的 約100Khz
#define W_SCL_H W_SCL=1 ; IIc_Delay(10) //SCL拉高 并延時(shí)
#define W_SCL_L W_SCL=0 ; IIc_Delay(10) //SCL拉低 并延時(shí)
#define W_SDA_H W_SDA=1 ; IIc_Delay(5) //SDA拉高 加延時(shí)
#define W_SDA_L W_SDA=0 ; IIc_Delay(5) //SDA拉低 并延時(shí)
#endif
#define PCF8575_ADDRESS 0x40 //IIC的I2C從機(jī)地址
#define PCF8574_ADDRESS 0x4E //IIC的I2C從機(jī)地址
#define PCF2129_ADDRESS 0xA2 //pcf2129
#define PCF8563_ADDRESS 0xA2 //pcf8563
#define R8025_ADDRESS 0x64 //R8025
extern uint8_t IIC_EEr ; //錯(cuò)誤標(biāo)志
extern void I2C1_Init(void); // IIC初始化
extern void I2C1_Reset(void); //I2C故障重啟
extern void I2C1_Read (uint8_t ADDRESS , uint8_t addr,uint8_t *pData,uint8_t len);
extern void I2C1_Write(uint8_t ADDRESS , uint8_t addr,uint8_t *pData,uint8_t len);
#endif
//====================MRI2C.c========================
//***************模擬IIC程序************************************
/*無延時(shí),最高速度,時(shí)鐘脈寬1.25us,間歇2.5us */
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "MRI2C.h"
#include "stm32f10x_i2c.h"
uint8_t IIC_EEr = 0; //錯(cuò)誤標(biāo)志。
uint16_t EER_coner = 0; //錯(cuò)誤計(jì)數(shù)器
//*********************************************************
void IIc_Delay(uint16_t ys)
{ uint16_t ystm;
ystm=ys;
while(ystm--){}
}
//產(chǎn)生IIC起始信號
void MyI2C_Start(void)
{
W_SDA_H;
W_SCL_H;
W_SDA_L;
W_SCL_L;
}
//產(chǎn)生IIC停止信號
void MyI2C_Stop(void)
{
W_SDA_L;
W_SCL_H;
W_SDA_H;
}
/**
* 函 數(shù):I2C發(fā)送一個(gè)字節(jié)
* 參 數(shù):Byte 要發(fā)送的一個(gè)字節(jié)數(shù)據(jù),范圍:0x00~0xFF
* 返 回 值:無
*/
void MyI2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i ++)
{
W_SDA=(Byte&0x80)>>7;
Byte<<=1;
W_SCL_H;
W_SCL_L;
}
}
/**
* 函 數(shù):I2C接收一個(gè)字節(jié)
* 參 數(shù):無
* 返 回 值:接收到的一個(gè)字節(jié)數(shù)據(jù),范圍:0x00~0xFF
*/
uint8_t MyI2C_ReceiveByte(void)
{
uint8_t i, Byte = 0x00;
W_SDA_H;
for (i = 0; i < 8; i ++)
{
W_SCL_H;
Byte<<=1;
if(R_SDA)
Byte|= 0x01;
W_SCL_L;
}
return Byte;
}
/**
* 函 數(shù):I2C發(fā)送應(yīng)答位
* 參 數(shù):Byte 要發(fā)送的應(yīng)答位,范圍:0~1,0表示應(yīng)答,1表示非應(yīng)答
* 返 回 值:無
*/
void MyI2C_SendAck(uint8_t AckBit)
{
W_SDA=AckBit;
W_SCL_H;
W_SCL_L;
}
//============================================================
//等待應(yīng)答信號到來
//返回值:0,接收應(yīng)答失敗 報(bào)錯(cuò)IIC_EEr
// 1,接收應(yīng)答成功
u8 IIC_Wait_Ack(void)
{
u16 ucErrTime=0;
W_SDA_H;
W_SCL_H;
while(-R_SDA)
{
ucErrTime++;
if(ucErrTime>10000)
{
IIC_EEr = 1; //錯(cuò)誤標(biāo)志 重啟IIC
EER_coner++; //錯(cuò)誤計(jì)數(shù)器用于調(diào)試
MyI2C_Stop();
return 0;
}
}
W_SCL_L;
return 1;
}
/**
* 函 數(shù):I2C連續(xù)寫一組數(shù)據(jù)
* 參 數(shù):ADDRESS 器件碼, addr 起始寄存地址,*pData 要寫的數(shù)組,len 寫入字?jǐn)?shù)
* 返 回 值:無
*/
void I2C1_Write(uint8_t ADDRESS , uint8_t addr,uint8_t *pData,uint8_t len)
{
uint8_t i;
MyI2C_Start(); //I2C起始
MyI2C_SendByte(ADDRESS); //發(fā)送從機(jī)地址,讀寫位為0,表示即將寫入
if(IIC_Wait_Ack()) //接受應(yīng)答出錯(cuò)跳過
MyI2C_SendByte(addr); //發(fā)送寄存器地址
if(IIC_Wait_Ack()) //接受應(yīng)答出錯(cuò)跳過
for(i=len;i>0;i--){
MyI2C_SendByte(*pData);pData++;//發(fā)送要寫入寄存器的數(shù)據(jù)
IIC_Wait_Ack(); //接受應(yīng)答
}
MyI2C_Stop(); //I2C終止
}
/**
* 函 數(shù):I2C連續(xù)讀一組數(shù)據(jù)
* 參 數(shù):ADDRESS 器件碼, addr 起始寄存地址,*pData 保存數(shù)組位置,len 讀出字?jǐn)?shù)
* 返 回 值:無
*/
void I2C1_Read(uint8_t ADDRESS, uint8_t addr,uint8_t *pData,uint8_t len)
{
// uint8_t i;
MyI2C_Start(); //I2C起始
MyI2C_SendByte(ADDRESS); //發(fā)送從機(jī)地址,讀寫位為0,表示即將寫入
if(IIC_Wait_Ack()) //接受應(yīng)答出錯(cuò)退出
MyI2C_SendByte(addr); //發(fā)送寄存器地址
if(IIC_Wait_Ack()) //接受應(yīng)答出錯(cuò)退出
{ MyI2C_Start(); //I2C重復(fù)起始
MyI2C_SendByte(ADDRESS | 0x01); //發(fā)送從機(jī)地址,讀寫位為1,表示即將讀取
}
if(IIC_Wait_Ack()){ //接受應(yīng)答出錯(cuò)退出
while (len)
{
*pData = MyI2C_ReceiveByte(); //接收指定寄存器的數(shù)據(jù)
if(len == 1)
MyI2C_SendAck(1); //發(fā)送非應(yīng)答,終止從機(jī)的數(shù)據(jù)輸出
else
MyI2C_SendAck(0); //發(fā)送應(yīng)答, 繼續(xù)從機(jī)的數(shù)據(jù)輸出
pData++;
len--;
}
}
MyI2C_Stop(); //I2C終止
}
// IIC初始化
void I2C1_Init(void) {
/*開啟時(shí)鐘*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //開啟GPIOB的時(shí)鐘
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //將PB8和PB9引腳初始化為開漏輸出
/*設(shè)置默認(rèn)電平*/
GPIO_SetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9); //設(shè)置PB8和PB9引腳初始化后默認(rèn)為高電平(釋放總線狀態(tài))
}
//---------------------------------------------------------------------------------------
void I2C1_Reset(void) //I2C故障重啟
{ uint8_t i;
// 手動(dòng)操作SCL和SDA
W_SDA_L;
for (i = 0; i < 9; i++)
{
W_SCL_H;
Delay_us(1); // 延時(shí)
W_SCL_L;
Delay_us(1); // 延時(shí)
}
W_SDA_L; // l拉低SDA
Delay_us(1); // 延時(shí)
W_SCL_H;
Delay_us(1); // 延時(shí)
W_SDA_H; // 釋放SDA 產(chǎn)生停止信號 必須 用于消除重啟后I2C->SR .BUSY 位
Delay_us(1);// 延時(shí)
IIC_EEr = 0; //清除錯(cuò)誤標(biāo)志
}
/*************************例子:main.c *********************************
uint8_t buffer[7]={0,0,0,0,0,0,0};
int main(void)
{
uint8_t Data=0;
// IIC初始化
I2C1_Init();
//I2C故障重啟 消除異常狀態(tài)
I2C1_Reset();
I2C1_Write(PCF8563_ADDRESS,0,buffer, 7); // 將緩沖區(qū)數(shù)據(jù)寫入PCF8563寄存器 時(shí)鐘清零
//OLED初始化
OLED_Init();
while
{
I2C1_Read(R8025_ADDRESS,0,buffer, 7); //讀取時(shí)鐘
I2C1_Write(0x78,0x40,&Data,1); Data++; // 寫一個(gè)數(shù)據(jù) oled顯示屏驅(qū)動(dòng)測試
if (IIC_EEr == 0) //錯(cuò)誤標(biāo)志{
{ disp_p(dis);} //IIC4線oled顯示驅(qū)動(dòng)程序
else {
I2C1_Reset(); //I2C故障重啟
OLED_Init();//OLED初始化
num_REST++; //錯(cuò)誤計(jì)數(shù)
}
}
}
}
************************************************************************/
51hei.png (2.92 KB, 下載次數(shù): 9)
下載附件
2024-8-12 14:06 上傳
以上3個(gè)文件下載:
3個(gè)文件.7z
(3.4 KB, 下載次數(shù): 13)
2024-8-12 14:06 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評分
-
查看全部評分
|