?? upsd_i2c.c
字號:
/*----------------------------------------------------------------------------
Title: upsd_i2c.c
Date: July 22, 2002
Author: Alec Bath
Description: I2C Routines for DK3200 Board
Copyright 2002 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.
----------------------------------------------------------------------------*/
#pragma CODE // include assembly in .lst file
#pragma NOAREGS
#include "upsd3200.h"
#include "upsd_hardware.h"
#include "upsd_i2c.h"
#include "upsd_timer.h" // timer fns for timeout, etc.
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
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
//--------------------------------------------------
// I2C Initialization Routine
//--------------------------------------------------
void upsd_i2c_init (void){
P3SFS |= 0xC0; // Enable P3.7 for SCL, P3.6 for SDA
S2CON |= 0x81; // Setup I2C-2 for 83KHz (40MHz XTAL)
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
}
//--------------------------------------------------
// I2C Transmit Data Routine
//--------------------------------------------------
void upsd_i2c_xmit (unsigned char i2c_address, unsigned char start_address, unsigned char data_len){
while ((S2STA & BBUSY) != 0); // wait for BBUSY to be clear
i2c_master = 1;
i2c_xmitr = 1; // set up for master transmitter
S2DAT = i2c_address; // set up i2c address
S2CON |= ENI; // Set ENI (Enable I2C-2)
S2CON &= ~STO; // Clr STO in S2CON
S2CON |= STA; // Set STA (Send start bit)
S2CON &= ~AA; // Clr AA in S2CON
i2c_wait_for_int(); // Wait for interrupt
S2CON &= ~STA; // clear STA
S2DAT = start_address;
i2c_wait_for_int(); // Wait for interrupt
S2CON &= ~STA; // clear STA
for (i=0; i < (data_len-1); i++){
S2DAT = i2c_xmit_buf[i];
i2c_wait_for_int(); // Wait for interrupt
S2CON &= ~STA; // clear STA
}
S2CON |= STO; // set STO (stop bit)
S2DAT = i2c_xmit_buf[i]; // send last data byte
i2c_wait_for_int(); // Wait for interrupt
S2DAT = dummy; // send dummy byte
}
//--------------------------------------------------
// I2C Receive Data Routine
//--------------------------------------------------
void upsd_i2c_rcv (unsigned char i2c_address, unsigned char start_address, unsigned char data_len)
{
while ((S2STA & BBUSY) != 0); // wait for BBUSY to be clear
i2c_master = 1;
i2c_xmitr = 0; // set flags for master receiver
// set up i2c slave starting address
S2DAT = i2c_address; // set up i2c address
S2CON |= ENI; // Set ENI (Enable I2C-2)
S2CON |= STA; // Set STA (Send start bit)
S2CON &= ~AA; // Clr AA in S2CON
i2c_wait_for_int(); // Wait for interrupt
S2CON &= ~STA; // clear STA
S2CON |= STO; // set STO (stop bit)
S2DAT = start_address; // send starting address
i2c_wait_for_int(); // Wait for interrupt
S2DAT = dummy; // send dummy byte
// receive bytes from slave from starting address
S2DAT = (i2c_address | 0x01); // set up i2c address (set R/W bit)
S2CON |= ENI; // Set ENI (Enable I2C-2)
S2CON &= ~STO; // Clr STO in S2CON
S2CON |= STA; // Set STA (Send start bit)
S2CON &= ~AA; // Clr AA in S2CON
i2c_wait_for_int(); // Wait for interrupt
S2CON &= ~STA; // clear STA
S2DAT = 0xFF; // send byte for rcv mode
S2CON |= AA; // Set AA in S2CON
i2c_wait_for_int(); // Wait for interrupt
for (i=0; i < (data_len-1); i++){
dummybyte = S2STA; // Dummy Read S2STA
i2c_rcv_buf[i] = S2DAT; // Get data byte from Slave
i2c_wait_for_int(); // Wait for interrupt
}
S2CON &= ~AA; // Clr AA in S2CON
i2c_rcv_buf[i] = S2DAT; // Get last data byte
i2c_wait_for_int(); // Wait for interrupt
dummybyte = S2STA; // Dummy Read S2STA
i++;
i2c_rcv_buf[i] = S2DAT; // Get dummy data byte
}
//--------------------------------------------------
// I2C Wait for Interrupt Routine
//--------------------------------------------------
void i2c_wait_for_int (void){
i2cwait = 1; //
i2c_timeout = 0;
while (i2cwait == 1){ // .. wait for int to clear flag
if (i2c_timeout >= 10){ // 10mS timeout loop
i2c_timeout_flag = 1; // set error flag
i2cwait = 0; //
}
timer0_delay(1); // 1 mS delay
i2c_timeout++;
}
}
/*--------------------------------------------------
I2C Interrupt Service Routine
--------------------------------------------------*/
void i2c_isr (void) interrupt I2C_VECTOR using 2
{ // I2C Interrupt Routine
if ((S2STA & BLOST) == 1){
S2DAT = dummy; // send dummy byte
bus_lost_flag = 1;
}
if ((S2STA & _ACKREP) == 1){
//!1 timer0_delay(1000); // 1 Sec timeout
S2DAT = dummy; // send dummy byte
slave_nack_flag = 1;
}
if (i2c_master & i2c_xmitr){ // mstr transmitter mode
i2cwait = 0; // reset wait flag
}
if (i2c_master & ~i2c_xmitr){ // mstr receiver mode
i2cwait = 0; // reset wait flag
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -