I2CBus是一般微處理器常用的溝通介面,因為使用的I/O腳PIN很少,只需要SDA,SCL這兩隻腳PIN,所以廣為控制器使用,以下由我使用Keil C寫了一些I2C的Driver,有心人士可以研究參考。
#include <AT89X51.H>
/*====================================
AT89C51 I2CBus Control by Henry Chou
Pins function define
=====================================*/
sbit SB_SDA = P1 ^ 0;
sbit SB_SCL = P1 ^ 1;
sbit RST_35010A = P1 ^ 2;
sbit SPI_Q = P1 ^ 4;
sbit SPI_D = P1 ^ 5;
sbit SPI_C = P1 ^ 6;
sbit SPI_S = P1 ^ 7;
sbit PLAY_KEY = P2 ^ 0;
sbit STOP_KEY = P2 ^ 1;
/*====================================
Serial Bus Control Function
=====================================*/
void SBUS_start(void);
void SBUS_stop(void);
bool SBUS_shift_out_byte(unsigned char);
bool SBUS_select_index(unsigned char, unsigned char);
int SBUS_read_data(unsigned char, unsigned char);
bool SBUS_write_data(unsigned char, unsigned char, unsigned char);
/********************************************/
/* 2-wire Serial Bus basic function */
/********************************************/
/* P1.0 SDA */
/* P1.1 SCL */
/* */
/* Note : */
/* The serial bus only 2 logical */
/* 0 : output low */
/* Z : input mode and pull-up */
/* */
/* So, if SDA or SCL is assigned '1', */
/* it is input mode and using pull-up */
/* */
/* [S] : START */
/* [P] : STOP */
/* [R] : READ (1) */
/* [W] : WRITE (0) */
/* [ADDR] : device address (7-bit) */
/* [DATA] : 8-bit data */
/* [INDEX]: 8-bit data */
/* [A] : ACK (acknowledge) */
/* [NA] : NACK (none-acknowledge) */
/* */
/********************************************/
void SBUS_start(void)
{
SB_SDA = 0;
SB_SCL = 0;
}
void SBUS_stop(void)
{
SB_SDA = 0;
SB_SCL = 1;
while ( SB_SCL == 0 ); /* wait device(35010A) release SCL */
SB_SDA = 1;
}
bool SBUS_shift_out_byte(unsigned char data_byte)
{
unsigned char i;
for ( i = 0 ; i < 8 ; i++ )
{
if ( data_byte & 0x80 )
{
SB_SDA = 1;
}
else
{
SB_SDA = 0;
}
SB_SCL = 1; /* release SCL , SCL pulse */
while ( SB_SCL == 0 ); /* wait device release SCL */
SB_SCL = 0; /* SCL pulse complete */
data_byte = data_byte << 1; /* shift next bit */
}
/* ACK */
SB_SDA = 1;
SB_SCL = 1;
while ( SB_SCL == 0 ); /* wait device release SCL */
if ( SB_SDA == 1 )
{
SB_SCL = 0;
SBUS_stop();
return (false); /* non-acknowledge */
}
else
{
SB_SCL = 0;
return(true);
}
}
bool SBUS_select_index(unsigned char device_addr, unsigned char index_reg)
{
/* START */
SBUS_start();
/* ADDR + R/W */
if ( !SBUS_shift_out_byte( device_addr << 1 ) ) /* WRITE */
{
return (false);
}
/* INDEX */
if ( !SBUS_shift_out_byte( index_reg ) )
{
return (false);
}
/* STOP */
SBUS_stop();
return (true);
}
int SBUS_read_data(unsigned char device_addr, unsigned char index_reg)
{
unsigned char i;
unsigned char read_data;
if ( !SBUS_select_index( device_addr , index_reg) )
{
return (-1);
}
/* START */
SBUS_start();
/* ADDR + R/W */
if ( !SBUS_shift_out_byte( (device_addr << 1) | 0x01 ) ) /* READ */
{
return (-1);
}
/* SHIFT IN DATA */
for ( i = 0 ; i < 8 ; i++ )
{
read_data = read_data << 1;
SB_SCL = 1; /* shift in SCL pulse */
while ( SB_SCL == 0 ); /* wait device release SCL */
if ( SB_SDA == 1 ) /* SCL high, get SDA data bit */
{
read_data = read_data | 0x01;
}
SB_SCL = 0; /* SCL pulse complete */
}
SB_SDA = 1; /* response NACK to 35010A */
SB_SCL = 1; /* ACK/NACK SCL pulse */
while ( SB_SCL == 0 ); /* wait device release SCL */
SB_SCL = 0; /* SCL pulse complete */
/* STOP */
SBUS_stop();
return ((int)read_data);
}
bool SBUS_write_data(unsigned char device_addr, unsigned char index_reg, unsigned char data_reg)
{
/* START */
SBUS_start();
/* ADDR + R/W */
if ( !SBUS_shift_out_byte( device_addr << 1 ) ) /* WRITE */
{
return (false);
}
/* INDEX */
if ( !SBUS_shift_out_byte( index_reg ) )
{
return (false);
}
/* DATA */
if ( !SBUS_shift_out_byte( data_reg ) )
{
return (false);
}
/* STOP */
SBUS_stop();
return (true);
}
#include <AT89X51.H>
/*====================================
AT89C51 I2CBus Control by Henry Chou
Pins function define
=====================================*/
sbit SB_SDA = P1 ^ 0;
sbit SB_SCL = P1 ^ 1;
sbit RST_35010A = P1 ^ 2;
sbit SPI_Q = P1 ^ 4;
sbit SPI_D = P1 ^ 5;
sbit SPI_C = P1 ^ 6;
sbit SPI_S = P1 ^ 7;
sbit PLAY_KEY = P2 ^ 0;
sbit STOP_KEY = P2 ^ 1;
/*====================================
Serial Bus Control Function
=====================================*/
void SBUS_start(void);
void SBUS_stop(void);
bool SBUS_shift_out_byte(unsigned char);
bool SBUS_select_index(unsigned char, unsigned char);
int SBUS_read_data(unsigned char, unsigned char);
bool SBUS_write_data(unsigned char, unsigned char, unsigned char);
/********************************************/
/* 2-wire Serial Bus basic function */
/********************************************/
/* P1.0 SDA */
/* P1.1 SCL */
/* */
/* Note : */
/* The serial bus only 2 logical */
/* 0 : output low */
/* Z : input mode and pull-up */
/* */
/* So, if SDA or SCL is assigned '1', */
/* it is input mode and using pull-up */
/* */
/* [S] : START */
/* [P] : STOP */
/* [R] : READ (1) */
/* [W] : WRITE (0) */
/* [ADDR] : device address (7-bit) */
/* [DATA] : 8-bit data */
/* [INDEX]: 8-bit data */
/* [A] : ACK (acknowledge) */
/* [NA] : NACK (none-acknowledge) */
/* */
/********************************************/
void SBUS_start(void)
{
SB_SDA = 0;
SB_SCL = 0;
}
void SBUS_stop(void)
{
SB_SDA = 0;
SB_SCL = 1;
while ( SB_SCL == 0 ); /* wait device(35010A) release SCL */
SB_SDA = 1;
}
bool SBUS_shift_out_byte(unsigned char data_byte)
{
unsigned char i;
for ( i = 0 ; i < 8 ; i++ )
{
if ( data_byte & 0x80 )
{
SB_SDA = 1;
}
else
{
SB_SDA = 0;
}
SB_SCL = 1; /* release SCL , SCL pulse */
while ( SB_SCL == 0 ); /* wait device release SCL */
SB_SCL = 0; /* SCL pulse complete */
data_byte = data_byte << 1; /* shift next bit */
}
/* ACK */
SB_SDA = 1;
SB_SCL = 1;
while ( SB_SCL == 0 ); /* wait device release SCL */
if ( SB_SDA == 1 )
{
SB_SCL = 0;
SBUS_stop();
return (false); /* non-acknowledge */
}
else
{
SB_SCL = 0;
return(true);
}
}
bool SBUS_select_index(unsigned char device_addr, unsigned char index_reg)
{
/* START */
SBUS_start();
/* ADDR + R/W */
if ( !SBUS_shift_out_byte( device_addr << 1 ) ) /* WRITE */
{
return (false);
}
/* INDEX */
if ( !SBUS_shift_out_byte( index_reg ) )
{
return (false);
}
/* STOP */
SBUS_stop();
return (true);
}
int SBUS_read_data(unsigned char device_addr, unsigned char index_reg)
{
unsigned char i;
unsigned char read_data;
if ( !SBUS_select_index( device_addr , index_reg) )
{
return (-1);
}
/* START */
SBUS_start();
/* ADDR + R/W */
if ( !SBUS_shift_out_byte( (device_addr << 1) | 0x01 ) ) /* READ */
{
return (-1);
}
/* SHIFT IN DATA */
for ( i = 0 ; i < 8 ; i++ )
{
read_data = read_data << 1;
SB_SCL = 1; /* shift in SCL pulse */
while ( SB_SCL == 0 ); /* wait device release SCL */
if ( SB_SDA == 1 ) /* SCL high, get SDA data bit */
{
read_data = read_data | 0x01;
}
SB_SCL = 0; /* SCL pulse complete */
}
SB_SDA = 1; /* response NACK to 35010A */
SB_SCL = 1; /* ACK/NACK SCL pulse */
while ( SB_SCL == 0 ); /* wait device release SCL */
SB_SCL = 0; /* SCL pulse complete */
/* STOP */
SBUS_stop();
return ((int)read_data);
}
bool SBUS_write_data(unsigned char device_addr, unsigned char index_reg, unsigned char data_reg)
{
/* START */
SBUS_start();
/* ADDR + R/W */
if ( !SBUS_shift_out_byte( device_addr << 1 ) ) /* WRITE */
{
return (false);
}
/* INDEX */
if ( !SBUS_shift_out_byte( index_reg ) )
{
return (false);
}
/* DATA */
if ( !SBUS_shift_out_byte( data_reg ) )
{
return (false);
}
/* STOP */
SBUS_stop();
return (true);
}