📄 i2c.c
字号:
/********************** I2C总线基本操作函数******************************
[文件名] I2C.c+I2C.H+ASMselect.h
[版本] TV0.2
[修正] hxc
hxc last change time 2006.4.10 x:x
hxc last check time 2006.4.24 17:00
***************************************************************************/
#include "ASMselect.h "
#if ASMI2C
#include <intrins.h>
#include <reg51x.h>
#include <stdio.h>
#include <i2c.h>
#include "TAB.h"
#include "78e65.h"
sbit SCL = P4^1;
sbit SDA = P4^0;
bit i2cok;//extern bit i2cok
/****************************************************************************
* 函数原型: void delay(void);
* 功 能: 本函数实际上只有一条返回指令, 在具体应用中可视具体要求增加延时
* 指令。
****************************************************************************/
void delay( void ) {
_nop_();_nop_();//_nop_();_nop_();
//_nop_();_nop_();_nop_();_nop_();
}
/****************************************************************************
* 函数原型: void wait_5ms(void);
* 功 能: 提供5ms延时(时钟频率为12MHz)。写入一个数据之后的延时
*****************************************************************************/
#if ASMI2C_wait_5ms
void wait_5ms( void ) { //现是5ms
int i ;
for ( i=0 ; i<1000 ; i++ ) {
;
}
}
#endif
#if ASMI2C_wait_1ms
void wait_1ms( void ) { //现是1ms,只用于连续存入函数
int i ;
for ( i=0 ; i<200 ; i++ ) {
;
}
}
#endif
/****************************************************************************
* 函数原型: void I_start(void);
* 功 能: 提供I2C总线工作时序中的起始位。
****************************************************************************/
void I_start( void ) {
SCL = HIGH ;
SDA= HIGH ;
delay() ;
SDA = LOW ;
delay() ;
SCL = LOW ;
delay() ;
}
/****************************************************************************
* 函数原型: void I_stop(void);
* 功 能: 提供I2C总线工作时序中的停止位。
****************************************************************************/
void I_stop( void ) {
SDA = LOW ;
SCL = HIGH ;
delay() ;
SDA = HIGH ;
delay() ;
}
/****************************************************************************
* 函数原型: bit I_clock(void);
* 功 能: 提供I2C总线的时钟信号, 并返回在时钟电平为高期间SDA 信号线上状
* 态。本函数可用于数据发送, 也可用于数据接收。
****************************************************************************/
bit I_clock( void ) {
bit sample ;
SCL = HIGH ;
delay() ;
sample = SDA ;
SCL = LOW ;
delay() ;
return ( sample ) ;
}
/****************************************************************************
* 函数原型: bit I_send(uchar Idata);
* 功 能: 向I2C总线发送8位数据, 并请求一个应答信号ACK。如果收到ACK应答
* 则返回1(TRUE), 否则返回0(FALSE)。
****************************************************************************/
bit I_send( uchar Idata ) {
uchar i ;
/* 发送8位数据 */
for ( i=0 ; i<8 ; i++ ) {
SDA = (bit)( Idata & 0x80 ) ;
Idata = Idata << 1 ;
I_clock() ;
}
/* 请求应答信号ACK */
SDA = HIGH ;
return ( WaitAck());//(~I_clock() );
}
/****************************************************************************
* 函数原型: bit WaitAck(void);
* 功 能: 请求一个应答信号ACK。如果收到ACK应答
* 则返回1(TRUE), 否则返回0(FALSE)。
****************************************************************************/
bit WaitAck(void)
{
bit HiLo=1;
unsigned char errtime=255;//因故障接收方无ACK,超时值为255。
SDA=1; //SDA -...(wait LOW ).._ timeout error_overtime=0x11
SCL=1; //SCL -... ...\ '
while(SDA)
{
errtime--;
if(!errtime)
{
I_stop();
//出错后给全局变量赋值
HiLo=0;
break;
}
}
SCL=0;
return(HiLo);
}
/****************************************************************************
* 函数原型: uchar I_receive(void);
* 功 能: 从I2C总线上接收8位数据信号, 并将接收到8位数据作为一个字节
* 返回, 不回送应答信号ACK。主函数在调用本函数之前应保证SDA信
* 号线处于浮置状态, 即使8051的P1.7脚置1。
****************************************************************************/
uchar I_receive( void ) {
uchar I_data = 0 ;
//register
uchar i ;
for ( i=0 ; i<8 ; i++ ) {
I_data *= 2 ;
if (I_read_1bit()) I_data++ ;
}
return ( I_data ) ;
}
/****************************************************************************
* 函数原型: void I_Ack(void);
* 功 能: 向I2C总线发送一个应答信号ACK, 一般用于连续数据读取时。
*****************************************************************************/
void I_Ack( void ) {
SDA = LOW ;
I_clock() ;
SDA = HIGH ;
}
/****************************************************************************
* 函数原型: I_read_1bit(void);
* 功 能: 向I2C总线读取一位数据并返回。
****************************************************************************/
bit I_read_1bit(void){
bit sample ;
SCL = LOW ;
delay() ;
SCL = HIGH ;
delay() ;
sample = SDA ;
SCL = LOW ;
delay() ;
return ( sample ) ;
}
/****************************************************************************
* 函数原型: bit E_address(uchar Address);
* 功 能: 向24C04写入器件地址和一个指定的字节地址。
*****************************************************************************/
#if ASMI2C_E_address
bit E_address( uchar Device_WRITE_id,uchar Address ) {
I_start() ;
if ( I_send( Device_WRITE_id ) )
{
return ( I_send( Address ) ) ;
}
else
{
return ( FALSE );}
}
#endif
/****************************************************************************
* 函数原型: bit i2c_writedata(uchar Address,uchar i2cdata)
* 功 能: i2cdata写入Address内,ok返回1。
*****************************************************************************/
#if ASMI2C_writedata
bit i2c_writedata(uchar Device_WRITE_id,uchar Address,uchar i2cdata)
{
uchar D_id;
I_init(); /* I2C 总线初始化 */
D_id=Device_WRITE_id;
if ( E_address(D_id,Address) && I_send(i2cdata) ) {
I_stop();
wait_5ms();
return (TRUE);
}
else {
return ( FALSE );
}
}
/*************************************
***************************************
* 函数原型: void I_init(void);
* 功 能: I2C总线初始化。在main()函数中应首先调用本函数, 然后再调用
* 其它函数。
****************************************************************************/
void I_init( void ) {
SCL = LOW ;
I_stop() ;
}
#endif
/****************************************************************************
* 函数原型: uchar i2c_READdata(uchar Address)
* 功 能: 正确读取指定地址的数据i2cok=1并返回数据,否则i2cok=0
*****************************************************************************/
#if ASMI2C_READdata
uchar i2c_READdata(uchar Device_READ_id,uchar Address)
{
uchar icdata,D_id; /* 从地址Address开始读取数据 */
D_id=Device_READ_id&0xfe;
if ( E_address( D_id,Address ) )
{
/* 发送重复启动信号 */
I_start() ;
if ( I_send( Device_READ_id ) ) {
icdata= I_receive();
I_clock();
I_stop();
i2cok=1;
return (icdata);
}
else {
I_stop();
i2cok=0;
}
}
else{
I_stop();
i2cok=0;
}
}
#endif
/****************************************************************************
* 函数原型: bit E_read_block(void); 连续读取数据
* 功 能: 从device中读取uccount个字节的数据并转存于* pucbuf_data
* 单元, 采用序列读操作方式从片内ucaddress地址开始连续读取数据。如果
* device ucid不接受指定的地址则返回0(FALSE)。
*****************************************************************************/
#if ASMI2C_read_block
bit i2c_read_block( uchar ucid,uchar ucaddress,uchar uccount, char *pucbuf_data) {
uchar i ;
uchar *pucbuf_temp;
//* 从地址ucaddress开始读取数据 *
if ( E_address(ucid++, ucaddress ) ) {
//* 发送重复启动信号 *
I_start() ;
if ( I_send( ucid ) ) {
pucbuf_temp = pucbuf_data;
for ( i=0 ; i<uccount ; i++ ) {
*pucbuf_data = ( I_receive() ) ;
#if debug
printf("\nR%bx=%bx",i,*pucbuf_data);
#endif
pucbuf_data++;
if ( i < uccount-1 ) I_Ack() ;
else {
I_clock() ;
I_stop() ;
}
}
return ( TRUE ) ;
}
else {
I_stop() ;
return ( FALSE ) ;
}
}
else
I_stop() ;
return ( FALSE ) ;
}
#endif
/****************************************************************************
* 函数原型: bit E_write_block; 连续存入数据
* 功 能: 将* pucbuf_data 单元中的数据写入到ucid 的ucaddress地址uccount个字节。
* 采用字节写操作方式, 每次写入时都需要指定片内地址。如果device
* 不接受指定的地址或某个传送的字节未收到应答信号ACK, 则返回0
* (FALSE)。
*****************************************************************************/
#if ASMI2C_write_block
bit i2c_write_block(uchar ucid,uchar ucaddress,uchar uccount, uchar * pucbuf_data) {
uchar i;
//I_init(); /* I2C 总线初始化 */
for ( i=0 ; i<uccount ; i++ ) {
if (( E_address(ucid,ucaddress+i))&&(I_send( * pucbuf_data ) )){
#if debug
printf("\nT%bx=%bx",i,*pucbuf_data);
#endif
pucbuf_data++;
I_stop() ;
wait_1ms();
}
else {
I_stop() ;
wait_1ms();
return ( FALSE ) ;
}
}
return ( TRUE ) ;
}
#endif
/*
//此24c16,连续存入时,在地址0x0f以后的数据无法存入
bit i2c_write_block(uchar ucid,uchar ucaddress,uchar uccount, uchar * pucbuf_data) {
uchar i ;
I_init(); // I2C 总线初始化
if ( E_address(ucid,ucaddress) ){
for ( i=0 ; i<uccount ; i++ ) {
if (I_send( * pucbuf_data ) ) {
#if debug
printf("\nT%bx=%bx",i,*pucbuf_data);
#endif
pucbuf_data++;
}
else {
I_stop() ;
wait_5ms();
return ( FALSE ) ;
}
}
}
else {
I_stop() ;
wait_5ms();
return ( FALSE ) ;
}
I_stop();
wait_5ms();
return ( TRUE ) ;
}//*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -