📄 upsd_i2c.c
字号:
return value:I2C_MR_END 8 //Indicate a receiving has been finished in master modelI2C_TIME_OUT 9 //Indicate I2C overtime.I2C_NACK 13 //Indicate I2C no acknowledgeI2C_BUSLOST 14 //Indicate I2C bus lostI2C_BUSY 16 //Indicate I2C bus is busy-------------------------------------------------------------------------*/unsigned char upsd_i2c_Master_Recv (unsigned char Slave_Addr, unsigned char* Data_Ptr, unsigned char N){ EA=0; i2c_master = 1; // set up for master i2c_rcv_buf= Data_Ptr; if(upsd_i2c_Busycheck(1000)==1){ S2CON&=~STA; S2CON|=STO; dummybyte=S2DAT; i2c_state=I2C_BUSY; return (i2c_state); } // Bus busy and return current state of I2C i2c_data_len=N; // Initialize i2c_data_len to specify communicated data length i2c_master = 1; i2c_xmitr = 0; // set flags for master receiver S2DAT = (Slave_Addr | 0x01); // set up i2c address (set R/W bit) S2CON |= ENI; // Set ENI (Enable I2C-2) S2CON &= ~STO; // Clr STO in S1CON S2CON |= STA; // Set STA (Send start bit) S2CON &= ~AA; // Clr AA in S2CON i2c_data_index=0; i2c_state=I2C_MR; EA=1; if(upsd_i2c_Timeout(I2C_MR,1000)==1){ EA=0; S2CON&=~STA; S2CON|=STO; dummybyte=S2DAT; S2CON&=~ENI;S2CON|=ENI; i2c_state=I2C_TIME_OUT; return (i2c_state); } // I2C master receive timeout else { EA=0; return(i2c_state); } // return I2C current state}/*-------------------------------------------------------------------------unsigned char upsd_i2c_Slave_Xmit(unsigned char* Data_Ptr, unsigned char* N_Ptr)This function is used to transmit data to master, only for Slave.Data_Ptr - unsigned char* - address pointer of transmit bufferN_Ptr - unsigned char* - the length of data buffer transmitted to master. return value:I2C_SX_END 6 //Indicate a transmitting has been finished in Slave modelI2C_TIME_OUT 9 //Indicate I2C overtime.I2C_NACK 13 //Indicate I2C no acknowledgeI2C_BUSLOST 14 //Indicate I2C bus lostI2C_BUSY 16 //Indicate I2C bus is busy-------------------------------------------------------------------------*/unsigned char upsd_i2c_Slave_Xmit(unsigned char* Data_Ptr, unsigned char* N_Ptr){ EA=0; i2c_xmit_buf=Data_Ptr; i2c_master = 0; i2c_xmitr = 1; // set up for Slave transmitter S2CON &= ~AA; // disable ACK and STOP control bit to prepare transmit data S2CON &= ~STO; i2c_data_index=0; S2DAT = i2c_xmit_buf[i2c_data_index]; //Send first data to master i2c_data_index++; i2c_state=I2C_SX; EA=1; if(upsd_i2c_Timeout(I2C_SX,1000)==1){ EA=0; i2c_state=I2C_TIME_OUT; S2DAT=dummy; return(i2c_state); } // I2C Slave timeout return else { EA=0; *N_Ptr=i2c_data_index; S2DAT=dummy; return(i2c_state); } // return current I2C state and the length of data // buffer transmitted to master.}/*-------------------------------------------------------------------------unsigned char upsd_i2c_Slave_Recv(unsigned char* Data_Ptr, unsigned char* N_Ptr)This function is used to receive data from master, only for Slave.Data_Ptr - unsigned char* - address pointer of receive bufferN_Ptr - unsigned char* - the length of data buffer received from master. return value:I2C_TIME_OUT 9 //Indicate I2C overtime.I2C_SR_END 11 //Indicate a receiving has been finished in Slave modelI2C_NACK 13 //Indicate I2C no acknowledgeI2C_BUSLOST 14 //Indicate I2C bus lostI2C_SX_APP 15 //Indicate I2C Slave is required to transmit data to masterI2C_BUSY 16 //Indicate I2C bus is busy-------------------------------------------------------------------------*/unsigned char upsd_i2c_Slave_Recv(unsigned char* Data_Ptr, unsigned char* N_Ptr){ EA=0; i2c_rcv_buf=Data_Ptr; i2c_master = 0; i2c_xmitr = 0; // set up for Slave transmitter i2c_data_index=0; i2c_state=I2C_SR; slave_addressed = 0; S2CON|=AA;// idle_mode = 0; // indicate not in idle mode#if IDLE_MODE_DEMO // only here for idle mode demonstration purposes ET0 = 0; // disable timer 0 int. so only I2C int brings uPSD out of idle mode// idle_mode = 1; // indicate in idle mode (I2C init function and ISR clears this flag) PSD8xx_reg.DATAOUT_B&=0xFC; // PB0 & PB1 = 0 - (LEDs on)#endif EA=1;#if IDLE_MODE_DEMO // only here for idle mode demonstration purposes PCON |= 0x01; // puts uPSD in idle mode PSD8xx_reg.DATAOUT_B|=0x03; // PB0 & PB1 = 1 - (LEDs off) ET0 = 1; // enable timer 0 interrupt#endif if(upsd_i2c_Timeout(I2C_SR,1000)==1){ EA=0; i2c_state=I2C_TIME_OUT; return(i2c_state); } //Slave receive timeout else { EA=0; *N_Ptr=i2c_data_index-1; return(i2c_state); } // Return I2C current state}/*------------------------------------------------------------------------ I2C Interrupt Service Routine------------------------------------------------------------------------*/ void i2c_isr (void) interrupt I2C_VECTOR using 2 { dummybyte=S2STA; // Clear INTR flag toggle = 0; // Reset timeout counter //------Master transmit operation-------------------------------------------- if (i2c_master & i2c_xmitr) // mstr transmitter mode { S2CON &= ~STA; // clear STA if ((S2STA & BLOST) !=0) // if bus lost, read dummybyte to turn to Slave mode { S2DAT=dummy; i2c_state=I2C_BUSLOST; // Indicate the bus lost return; } else if ((S2STA & _ACKREP) !=0) { S2CON |=STO; S2DAT=dummy; // if no ACK, send STOP condition to Bus i2c_state=I2C_NACK; // Indicate no ACK return; } if((i2c_data_index)<(i2c_data_len-1)) { S2DAT = i2c_xmit_buf[i2c_data_index]; // send data from Master i2c_data_index++; // increment data-pointer } else if((i2c_data_index)==(i2c_data_len-1)) { S2CON |= STO; // set STO (stop bit) for last data byte to send S2DAT = i2c_xmit_buf[i2c_data_index]; // send data from Master i2c_data_index++; } else if((i2c_data_index)==(i2c_data_len)) { S2DAT=dummy; i2c_state=I2C_MX_END; // Indicate the operation has completed } } //------Master receive operation-------------------------------------------- if (i2c_master & ~i2c_xmitr) // master receive mode { S2CON &= ~STA; // clear STA if(i2c_data_index<i2c_data_len) { if((S2CON&AA)==0) { S2DAT=dummy; // if ((dummybyte & _ACKREP) !=0) { S2CON |=STO; i2c_data_index=0; S2DAT=dummy; i2c_state=I2C_NACK; // indicate no ACK return; } else if(i2c_data_len == 1) { S2CON&=~AA; i2c_data_index ++; return; } else { S2CON |= AA; // enable ACK i2c_data_index ++; return; } } else { // Begin receiving data i2c_rcv_buf[i2c_data_index-1] = S2DAT; // receive data i2c_data_index++; // increment data-pointer if(i2c_data_index==i2c_data_len){S2CON&=~AA;} } } else if(i2c_data_index==i2c_data_len) // End the reception of data { S2CON |=STO; i2c_rcv_buf[i2c_data_index-1] = S2DAT; i2c_state=I2C_MR_END; // indicate operation has completed } } //------Slave operation-------------------------------------------- if(i2c_master==0) { if(((S2CON&ADDR)!=0)||!i2c_processing) // if ADDR bit is set or if coming out of idle { // mode, then a START and address match detected. i2c_processing = 1; // indicate processing I2C transaction S2CON&=~ADDR; //Clear ADDR flag slave_addressed = 1; if(dummybyte & TX_MODE) { i2c_state=I2C_SX_APP; // indicate Slave is required to transmit data to master S2CON &= ~AA; // disable ACK } else { S2DAT=dummy; // Write dummy i2c_xmitr=0; // set up for Slave receive S2CON |=AA; // enable ACK to prepare receive data i2c_data_index=0; i2c_state=I2C_SR; // indicate Slave is receiving } } else { if(slave_addressed != 1) { return; } else if(i2c_xmitr==1) //Slave transmit data { if(((dummybyte&STOP)!=0)||((dummybyte&_ACKREP)!=0)) //if STOP or NACK received, then master // is done reading data from slave. { S2DAT=dummy; i2c_state=I2C_SX_END; // indicate Slave transmitted all data i2c_processing = 0; // indicate not processing I2C transaction } else { S2DAT = i2c_xmit_buf[i2c_data_index]; // Send data i2c_data_index++; // Increment data-pointer } } else if(i2c_xmitr==0) // Slave receive data mode { if((dummybyte & STOP)!=0) { S2DAT = dummy; // STOP bit received while in slave receiver mode S2CON &= ~ENI; // This disable/enable I2C is needed for transfers S2CON |= ENI; // from master without data (START-ADDR-WRITE-STOP). // This type of transfer is used by a master as a // type of device detect. If the slave ACKS, then // the device is detected by the master. i2c_state = I2C_SR_END; // Indicate the data has been received completely i2c_processing = 0; // indicate not processing I2C transaction S2CON &= ~AA; // Disable ACK. } i2c_rcv_buf[i2c_data_index] = S2DAT; // Get data byte from Master i2c_data_index++; // increment data-pointer } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -