?? 24c02.c
字號:
/*====================================
下為此程序的說明
功能:I2C總線驅(qū)動
版本:Ver 1.0
日期:2007年
說明:由楊德富編寫,在硬件(24C04)上通過。但是在PROTEUS中不通過。
====================================*/
#define uint unsigned int
#define uchar unsigned char
#include<reg52.h>
#include<intrins.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define NOP _nop_(); _nop_(); _nop_()
//定義數(shù)碼管的段選
uchar code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//全局變量的定義
//uchar Step = 50;
bit ack; //應(yīng)答信號檢測
//位操作定義
sbit SDA = P1^0;
sbit SCL = P1^1; //24C04的操作線
/*====================================
非關(guān)鍵函數(shù)申明
====================================*/
void Initial(void); //系統(tǒng)初始化
void Delay(uint n); //普通延時
void Disp(uchar num); //顯示數(shù)據(jù)
/*====================================
24C04函數(shù)申明
====================================*/void Start_I2C(void);
void Stop_I2C(void);
void SendByte(uchar fdata); /*24C04子函數(shù)*/
uchar RecByte(void);
void Ack_I2C(bit a);
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);
bit RecStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);
/*====================================
函數(shù)功能:主函數(shù)
入口參數(shù):
說 明 :
=====================================*/
main()
{
uchar Rec_data[2];
uchar Sen_data[2]={1,4};
uchar *ptr;
ptr = Sen_data;
Initial(); //初始化
SendStr(0xa0, 0x20,ptr,2); /*24C04的20H*/
Delay(100);
Delay(100);
ptr=Rec_data;
RecStr(0xa1,0x20,ptr,2);
while(1)
{
P2=tab[Rec_data[0]];
}
}
//初始化
void initial(void)
{
P1=0xff;
P0=0xff;
P2=0xff;
P3=0xff;
}
//////////////////////////////////////
void Delay(uint n) //延時主函數(shù)
{
uchar i,k;
for(k=0;k<n;k++)
{
for(i=0;i<200;i++);
}
}
/*************************************************************************************
對24C04進(jìn)行讀寫操作子函數(shù)
*************************************************************************************/
/*******************************************************************
void Start_I2C();
啟動I2C總線,即發(fā)送I2C起始條件。
********************************************************************/
void Start_I2C()
{
SDA = 1; /*發(fā)送起始條件的數(shù)據(jù)信號*/
_nop_();
SCL = 1;
_nop_(); /* 起始條件建立時間大于4us,延時 */
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 0; /* 發(fā)送起始信號 */
_nop_(); /* 起始條件鎖定時間大于4 us */
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0; /* 準(zhǔn)備發(fā)送或接收數(shù)據(jù) */
_nop_();
_nop_();
}
/*******************************************************************
void Stop_I2C();
結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件。
********************************************************************/
void Stop_I2C()
{
SDA = 0; /* 發(fā)送結(jié)束條件的數(shù)據(jù)信號 */
_nop_(); /* 發(fā)送結(jié)束條件的時鐘信號 */
SCL = 1; /* 結(jié)束條件建立時間大于4 us */
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1; /* 發(fā)送I2C總線結(jié)束信號 */
_nop_();
_nop_();
_nop_();
_nop_();
}
/*******************************************************************
void SendByte(uchar data);
將數(shù)據(jù)data發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對此狀態(tài)
位進(jìn)行操作。(不應(yīng)答或非應(yīng)答都使ack = 0) 發(fā)送數(shù)據(jù)正常,ack=1;ack=0
表示接收器無應(yīng)答或損壞。
********************************************************************/
void SendByte(uchar fdata)
{
uchar BitCount;
ack=0;
for(BitCount = 0; BitCount < 8; BitCount ++) /* 要傳送的數(shù)據(jù)長度為8位 */
{
if((fdata << BitCount) & 0x80) SDA = 1; /* 判斷發(fā)送位 */
else SDA = 0;
_nop_();
SCL = 1; /* 置時鐘線為高,通知被控器開始接收數(shù)據(jù)位 */
_nop_();
_nop_(); /* 保證時鐘高電平周期大于4 us */
_nop_();
_nop_();
_nop_();
SCL = 0;
}
_nop_();
_nop_();
SDA = 0; /* 8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/
SCL=0;
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
NOP;
if(SDA == 1) ack = 0; /* 無應(yīng)答信號 */
else ack = 1; /* 判斷是否接收到應(yīng)答信號*/
ack=1;
SCL=0;
_nop_();
_nop_();
}
/*******************************************************************
uchar RecByte();
功能:
用來接收從器件傳來的數(shù)據(jù),并判斷總線錯誤(不發(fā)應(yīng)答信號),發(fā)完后請用
應(yīng)答函數(shù)。
********************************************************************/
uchar RecByte()
{
uchar RecData;
uchar BitCount;
RecData = 0;
SDA = 1; /* 置數(shù)據(jù)線為輸入方式 */
for(BitCount = 0; BitCount < 8; BitCount ++)
{
_nop_();
SCL=0; /* 置時鐘線為低,準(zhǔn)備接收數(shù)據(jù)位 */
_nop_();
_nop_(); /* 時鐘低電平周期大于4.7us */
_nop_();
_nop_();
_nop_();
SCL= 1; /* 置時鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效 */
_nop_();
_nop_();
if(SDA==1) RecData = RecData +1; /* 讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中 */
RecData = RecData << 1;
_nop_();
_nop_();
}
SCL= 0;
_nop_();
_nop_();
return(RecData);
}
/********************************************************************
void Ack_I2C(bit a);
主控器進(jìn)行應(yīng)答信號,,(可以是應(yīng)答或非應(yīng)答信號)
/********************************************************************/
void Ack_I2C(bit a)
{
if(a == 0) SDA = 0; /* 在此發(fā)出應(yīng)答或非應(yīng)答信號 */
else SDA=1;
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_(); /* 時鐘低電平周期大于4us */
_nop_();
_nop_();
_nop_();
SCL = 0; /* 清除時鐘線,以便繼續(xù)接收 */
_nop_();
_nop_();
}
/*******************************************************************
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);
從啟動總線到發(fā)送地址,子地址,數(shù)據(jù),結(jié)束總線的過程。
Slave--從器件地址
SubAddress--子地址
Source--指向發(fā)送內(nèi)容的指針
Num--發(fā)送字節(jié)個數(shù)
返回值:
如果返回1表示操作成功,否則操作有誤。
********************************************************************/
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num)
{
uchar i;
Start_I2C(); /* 啟動總線 */
SendByte(Slave); /* 發(fā)送器件地址 */
if(ack == 0) return(0);
SendByte(SubAddress); /* 發(fā)送器件子地址 */
if(ack == 0) return(0);
for(i = 0; i < Num; i++)
{
SendByte(*Source); /* 發(fā)送數(shù)據(jù) */
if(ack == 0) return(0);
Source ++;
}
Stop_I2C(); /* 結(jié)束總線 */
return(1);
}
/*******************************************************************
bit RecStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num);
從啟動總線到發(fā)送地址,子地址,讀數(shù)據(jù),結(jié)束總線的過程。
參數(shù):
Slave--從器件地址。
SubAddress--子地址
Source--指向讀出的內(nèi)容放入的存儲區(qū)的指針
Num--讀字節(jié)個數(shù)。
返回值:
如果返回1表示操作成功,否則操作有誤。
********************************************************************/
bit RecStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num)
{
uchar i;
Start_I2C(); /* 啟動總線 */
SendByte(Slave-1); /* 發(fā)送器件地址 */
if(ack == 0) return(0);
SendByte(SubAddress); /* 發(fā)送器件子地址 */
if(ack == 0) return(0);
Start_I2C();
SendByte(Slave);
if(ack == 0) return(0);
for(i = 0; i < Num-1; i++)
{
*Source = RecByte(); /* 接收數(shù)據(jù) */
Ack_I2C(0); /* 發(fā)送就答位 */
Source++;
}
*Source =RecByte();
Ack_I2C(1); /* 發(fā)送非應(yīng)位 */
Stop_I2C(); /* 結(jié)束總線 */
return(1);
}
/*****************************************************************************
--------------------------------程序結(jié)束-------------------------------------
*****************************************************************************/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -