?? i2c.c
字號:
//--------------------------------------------------------------------------------
#include <c8051f340.h>
#include <stdio.h>
typedef unsigned int uint ;
typedef unsigned char uchar;
#define SYSCLK 12000000 // 12M內(nèi)部時鐘
#define BAUDRATE 9600 // Baud rate of UART in bps
sbit SDA = P1^0;
sbit SCL = P1^1;
uchar buffer[16]; //數(shù)據(jù)存儲器
bit Ack(void); /*應答位*/
bit NAck(void); //無應答位
void delay(); //長延時
void UART0_Init (void); //UART Init
void Start(void); /*起始條件*/
void Stop(void); /*停止條件*/
void Send(uchar Data); /*發(fā)送數(shù)據(jù)子程序,Data為要求發(fā)送的數(shù)據(jù)*/
uchar Read(void); /*讀一個字節(jié)的數(shù)據(jù),并返回該字節(jié)值*/
void OSCILLATOR_Init (void); //內(nèi)部振蕩器初始化
void PORT_Init (void); //I/O初始化
void wait(int n); //精確延時
int I2cReadWriteZL(int mode,unsigned char ChipAddress,unsigned char *Data,int NbData);
void outputchar(uint order);
void selectout(uint dat);
void main (void)
{
uchar i;
uchar deviceAddr=0x1C;
uchar dat[2]={0x14,0xC0};
uchar ucBuffer[3]={0xFF};
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
PORT_Init(); // Initialize Port I/O
OSCILLATOR_Init (); // Initialize Oscillator
UART0_Init(); //Initialize UART0
delay();
delay();
}
void PORT_Init (void)
{
P1MDOUT &= 0x00; // Enable UTX as push-pull output
P0MDOUT |= 0x10;
XBR1 = 0x40; // Enable crossbar and enable
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
// weak pull-ups
}
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}
void Start(void) /*起始條件*/
{
SDA=1;
SCL=1;
wait(50);
SDA=0;
wait(50);
}
void Stop(void) /*起始條件*/
{
SDA=0;
SCL=1;
wait(50);
SDA=1;
wait(50);
}
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}
TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}
/*------長延時-----*/
void delay(void)
{
int i,j;
for(i=255;i>0;i--)
for(j=255;j>0;j--)
;
}
void wait(int n) //延長n個系統(tǒng)時鐘
{
for(;n>0;n--)
;
}
void SEND_0(void) /*發(fā)送0比特*/
{
SCL=0; //獲取總線控制權(quán)
SDA=0; //發(fā)送數(shù)據(jù)
SCL=1;
wait(50); //延時 確保從機讀取數(shù)據(jù) 具體時間視系統(tǒng)時鐘而定
SCL=0;
wait(20); //延時
}
void SEND_1(void) /*發(fā)送比特1*/
{
SCL=0;
SDA=1;
SCL=1;
wait(50);
SCL=0;
wait(20);
}
void Send(uchar Data) /*發(fā)送數(shù)據(jù)子程序,Data為要求發(fā)送的數(shù)據(jù)*/
{
char i;
for(i=0;i<8;i++)
{
if((Data<<i)&0x80)
SEND_1();
else
SEND_0();
}
}
uchar Read(void) /*讀一個字節(jié)的數(shù)據(jù),并返回該字節(jié)值*/
{
bit F0;
char b=0,i;
for(i=0;i<8;i++)
{
SDA=1; /*釋放總線*/
SCL=1; /*接受數(shù)據(jù)*/
wait(10); //等待數(shù)據(jù)建立
F0=SDA; //讀取數(shù)據(jù)
if(F0==1) //判斷存儲
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
wait(20);
SCL=0;
wait(10);
}
return b;
}
bit Ack(void) /*應答位*/
{
uchar w=40; //等待時間值
bit F0=1; //標志位
SDA=1;
SCL=1;
wait(10);
while(--w&&F0) //讀取應答位
F0=SDA;
wait(20);
SCL=0;
return F0;
}
/*無應答數(shù)據(jù)位發(fā)送子程序*/
bit NAck(void)
{
bit s=0;
SCL=0;
wait(5);
SCL=1;
SDA=1;
wait(20);
s=SDA;
wait(40);
SCL=0;
return !s;
}
/*------底層I2C讀寫子程序-----
函數(shù)為單主機主控發(fā)送接受子程序,該程序使用時總線上不可有其他主機。。。。
函數(shù)參數(shù)設(shè)置為 wr_mode--讀寫模式 char_slv_addr--從機地址 *dat--數(shù)據(jù)首地址 len----數(shù)據(jù)長度
數(shù)據(jù)地址的第一個字節(jié)一般為寄存器的地址
寫數(shù)據(jù)時--在上層函數(shù)中需要把被寫寄存器地址寫入*dat的第一個字節(jié) 寫入數(shù)據(jù)從第二個字節(jié)開始 寫入字節(jié)數(shù)不多于16個
讀數(shù)據(jù)時--需要讀取的寄存器地址存放在第一個字節(jié)中,讀取的數(shù)據(jù)存放在第一個字節(jié)中,讀取的數(shù)據(jù)會覆蓋原寄存器的地址
讀模式專用于10313和10039器件,其格式為
--發(fā)送開始標志
--發(fā)送從機地址(寫形式)
--應答位
--發(fā)送寄存器地址
--應答位
--發(fā)送開始標志
--發(fā)送從機地址(讀模式)
------------------
--應答位
--讀取寄存器數(shù)據(jù)
----------------
--無應答位
--結(jié)束標志。
----------------------------------------------------------------------------------------------------------------*/
int I2cReadWriteZL(int wr_mode, char slv_addr, char *dat, int len)
{
uchar i;
if (wr_mode == 1) //判斷讀寫功能
{
Start(); //開始標志
Send(slv_addr); //發(fā)送從機地址
for(i=0;i<len;i++)
{
if(Ack()) //讀取應答位
return 1;
Send(*dat); //發(fā)送數(shù)據(jù)
++dat;
}
NAck();
Stop(); //結(jié)束標志
if(i==len) //成功
return 0;
}
else //數(shù)據(jù)讀取
{
Start(); //開始標志位
Send(slv_addr); //從機地址
Ack();
Send(*dat); //數(shù)據(jù)發(fā)送--寄存器地址
Ack();
Start(); //開始標志
Send(slv_addr+1); //從機地址
for(i=0;i<len;i++)
{
if (Ack()) //應答位
return 1;
*dat=Read(); //數(shù)據(jù)讀取
++dat;
}
NAck();
Stop(); //結(jié)束標志
if(i==len) //成功
return 0;
}
return 1; //失敗
}
/*------輸出字符形式數(shù)據(jù)---
數(shù)據(jù)以ASCII的形式輸出
------------------------------*/
void outputchar(uint order)
{
selectout(order/16);
selectout(order%16);
}
/*獲得的數(shù)據(jù)判斷--以確定輸出字符
---------------------------------*/
void selectout(uint dat)
{
switch(dat)
{
case 0:printf("%c",'0');
break;
case 1:printf("%c",'1');
break;
case 2:printf("%c",'2');
break;
case 3:printf("%c",'3');
break;
case 4:printf("%c",'4');
break;
case 5:printf("%c",'5');
break;
case 6:printf("%c",'6');
break;
case 7:printf("%c",'7');
break;
case 8:printf("%c",'8');
break;
case 9:printf("%c",'9');
break;
case 10:printf("%c",'A');
break;
case 11:printf("%c",'B');
break;
case 12:printf("%c",'C');
break;
case 13:printf("%c",'D');
break;
case 14:printf("%c",'E');
break;
case 15:printf("%c",'F');
break;
default:printf("error");
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -