I2C corrected
This commit is contained in:
parent
791a7820c3
commit
53663ade65
174
pic/MDR/I2C.c
174
pic/MDR/I2C.c
|
@ -11,16 +11,7 @@
|
|||
#define release_SDA() LATB |= SDA
|
||||
/* set data low */
|
||||
#define hold_SDA() LATB &= ~SDA
|
||||
|
||||
/* a small delay for better clock */
|
||||
#define WAIT 1
|
||||
/*
|
||||
void delay(void)
|
||||
{
|
||||
uint8_t wait=WAIT;
|
||||
while (wait--);
|
||||
}
|
||||
*/
|
||||
#define delay() __asm\
|
||||
nop\
|
||||
nop\
|
||||
|
@ -29,12 +20,75 @@ void delay(void)
|
|||
__endasm
|
||||
|
||||
/* read SDA
|
||||
* don't forget to set SDA as input in the begining
|
||||
* are set SDA as output in the end
|
||||
* set SDA as input in the begining
|
||||
* set SDA as output in the end
|
||||
*/
|
||||
uint8_t read_SDA(void)
|
||||
uint8_t read_ack(void)
|
||||
{
|
||||
uint8_t ack;
|
||||
hold_SCL(); /* set clock to low for SDA to change */
|
||||
TRISB |= SDA; /* set as input */
|
||||
delay(); /* wait for SDA to change */
|
||||
release_SCL(); /* SDA should be valid when clock is high */
|
||||
delay();
|
||||
/* we don't verify the SCL state as only we can drive it */
|
||||
if (PORTB&SDA) { /* read bit */
|
||||
ack = 1;
|
||||
} else {
|
||||
ack = 0;
|
||||
}
|
||||
hold_SCL(); /* put clock to low, as safe state */
|
||||
release_SDA(); /* set data to default state */
|
||||
TRISB &= ~SDA; /* set back to output */
|
||||
/* leave the output value as it is */
|
||||
return ack;
|
||||
}
|
||||
|
||||
/* sent start condition
|
||||
* falling SDA while SCL is high
|
||||
*/
|
||||
void send_start(void)
|
||||
{
|
||||
release_SCL(); /* endure SCL is high */
|
||||
delay();
|
||||
release_SDA(); /* ensure SDA is high to be able to start */
|
||||
delay();
|
||||
hold_SDA(); /* send start signal */
|
||||
}
|
||||
|
||||
/* send stop condition
|
||||
* rising SDA while SCL is high
|
||||
*/
|
||||
void send_stop(void)
|
||||
{
|
||||
hold_SDA(); /* be sure SDA is low for rising edge */
|
||||
delay();
|
||||
release_SCL(); /* be sure SCL is high */
|
||||
delay();
|
||||
release_SDA(); /* set SDA high while SCL is high */
|
||||
}
|
||||
|
||||
/* send byte and get ack (0=ack) */
|
||||
uint8_t send_byte(uint8_t byte)
|
||||
{
|
||||
uint8_t bit, ack;
|
||||
/* send every bit, MSb first */
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
hold_SCL(); /* value can change when SCL is low */
|
||||
delay();
|
||||
if (byte&0x80) {
|
||||
release_SDA(); /* set high for 1 */
|
||||
} else {
|
||||
hold_SDA(); /* set low for 0 */
|
||||
}
|
||||
delay();
|
||||
release_SCL(); /* set clock high to indicate valid value */
|
||||
byte <<= 1;
|
||||
}
|
||||
/* read ack */
|
||||
delay();
|
||||
hold_SCL(); /* set clock to low for SDA to change */
|
||||
TRISB |= SDA; /* set as input */
|
||||
delay(); /* wait for SDA to change */
|
||||
delay();
|
||||
delay();
|
||||
|
@ -42,85 +96,47 @@ uint8_t read_SDA(void)
|
|||
delay();
|
||||
/* we don't verify the SCL state as only we can drive it */
|
||||
if (PORTB&SDA) { /* read bit */
|
||||
return 1;
|
||||
ack = 1;
|
||||
} else {
|
||||
return 0;
|
||||
ack = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t read_ack(void)
|
||||
{
|
||||
uint8_t ack = 0;
|
||||
TRISB |= SDA; /* set as input */
|
||||
ack = read_SDA();
|
||||
hold_SCL(); /* put clock to low, as safe state */
|
||||
delay();
|
||||
release_SDA(); /* set output to high (default) */
|
||||
TRISB &= ~SDA; /* set back to output */
|
||||
hold_SCL();
|
||||
return ack;
|
||||
}
|
||||
|
||||
/* start bit is when SDA goes low while SCL is high */
|
||||
void send_start(void)
|
||||
{
|
||||
release_SCL();
|
||||
delay();
|
||||
release_SDA(); /* ensure SDA is high on the beginning */
|
||||
delay();
|
||||
hold_SDA();
|
||||
}
|
||||
|
||||
void send_stop(void)
|
||||
{
|
||||
hold_SDA(); /* be sure SDA is low */
|
||||
release_SCL();
|
||||
delay();
|
||||
release_SDA(); /* set SDA high while SCL is high */
|
||||
}
|
||||
|
||||
void send_1(void)
|
||||
{
|
||||
hold_SCL(); /* value can change when SCL is low */
|
||||
delay();
|
||||
release_SDA(); /* set the right state */
|
||||
delay();
|
||||
release_SCL(); /* value will be read when SCL goes high */
|
||||
}
|
||||
|
||||
void send_0(void)
|
||||
{
|
||||
hold_SCL(); /* value can change when SCL is low */
|
||||
delay();
|
||||
hold_SDA(); /* set the right state */
|
||||
delay();
|
||||
release_SCL(); /* value will be read when SCL goes high */
|
||||
}
|
||||
|
||||
/* send byte and get ack */
|
||||
uint8_t send_byte(uint8_t byte)
|
||||
{
|
||||
uint8_t bit;
|
||||
/* send every bit, MSb first */
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
if (byte&0x80) {
|
||||
send_1();
|
||||
} else {
|
||||
send_0();
|
||||
}
|
||||
byte <<= 1;
|
||||
}
|
||||
return read_ack();
|
||||
}
|
||||
|
||||
uint8_t read_byte(void)
|
||||
/* read one byte and send an ack
|
||||
* send an ack if you want to read more bytes
|
||||
* send a nack if this is the last byte read
|
||||
*/
|
||||
uint8_t read_byte(uint8_t ack)
|
||||
{
|
||||
uint8_t byte = 0;
|
||||
uint8_t bit;
|
||||
hold_SCL(); /* set clock to low for SDA to change */
|
||||
TRISB |= SDA; /* set as input */
|
||||
/* read 8 bits */
|
||||
for (bit=0; bit<8; bit++) {
|
||||
byte += read_SDA();
|
||||
delay(); /* wait for SDA to change */
|
||||
release_SCL(); /* SDA should be valid when clock is high */
|
||||
if (PORTB&SDA) { /* read bit */
|
||||
byte += 1;
|
||||
} else {
|
||||
byte += 0;
|
||||
}
|
||||
byte <<= 1;
|
||||
hold_SCL(); /* set clock to low for SDA to change */
|
||||
}
|
||||
TRISB &= ~SDA; /* set back to output */
|
||||
send_0(); /* send ack */
|
||||
if (ack) {
|
||||
hold_SDA(); /* set low for ack */
|
||||
} else {
|
||||
release_SDA(); /* set high for nack */
|
||||
}
|
||||
TRISB &= ~SDA; /* set back to output */
|
||||
delay();
|
||||
release_SCL(); /* set clock high to indicate valid value */
|
||||
delay();
|
||||
hold_SCL(); /* set clock to low for SDA to change */
|
||||
return byte;
|
||||
}
|
||||
|
|
|
@ -8,5 +8,4 @@
|
|||
void send_start(void);
|
||||
void send_stop(void);
|
||||
uint8_t send_byte(uint8_t byte);
|
||||
uint8_t read_byte(void);
|
||||
|
||||
uint8_t read_byte(uint8_t ack);
|
||||
|
|
Loading…
Reference in New Issue