📄 upsd3300_i2c.c
字号:
/*----------------------------------------------------------------------------
September 30, 2004
Note: This is an early version of the I2C device driver. Refer to the website
(www.st.com/psm) for the latest copy of the 3300 I2C device driver.
Title: upsd3300_i2c.c
For I2C test based on interrupt mode on uPSD3300.
Date: 5, 2003
Description: I2C Routines for DK3300 Board
Copyright (c) 2003 ST Microelectronics
This example demo code is provided as is and has no warranty,
implied or otherwise. You are free to use/modify any of the provided
code at your own risk in your applications with the expressed limitation
of liability (see below) so long as your product using the code contains
at least one uPSD products (device).
LIMITATION OF LIABILITY: NEITHER STMicroelectronics NOR ITS VENDORS OR
AGENTS SHALL BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
----------------------------------------------------------------------------*/
#include "uPSD3300.h"
#include "uPSD3300_hardware.h"
#include "uPSD3300_timer.h"
#include "uPSD3300_I2C.h"
xdata unsigned char i2c_xmit_buf[256]; // message xmit buffer
xdata unsigned char i2c_rcv_buf[256]; // message rcv buffer
unsigned int i; // array pointer
unsigned char dummybyte, i2c_timeout; // dummy byte to rcv, timeout cntr
static unsigned char i2c_data_len,data_index; // the data length and data-pointer in communication
bit i2c_init_flag, i2cwait, i2c_master, i2c_xmitr; // callable status flag bits
bit bus_lost_flag, slave_nack_flag, i2c_timeout_flag; // error flag bits
unsigned char i2c_Mx_end,i2c_Mr_end;
//--------------------------------------------------
// I2C Initialization Routine
//--------------------------------------------------
void Turbo_i2c_init (void){
P3SFS |= 0xC0; // Enable P3.7 for SCL, P3.6 for SDA
S1CON |= 0x83; // Setup I2C for 83KHz (40MHz XTAL)
S1SETUP=0x80; // set start and stop hold time for 25ns
i2c_init_flag = 1; // set init done flag
i2c_timeout_flag = 0; // clear timeout error flag
IPA |= 0x02; // set high priority for EI2C
IEA |= 0x02; // set EI2C I2C Int. Enable bit
data_index=0; // Initialize data-pointer
}
//--------------------------------------------------
// I2C Transmit Data in Master mode
//--------------------------------------------------
void Turbo_i2c_MX (unsigned char i2c_address, unsigned char data_len){
int i;
EA=0;
while ((S1STA & BBUSY) != 0); // wait for BBUSY to be clear
i2c_data_len=data_len; //Initialize i2c_data_len to specify communicated data length
i2c_master = 1;
i2c_xmitr = 1; // set up for master transmitter
i2c_Mx_end=0;
S1DAT = i2c_address; // set up i2c address
S1CON |= ENI; // Set ENI (Enable I2C-2)
S1CON &= ~STO; // Clr STO in S1CON
S1CON |= STA; // Set STA (Send start bit)
S1CON &= ~AA; // Clr AA in S1CON, because acknowledge should be provided by receiver
for(i=0;i<20000;i++);
while ((S1STA & BLOST) != 0) // wait for BBUSY to be clear
{
S1DAT = i2c_address; // set up i2c address
S1CON |= ENI; // Set ENI (Enable I2C-2)
S1CON &= ~STO; // Clr STO in S1CON
S1CON |= STA; // Set STA (Send start bit)
S1CON &= ~AA; // Clr AA in S1CON, because acknowledge should be provided by receiver
for(i=0;i<20000;i++);
}
EA=1;
while(i2c_Mx_end==0);
}
//--------------------------------------------------
// I2C Receive Data in Master mode
//--------------------------------------------------
void Turbo_i2c_MR (unsigned char i2c_address, unsigned char data_len){
while ((S1STA & BBUSY) != 0); // wait for BBUSY to be clear
i2c_data_len=data_len; //Initialize i2c_data_len to specify communicated data length
i2c_master = 1;
i2c_xmitr = 0; // set flags for master receiver
S1DAT = (i2c_address | 0x01); // set up i2c address (set R/W bit)
S1CON |= ENI; // Set ENI (Enable I2C-2)
S1CON &= ~STO; // Clr STO in S1CON
S1CON |= STA; // Set STA (Send start bit)
S1CON &= ~AA; // Clr AA in S1CON
i2c_Mr_end=0;
while(i2c_Mr_end==0);
}
//--------------------------------------------------
// I2C Transmit and receive Data in Slave mode
//--------------------------------------------------
/*
void Turbo_i2c_SXR (unsigned char i2c_address, unsigned char data_len){
while ((S1STA & BBUSY) != 0); // wait for BBUSY to be clear
i2c_data_len=data_len; //Initialize i2c_data_len to specify communicated data length
i2c_master = 0; // set up for slave
S1ADR = i2c_address; // set up i2c address
S1CON |= ENI; // Set ENI (Enable I2C-2)
S1CON |= AA; //
i2c_data_len=data_len;
}
*/
void i2c_delay(unsigned int time)
{
unsigned int i;
for(i=0;i<time;i++){};
}
/*--------------------------------------------------
I2C Interrupt Service Routine
--------------------------------------------------*/
void i2c_isr (void) interrupt I2C_VECTOR using 2 {
//------Master transmit operation--------------------------------------------
if (i2c_master & i2c_xmitr){ // mstr transmitter mode
S1STA &= ~INTR; // Clear INTR flag
if ((S1STA & BLOST) !=0){
dummybyte=S1DAT;
data_index=0;
return;
}
else if ((S1STA & _ACKREP) !=0){
S1CON |=STO;
S1DAT=dummy;
data_index=0;
i2c_delay(1000); // 1 Sec timeout
return; // if not slave ACK, cancel transmit
// May be should add some code to end the communication?
}
if((data_index)<i2c_data_len)
{
S1STA &= ~INTR; // Clear INTR flag
//STA start flag already have been cleared by i2c hardware according to spec.
S1DAT = i2c_xmit_buf[data_index]; //send data from Master
data_index++; //increment data-pointer
}
else if((data_index)==i2c_data_len)
{
S1CON |= STO; // set STO (stop bit) for lase one data byte to send
S1DAT = dummy; // send dummy byte
data_index=0; // reset data-pointer
i2c_Mx_end=1;
}
}
//------Master receive operation--------------------------------------------
if (i2c_master & ~i2c_xmitr){ // mstr receiver mode
S1STA &= ~INTR; // Clear INTR flag
if(data_index<i2c_data_len)
{
if((S1CON&AA)==0){S1CON |= AA;dummybyte = S1DAT;return;} //if this is TR_INT (address information send completely), allow ACK to prepare receive data
else{
//Begin reveive data
//STA start flag already have been cleared by i2c hardware according to spec.
P1_7=1; //generate a squarewave at P1.7 for confirmation I2C interrupt function at Master receive mode
i2c_rcv_buf[data_index] = S1DAT; //receive data
data_index++; //increment data-pointer
P1_7=0;
if((data_index)==i2c_data_len){S1CON&=~AA;S1CON|=STO;} //disable ACK to prepare receive lase one data byte
}
if((S1STA&STOP)!=0){data_index=0;return;}
}
else if(data_index==i2c_data_len) //receive last one data
{
P1_7=1;
dummybyte = S1DAT; // dummy read
data_index=0; // reset data-pointer
i2c_Mr_end=1;
P1_7=0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -