English
Language : 

CP3BT23 Datasheet, PDF (174/260 Pages) Texas Instruments – CP3BT23 Reprogrammable Connectivity Processor with Bluetooth and Dual CAN Interfaces
23.4.1 Avoiding Bus Error During Write Transaction
A Bus Error (BER) may occur during a write transaction if
the data register is written at a very specific time. The mod-
ule generates one system-clock cycle setup time of SDA to
SCL vs. the minimum time of the clock divider ratio.
The problem can be masked within the driver by dynamical-
ly dividing-by-half the SCL width immediately after the slave
address is successfully sent and before writing to the ACB-
SDA register. This has the effect of forcing SCL into the
stretch state.
The following code example is the relevant segment of the
ACCESS.bus driver addressing this issue.
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; NAME: ACBRead
Reads "Count" byte(s) from selected I2C Slave. If read address differs from previous
;
Read or Write operation (as recorded in NextAddress), a "dummy" write transaction is
;
initiated to reset the address to the desired location. This is followed by a repeated
;
Start sequence and the Read transaction. All transactions begin with a call to ACBStartX
;
which sends the Start condition and Slave address. Checks for errors throughout process.
;
; PARAMETERS: UBYTE Slave - Slave Device Address. Must be of format 0xXXXX0000
;
UWORD Addrs - Byte/Array address (extended addressing mode uses two byte address)
;
UWORD Count - Number of bytes to read
;
UBYTE *buf - Pointer to receive buffer
;
; CALLS: ACBStartX
;
; RETURNED: error status
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
UWORD ACBRead (UBYTE Slave, UWORD Addrs, UWORD Count, UBYTE *buf)
{
ACB_T *acb;
UBYTE err, *rcv;
UWORD Timeout;
te acb = (ACB_T*)ACB_ADDRESS;
if (Addrs != NextAddress) {
NextAddress = Addrs;
/* Set pointer to ACB module
*/
/* If the indicated address differs from the last
*/
/* recorded access (i.e. Random Read), we must first */
/* send a "dummy" write to the desired new address.. */
/* Update last address placeholder
*/
KeyInit();
KBD_OUT &= ~BIT0;
le /* Send start bit and Slave address...
*/
if ((err = ACBStartX (Slave | (Addrs >> 7 & 0x0E), ACB_WRITE, 0)))
return (err);
/* If unsuccessful, return error code
*/
// KBD_OUT &= ~BIT0;
acb->ACBsda = (UBYTE)Addrs;
/* Send new address byte
*/
o KBD_OUT &= ~BIT0;
Timeout = 1000;
/* Set timeout
*/
/* Wait for xmitter to be ready...zzzzzzzzz
*/
while (!(acb->ACBst & ACBSDAST) && !(acb->ACBst & ACBBER) && Timeout--);
s if (acb->ACBst & ACBBER) {
acb->ACBst |= ACBBER;
/* If a bus error occurs while sending address, clear */
/* the error flag and return error status
*/
return (ACBERR_COLLISION);
}
b KBD_OUT &= ~BIT0;
if (!Timeout)
/* If we timeout, return error
*/
return (ACBERR_TIMEOUT);
}
/* (Re)Send start bit and Slave address...
*/
if ((err = ACBStartX (Slave | (Addrs >> 7 & 0x0E), ACB_READ, Count)))
/* If error, return
*/
O return (err);
rcv = buf;
while (Count) {
/* Get address of read buffer
*/
/* Read Count bytes into user’s buffer
*/
if (Count-- == 1)
acb->ACBctl1 |= ACBACK;
/* If this the final byte, or only one requested, send */
/* the NACK bit after reception
*/
Timeout = 1000;
/* Set timeout
*/
while (!(acb->ACBst & ACBSDAST) && Timeout--);
if (!Timeout)
/* Timed out??
*/
/* YES - return error
*/
return (ACBERR_TIMEOUT);
*rcv++ = acb->ACBsda;
NextAddress++;
}
/* NO - Read byte from Recv register
*/
/* Adjust current address placeholder
*/
173
www.national.com