aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKing Kévin <kingkevin@cuvoodoo.info>2014-08-02 13:33:22 -0700
committerKing Kévin <kingkevin@cuvoodoo.info>2014-08-02 13:33:22 -0700
commit53663ade65a4938384dc1b583d3dbcd211540725 (patch)
tree7ad152f8a9951c0cfe2b3bf6736358c6314c47e4
parent791a7820c3b0e495a0828e2ada5a8b6619220912 (diff)
I2C corrected
-rw-r--r--pic/MDR/I2C.c132
-rw-r--r--pic/MDR/I2C.h3
2 files changed, 75 insertions, 60 deletions
diff --git a/pic/MDR/I2C.c b/pic/MDR/I2C.c
index c644dc9..3da593e 100644
--- a/pic/MDR/I2C.c
+++ b/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,98 +20,123 @@ 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 */
- delay();
- delay();
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 */
- 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 */
+ release_SDA(); /* set data to default state */
TRISB &= ~SDA; /* set back to output */
- hold_SCL();
+ /* leave the output value as it is */
return ack;
}
-/* start bit is when SDA goes low while SCL is high */
+/* sent start condition
+ * falling SDA while SCL is high
+ */
void send_start(void)
{
- release_SCL();
+ release_SCL(); /* endure SCL is high */
delay();
- release_SDA(); /* ensure SDA is high on the beginning */
+ release_SDA(); /* ensure SDA is high to be able to start */
delay();
- hold_SDA();
+ 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 */
- release_SCL();
+ hold_SDA(); /* be sure SDA is low for rising edge */
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 */
+ release_SCL(); /* be sure SCL is high */
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 */
+ release_SDA(); /* set SDA high while SCL is high */
}
-/* send byte and get ack */
+/* send byte and get ack (0=ack) */
uint8_t send_byte(uint8_t byte)
{
- uint8_t bit;
+ 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) {
- send_1();
+ release_SDA(); /* set high for 1 */
} else {
- send_0();
+ hold_SDA(); /* set low for 0 */
}
+ delay();
+ release_SCL(); /* set clock high to indicate valid value */
byte <<= 1;
}
- return read_ack();
+ /* 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();
+ 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 */
+ delay();
+ release_SDA(); /* set output to high (default) */
+ TRISB &= ~SDA; /* set back to output */
+ return 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;
}
diff --git a/pic/MDR/I2C.h b/pic/MDR/I2C.h
index 19998ad..9e122cf 100644
--- a/pic/MDR/I2C.h
+++ b/pic/MDR/I2C.h
@@ -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);