📄 upsd3300_i2c.c
字号:
/*------------------------------------------------------------------------upsd3300_i2c.cVersion:October 15, 2004 Version 2.0 - Comments and include file name updates.May 2004 Version 0.4 - upsd_i2c_init() function further revised.April 2004 Version 0.3 - Comments revised. upsd_i2c_init() functionupdated. Various other changes made.February 2004 Version 0.2 - Initial ReleaseDependencies:FREQ_OSC (from upsd3300_hardware.h) - used in the calculation thatdetermines the prescaler setting for the I2C bus frequncy.Description:The uPSD I2C device driver is intended to provide a standard interrupt I/Oset of functions for the I2C unit inside the uPSD 3300 MCU. See thefunctions below for their respective descriptions.Copyright (c) 2004 ST MicroelectronicsThis example demo code is provided as is and has no warranty,implied or otherwise. You are free to use/modify any of the providedcode at your own risk in your applications with the expressed limitationof liability (see below) so long as your product using the code containsat least one uPSD product (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 ORCONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OROTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.-------------------------------------------------------------------------*/#pragma CODE #include "upsd3300.h"#include "upsd3300_hardware.h"#include "upsd3300_i2c.h"/*-------------------------------------------------------------------------Declaration of local variables-------------------------------------------------------------------------*/unsigned char* i2c_xmit_buf; // Message transmit buffer address pointerunsigned char* i2c_rcv_buf; // Message receive buffer address pointerunsigned char dummybyte; // Dummy byte static unsigned char i2c_data_len,i2c_data_index; // The length and pointer of data buffer bit i2c_master, i2c_xmitr; // Callable status flag bits // Indicate the status of I2C device, Master // or slave, Transmit or receivebit i2c_slave_addressed; // Indicate if the slave has been addressedunsigned char i2c_state; // The current state of I2C operationunsigned char i2c_sta; // Used to store the content of register S1STA // when I2C device enter into ISR. // Temporary value of S1STA in ISR.static unsigned int toggle;/*-------------------------------------------------------------------------upsd_i2c_Timeout(operation, Max_time)This function is used to indicate if the current I2C operation timed out.operation - unsigned char - current I2C operation (I2C_MX/I2C_MR/I2C_SX/I2C_SR).Max_time - unsigned int - the wait time.Returns:0: Did not time out1: Timed out -------------------------------------------------------------------------*/unsigned char upsd_i2c_Timeout(unsigned char operation,unsigned int Max_time){ toggle=0; while(i2c_state==operation) { toggle++; if(toggle>=Max_time){ return (1);} } return (0);}/*-------------------------------------------------------------------------char upsd_i2c_init (Bus_Freq, Slave_Addr)This function is used to initialize the I2C port including the specified bus frequency and slave address. This function must be called before using theI2C driver functions.Slave_Addr - unsigned char - I2C port slave addressBus_Freq - unsigned int - I2C bus frequency (KHz).Returns:0: Initialization successful 1: Input argument error-------------------------------------------------------------------------*/unsigned char upsd_i2c_init (unsigned int Bus_Freq, unsigned char Slave_Addr){ // The following table is mid points of the I2C divisor so that rounding will occur unsigned int code table[10] = {20,27,45,90,180,360,720,1440,0xffff}; unsigned char prescaler; unsigned int MCU_Freq_mem, divider, mhz, ns_clk, holdtime, no_clks; if ((Bus_Freq > 833) || (Bus_Freq < 6)) return (1); // Bad Requested range MCU_Freq_mem = (unsigned int) FREQ_OSC; // Caclualte divider needed MCU_Freq_mem = MCU_Freq_mem >> 1; // Divide Freq_osc by 2 divider = MCU_Freq_mem / Bus_Freq; prescaler = 0; while (divider > table[prescaler]) prescaler++; // Use table to calc best fit prescaler if (prescaler > 7) return(1); // Past max range - bad bus freq if (prescaler >= 4) prescaler = (prescaler-4)+0x80; // fix bit positions for S1CON S1CON = prescaler; // set I2C prescaler for specified bus freq P3SFS |= 0xC0; // Enable P3.7 for SCL, P3.6 for SDA // Calcualte S1SETUP time based on Bus_Freq and FREQ_OSC mhz = FREQ_OSC / 1000; // get Mhz number - compile time constant ns_clk = (unsigned int) 1000 / mhz; // Calc ns per clock period if (Bus_Freq <= 100) holdtime = 4000; // Use 4us Spec for slow I2C else if (Bus_Freq <= 400) holdtime = 600; // Use 600ns Spec for Fast I2C else holdtime = 160; // Use 160ns Spec for high speec I2C no_clks = holdtime / ns_clk; // Calc the number of clocks needed for hold time if (no_clks > 127) no_clks = 127; // Satuarate to max number of clocks S1SETUP = (unsigned char) no_clks | 0x80; // set start and stop detection time IPA |= 0x02; // set high priority for I2C interrupt IEA |= 0x02; // set I2C interrupt Enable bit S1ADR = Slave_Addr; // set up i2c slave address S1CON |= AA; // set Enable Acknowledge bit return(0);}/*-------------------------------------------------------------------------upsd_i2c_Master_Xmit (Slave_Addr, Data_Ptr,N)This function is used to transmit a specified amount of data to a slavewhile in Master mode.Slave_Addr - unsigned char - slave address of I2C device.Data_Ptr - unsigned char* - pointer to transimt bufferN - unsigned char - the length of data to be transmited Returns:I2C_MX_END 4 //Master Mode - transmission completeI2C_TIME_OUT 9 //I2C Timed OutI2C_NACK 13 //I2C NACK (No Acknowledge)I2C_BUSLOST 14 //I2C bus lost-------------------------------------------------------------------------*/unsigned char upsd_i2c_Master_Xmit (unsigned char Slave_Addr, unsigned char* Data_Ptr, unsigned char N){ EA=0; S1CON|=ENI; S1DAT = Slave_Addr; // Transmit I2C slave address S1CON &= ~STO; // Clr STO in S1CON S1CON |= STA; // Set STA (Send start bit) S1CON &= ~AA; // Clr AA in S1CON i2c_data_index=0; i2c_state=I2C_MX; // Set up I2C current state I2C_MX. i2c_xmit_buf=Data_Ptr; // Initialize data point of transmit buffer i2c_data_len=N; // Initialize length of data to be transmitted i2c_master = 1; i2c_xmitr = 1; // Set up for master transmitter EA=1; if(upsd_i2c_Timeout(I2C_MX,10000)==1){ S1CON&=~STA; S1CON&=~ENI;S1CON|=ENI; i2c_state=I2C_TIME_OUT; return (i2c_state); } // I2C master transmit timed out else { return(i2c_state); } // Return I2C current state} /*-------------------------------------------------------------------------upsd_i2c_Master_Recv (Slave_Addr,Data_Ptr,N)This function is used to receive a specified length of data from a slave,while in Master mode.Slave_Addr - unsigned char - slave address of I2C device.Data_Ptr - unsigned char* - address pointer of receive bufferN - unsigned char - length of the receive data buffer. Returns:I2C_MR_END 8 ////Master Mode - reception completeI2C_TIME_OUT 9 //I2C Timed OutI2C_NACK 13 //I2C NACK (No Acknowledge)I2C_BUSLOST 14 //I2C bus lost-------------------------------------------------------------------------*/unsigned char upsd_i2c_Master_Recv (unsigned char Slave_Addr, unsigned char* Data_Ptr, unsigned char N){ EA=0; S1CON|=ENI; S1DAT = (Slave_Addr | 0x01); // Set up I2C address (set R/W bit) S1CON &= ~STO; // Clr STO in S1CON S1CON |= STA; // Set STA (Send start bit) S1CON &= ~AA; // Clr AA in S1CON i2c_data_index=0; i2c_state=I2C_MR; i2c_rcv_buf= Data_Ptr; // Initialize address pointer of receive buffer i2c_data_len=N; // Length of the receive data buffer i2c_master = 1; i2c_xmitr = 0; // Set up for master mode, receive data EA=1; if(upsd_i2c_Timeout(I2C_MR,10000)==1){ S1CON&=~STA; S1CON&=~ENI;S1CON|=ENI;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -