📄 i2c.c
字号:
/*
-02/23/2006: Petre M.
-this file contains all the functions used in I2C communications
*/
#include "ioADE7169F16.h"
#include "extern_declarations.h"
#include "EEPROM_locations.h"
void Tx_byte3(void) {
//enable I2C
I2CMOD_bit.I2CEN=1;
//initialize the control word=1010 00 B0 0=Write operation
I2CADR = 0xa0 | ((X & 0x100)>>7);
SPI2CTx = X & 0x0ff; //sends the address
//send the byte to be written
SPI2CTx = *I2C_ptr;
return;
}
void Tx_byte2(void) {
if (N>1) {
//update the pointers
++I2C_ptr;
N=N-1;
X=X+1;
//before a new communication is started, Bit6 of SPI2CSTAT must be cleared
//even if it has not been set!?
I2CSTAT = I2CSTAT & NBit6;
Tx_byte3();
}
else {
//before a new communication is started, Bit6 of SPI2CSTAT must be cleared
//even if it has not been set!?
I2CSTAT = I2CSTAT & NBit6;
//clear bit0 of I2C_Status to show no EEPROM operation is under way
I2C_Status = I2C_Status & NBit0;
}
return;
}
//this function writes one byte at a time to EEPROM. This means that if we have to write
//N bytes, it sends N times the control word, the address and a byte
//It waits until the entire communication ends
void Tx_byte(char Nr_Bytes, int EEPROM_address,unsigned char __idata *Pointer) {
unsigned char I2C_timeout;
N=Nr_Bytes;
X=EEPROM_address;
I2C_ptr = Pointer;
//set bit0 of I2C_Status to show an EEPROM operation is under way
I2C_Status=I2C_Status | Bit0;
Tx_byte3();
I2C_timeout=0;
//stay in this loop as long as I2C communication is executed
while (I2C_Status & Bit0) {
while (I2CSTAT_bit.I2CBUSY) {
if (I2CSTAT_bit.I2CNOACK) {
//erase NoACK bit by writing over a 0
I2CSTAT = I2CSTAT & NBit6;
//set bit7 to empty the Tx FIFO
I2CSTAT = I2CSTAT | 0x80;
Tx_byte3();
}
}
Tx_byte2();
//we must ensure that if I2C communication does not function for some reason,
//we avoid remaining in an endless loop
I2C_timeout++;
if (I2C_timeout>0x80){
I2C_Status=I2C_Status & NBit0;
Meter_Errors[0] = Meter_Errors[0] | Bit0;
}
}
return;
}
//This function reads Nr_Bytes from address EEPROM_address in EEPROM and stores
//them at Pointer
//It waits until the entire communication ends
void Tx_CTRL_byte(char Nr_Bytes, int EEPROM_address,unsigned char __idata *Pointer) {
unsigned int I2C_timeout;
N = Nr_Bytes;
X = EEPROM_address;
I2C_ptr = Pointer;
//enable I2C
I2CMOD_bit.I2CEN=1;
//initialize the control word=1010 00 B0 0=Write operation
I2CADR = 0xa0 | ((X & 0x100)>>7);
SPI2CTx = X & 0x0ff; //sends the address
//set bit0 of I2C_Status to show an EEPROM operation is under way
I2C_Status=I2C_Status | Bit0;
I2C_timeout = 0;
//stay in this loop as long as I2C communication is executed
while (I2C_Status & Bit0) {
if (I2CSTAT_bit.I2CNOACK) {
//clear NoACK bit by writing over a 0
I2CSTAT = I2CSTAT & NBit6;
//set bit7 to empty the Tx FIFO
I2CSTAT = I2CSTAT | Bit7;
//enable I2C
I2CMOD_bit.I2CEN=1;
//initialize the control word=1010 00 B0 0=Write operation
I2CADR = 0xa0 | ((X & 0x100)>>7);
SPI2CTx = X & 0x0ff; //sends the address
}
if (I2CSTAT_bit.I2CTxIRQ) {
//enable I2C, put N-1 bytes to read into the register
I2CMOD = ((I2CMOD & 0xE0) | 0x80) | (N-1);
//initialize the control word=1010 00 B0 1=Read operation
I2CADR = 0xa1 | ((X & 0x100)>>7);
}
if (I2CSTAT_bit.I2CRxIRQ) {
Rx_byte();
}
I2C_timeout++;
if (I2C_timeout>0x400){
I2C_Status=I2C_Status & NBit0;
Meter_Errors[0] = Meter_Errors[0] | Bit1;
}
}
return;
}
//this function stores all the bytes that were already received
void Rx_byte(void) {
//read data from RxFIFO until it becomes empty
while (I2CSTAT & 0x0c) {
//read from Rx buffer
*I2C_ptr = SPI2CRx;
//if during this process, a FIFO location has been read and written in the same time,
//then bit1 of SPI2CSTAT has been set. If this happened, we need to restart the
//entire reading process, so we set bit1 of I2C_Status to signal this
if (I2CSTAT & Bit1) {
I2C_Status = I2C_Status | Bit1;
}
//increment pointer
++I2C_ptr;
N=N-1;
}
//if no bytes are to be received, clear the status bit
if (N==0) {
//we erase here bit0 of I2C_Status to show that the communication stopped
I2C_Status=I2C_Status & NBit0;
}
return;
}
void Setup_I2C(void)
//this function initializes the I2C and enables I2C interrupt
{
CFG_bit.SCPS = 0; //P0.4 and P0.6 are used as SDATA and SCLK for I2C
//disable the weak pull up resistors on P0.4 and P0.6
PINMAP0_bit.PINMAP04 = 1;
PINMAP0_bit.PINMAP06 = 1;
/*0=I2C disabled
11=I2C serial frequency=Fcore/128=32KHz
00000=receive nr bytes=0
*/
I2CMOD = 0x60;
IEIP2_bit.ESI = 0; //disable I2C interrupt
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -