test I2C: fails. same code produce similar result every 9 times
This commit is contained in:
parent
d352167fb4
commit
03dfdc0737
116
pic/MDR/I2C.c
116
pic/MDR/I2C.c
|
@ -1,47 +1,44 @@
|
||||||
/* software bit banging implementation
|
/* software bit banging implementation
|
||||||
* based on https://en.wikipedia.org/wiki/I2c example code
|
* based on https://en.wikipedia.org/wiki/I2c example code
|
||||||
|
*
|
||||||
|
* there is no external pull-up on SCL, and the internal one is too weak
|
||||||
|
* SCL must be driven
|
||||||
|
* but that is ok as we are the only master
|
||||||
|
* there is an external pull-up on SDA, and the internal one is too weak
|
||||||
|
* SDA goes to 3V instead of 5V due to the external pull-up
|
||||||
|
* but the 24LC256 still seems to work
|
||||||
*/
|
*/
|
||||||
#include "I2C.h"
|
#include "I2C.h"
|
||||||
|
|
||||||
// Hardware-specific support functions that MUST be customized:
|
// Hardware-specific support functions that MUST be customized:
|
||||||
#define I2CSPEED 100
|
/* even when doing nothing, the max speed will be 100kHz, while the chip supports 400kHz */
|
||||||
void I2C_delay()
|
#define I2C_delay()
|
||||||
{
|
|
||||||
volatile int v = 0;
|
|
||||||
int i;
|
|
||||||
for (i=0; i < I2CSPEED/2; i++) {
|
|
||||||
v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set SCL as input and return current level of line, 0 or 1 */
|
/* Set SCL as input and return current level of line, 0 or 1 */
|
||||||
bool read_SCL(void)
|
bool read_SCL(void)
|
||||||
{
|
{
|
||||||
PORTB |= SCL; /* set as input */
|
LATB |= SCL; /* set high (must be driven because no pull-up */
|
||||||
WPUB |= SCL; /* enable pull-up */
|
return 1;
|
||||||
return (PORTB&SCL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set SDA as input and return current level of line, 0 or 1 */
|
/* Set SDA as input and return current level of line, 0 or 1 */
|
||||||
bool read_SDA(void)
|
bool read_SDA(void)
|
||||||
{
|
{
|
||||||
PORTB |= SDA; /* set as input */
|
TRISB |= SDA; /* set as input */
|
||||||
WPUB |= SDA; /* enable pull-up */
|
return (PORTB&SDA)!=0;
|
||||||
return (PORTB&SDA);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actively drive SCL signal low */
|
/* Actively drive SCL signal low */
|
||||||
void clear_SCL(void)
|
void clear_SCL(void)
|
||||||
{
|
{
|
||||||
PORTB &= ~SCL; /* set as output */
|
LATB &= ~SCL; /* set low */
|
||||||
PORTB &= ~SDA; /* set low */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actively drive SDA signal low */
|
/* Actively drive SDA signal low */
|
||||||
void clear_SDA(void)
|
void clear_SDA(void)
|
||||||
{
|
{
|
||||||
PORTB &= ~SCL; /* set as output */
|
TRISB &= ~SDA; /* set as output */
|
||||||
PORTB &= ~SDA; /* set low */
|
LATB &= ~SDA; /* set low */
|
||||||
}
|
}
|
||||||
|
|
||||||
void arbitration_lost(void)
|
void arbitration_lost(void)
|
||||||
|
@ -111,51 +108,52 @@ void i2c_write_bit(bool bit) {
|
||||||
|
|
||||||
// Read a bit from I2C bus
|
// Read a bit from I2C bus
|
||||||
bool i2c_read_bit(void) {
|
bool i2c_read_bit(void) {
|
||||||
bool bit;
|
bool bit;
|
||||||
// Let the slave drive data
|
// Let the slave drive data
|
||||||
read_SDA();
|
read_SDA();
|
||||||
I2C_delay();
|
I2C_delay();
|
||||||
while (read_SCL() == 0) { // Clock stretching
|
while (read_SCL() == 0) { // Clock stretching
|
||||||
// You should add timeout to this loop
|
|
||||||
}
|
// You should add timeout to this loop
|
||||||
// SCL is high, now data is valid
|
}
|
||||||
bit = read_SDA();
|
// SCL is high, now data is valid
|
||||||
I2C_delay();
|
bit = read_SDA();
|
||||||
clear_SCL();
|
I2C_delay();
|
||||||
return bit;
|
clear_SCL();
|
||||||
|
return bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a byte to I2C bus. Return 0 if ack by the slave.
|
// Write a byte to I2C bus. Return 0 if ack by the slave.
|
||||||
bool i2c_write_byte(bool send_start,
|
bool i2c_write_byte(bool send_start, bool send_stop, unsigned char byte)
|
||||||
bool send_stop,
|
{
|
||||||
unsigned char byte) {
|
unsigned bit;
|
||||||
unsigned bit;
|
bool nack;
|
||||||
bool nack;
|
if (send_start) {
|
||||||
if (send_start) {
|
i2c_start_cond();
|
||||||
i2c_start_cond();
|
}
|
||||||
}
|
for (bit = 0; bit < 8; bit++) {
|
||||||
for (bit = 0; bit < 8; bit++) {
|
i2c_write_bit((byte & 0x80) != 0);
|
||||||
i2c_write_bit((byte & 0x80) != 0);
|
byte <<= 1;
|
||||||
byte <<= 1;
|
}
|
||||||
}
|
nack = i2c_read_bit();
|
||||||
nack = i2c_read_bit();
|
if (send_stop) {
|
||||||
if (send_stop) {
|
i2c_stop_cond();
|
||||||
i2c_stop_cond();
|
}
|
||||||
}
|
return nack;
|
||||||
return nack;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a byte from I2C bus
|
// Read a byte from I2C bus
|
||||||
unsigned char i2c_read_byte(bool nack, bool send_stop) {
|
unsigned char i2c_read_byte(bool nack, bool send_stop)
|
||||||
unsigned char byte = 0;
|
{
|
||||||
unsigned bit;
|
unsigned char byte = 0;
|
||||||
for (bit = 0; bit < 8; bit++) {
|
unsigned bit;
|
||||||
byte = (byte << 1) | i2c_read_bit();
|
for (bit = 0; bit < 8; bit++) {
|
||||||
}
|
byte = (byte << 1) | i2c_read_bit();
|
||||||
i2c_write_bit(nack);
|
}
|
||||||
if (send_stop) {
|
i2c_write_bit(nack);
|
||||||
i2c_stop_cond();
|
if (send_stop) {
|
||||||
}
|
i2c_stop_cond();
|
||||||
return byte;
|
}
|
||||||
|
return byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,8 @@
|
||||||
/* pin 18 is for a secret function, set by jumper WJ2, Vdd per default */
|
/* pin 18 is for a secret function, set by jumper WJ2, Vdd per default */
|
||||||
|
|
||||||
/* simple functions */
|
/* simple functions */
|
||||||
#define led_off() PORTB |= LED
|
#define led_off() LATB |= LED
|
||||||
#define led_on() PORTB &= ~(LED)
|
#define led_on() LATB &= ~(LED)
|
||||||
#define sleep() __asm sleep __endasm
|
#define sleep() __asm sleep __endasm
|
||||||
|
|
||||||
/* variables */
|
/* variables */
|
||||||
|
@ -69,11 +69,9 @@ uint16_t __at(_CONFIG2) __CONFIG2 = _LVP_ON & /* enable low voltage programming
|
||||||
_PLLEN_OFF & /* don't use 4X PLL, for longer timer */
|
_PLLEN_OFF & /* don't use 4X PLL, for longer timer */
|
||||||
_WRT_OFF; /* no flash write protect */
|
_WRT_OFF; /* no flash write protect */
|
||||||
|
|
||||||
|
|
||||||
/* initialize micro-conroller */
|
/* initialize micro-conroller */
|
||||||
void init (void) {
|
void init (void) {
|
||||||
/* configure IO */
|
/* configure IO */
|
||||||
NOT_WPUEN = 0; /* enable individual pull-ups */
|
|
||||||
ANSELA = 0; /* all pins are digital */
|
ANSELA = 0; /* all pins are digital */
|
||||||
ANSELB = 0; /* all pins are digital */
|
ANSELB = 0; /* all pins are digital */
|
||||||
TRISA |= RADIO; /* radio signal is an input */
|
TRISA |= RADIO; /* radio signal is an input */
|
||||||
|
@ -118,6 +116,8 @@ void init (void) {
|
||||||
* this PIC16F1847 offers hardware I2C, but not on those pins
|
* this PIC16F1847 offers hardware I2C, but not on those pins
|
||||||
* so we also have to use software bit banging I2C
|
* so we also have to use software bit banging I2C
|
||||||
*/
|
*/
|
||||||
|
TRISB &= ~SCL; /* set as output (it must be driven because there is no pull-up */
|
||||||
|
LATB |= SCL; /* set clock as high (default pull-up state) */
|
||||||
|
|
||||||
PEIE = 1; /* enable peripheral interrupt (for timer 2) */
|
PEIE = 1; /* enable peripheral interrupt (for timer 2) */
|
||||||
GIE = 1; /* golablly enable interrupts */
|
GIE = 1; /* golablly enable interrupts */
|
||||||
|
@ -161,6 +161,11 @@ static void interrupt(void) __interrupt 0
|
||||||
if (switches&SWITCH1) { /* switch 1 changed */
|
if (switches&SWITCH1) { /* switch 1 changed */
|
||||||
if (PORTB&SWITCH1) { /* switch 1 released */
|
if (PORTB&SWITCH1) { /* switch 1 released */
|
||||||
led_off(); /* reset LED */
|
led_off(); /* reset LED */
|
||||||
|
i2c_write_byte(1,0,0xa0);
|
||||||
|
i2c_write_byte(0,1,0xa0);
|
||||||
|
// i2c_write_byte(0,1,0x17);
|
||||||
|
// i2c_write_byte(1,0,0xa1);
|
||||||
|
// i2c_read_byte(0,0);
|
||||||
} else { /* switch 1 pressed */
|
} else { /* switch 1 pressed */
|
||||||
led_on(); /* test LED */
|
led_on(); /* test LED */
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ OBJ := $(patsubst %.c,%.o,$(SRC))
|
||||||
|
|
||||||
all: compile flash
|
all: compile flash
|
||||||
|
|
||||||
# flash program
|
# flash program (the board needs to power externally)
|
||||||
flash: $(TARGET).hex
|
flash: $(TARGET).hex
|
||||||
pk2cmd -PPIC$(PIC) -F$< -M -W -R
|
pk2cmd -P PIC$(PIC) -F $< -M -W -R
|
||||||
|
|
||||||
# compile stages
|
# compile stages
|
||||||
assembly: $(ASM)
|
assembly: $(ASM)
|
||||||
|
@ -36,7 +36,7 @@ compile: hex
|
||||||
gpasm -I . -o $@ -c $<
|
gpasm -I . -o $@ -c $<
|
||||||
|
|
||||||
$(TARGET).hex: $(OBJ)
|
$(TARGET).hex: $(OBJ)
|
||||||
gplink -w -r -s /usr/share/gputils/lkr/$(PIC)_g.lkr -I/usr/share/sdcc/lib/pic14 -I/usr/share/sdcc/non-free/lib/pic14 -I. -o $@ libsdcce.lib pic$(PIC).lib $<
|
gplink -w -r -s /usr/share/gputils/lkr/$(PIC)_g.lkr -I /usr/share/sdcc/lib/pic14 -I /usr/share/sdcc/non-free/lib/pic14 -I . -o $@ libsdcce.lib pic$(PIC).lib $(OBJ)
|
||||||
|
|
||||||
# remove temporary files
|
# remove temporary files
|
||||||
clean:
|
clean:
|
||||||
|
|
Loading…
Reference in New Issue