Kirk Humphries

Another Programmer confused by IIC

Discussion created by Kirk Humphries Employee on Jan 31, 2006

This message contains an entire topic ported from a separate forum. The original message and all replies are in this single message. We have seeded this new forum with selected information that we expect will be of value to you as you search for answers to your questions.


Posted: Thu Jun 30, 2005  6:23 pm


I am having huge troubles with my HCS12 and a DS1307 real time clock, and bigger problems finding any examples online or solid documentation (don't get me wrong the freescale documentation is usually great but with IIC it seems lacking to me).


The lines are pulled up correctly yet whenever I set the TX_RX flag to receive the IBDR reads back as 0. To me this is clearly wrong, an IIC bus is high unless pulled low and nothing is holding this low. I would expect FF to come back unless by some miracle my chip was replying but it occurs even when I intentionally address the wrong chip (one that isn't there).


All I can assume is this bus is not enabling correctly. I have interfaced this chip with HC05 and HC08s before so know I have to set the oscillator starting by writing 0 to bit 8 of the top register and have experienced the odd quirk but it was never this hard.


Any help would be greatly appreciated.



Posted: Thu Jun 30, 2005  11:33 pm


I had a hard time getting my 9S12DP256 to talk to the I2C port on a Ti DSP. Finally I found that the SDA pin on my MCU had gone bad. I could not read the proper value on receive. My digital scope was how I found that the target was not sending the Ack bit.


I suggest verifying the i/o lines in general purpose mode, also as open-collectors.



Posted: Fri Jul 1, 2005  3:23 pm


What is wrong with this code?


Every HC08 or HC05 device I have made which interfaces with this RTC turns on the oscillator by setting the first line to 0. All I want this to do is write 0 to the first address of the clocks ram and it cant even do that?


// Enable IIC

IBAD = 0x02;

IBFD = 0x35;

IBCR = 0xB1;

IBDR = 0xD0; //Slave address Write mode

while(!IBSR_TCF) { ; }

IBDR = 0x00; //Reset Pointer

while(!IBSR_TCF) { ; }

IBDR = 0x00; //Clear line 0

while(!IBSR_TCF) { ; }

IBCR = 0;


Thanks to anyone who can help.



Posted: Tue Jul 5, 2005  6:07 pm


I was writing the following suggestions when I saw the probable cause. IBCR should be returned to 0x80 to end message. More discussion below.


It reminds me of a problem when I forgot that IBAD reserved bit 0 (because R/W control bit is sent in that spot), so in setting the addr I needed to shift left. It was a problem because on the other device, the address was 0x01 but I needed to send 0x02 for the same address.


About TCF... My notes say not to use that flag to detect completion. Apparently IBIF is the reliable flag to tell when it is ready to accept the next byte to send.


About IBCR, you should return it back to slave mode (0x80). If you set it to 0 instead, you are disabling the IIC hardware before it finishes the transfer.


Here is my example code listing. It was compiled with GNU as.


;;; Initialize IIC

100b: 18 0b 57 00 movb #87, e1 <IBFD> ; speed

100f: e1

1010: 18 0b 04 00 movb #4, e0 <IBAD> ; my IIC address, 0x02

1014: e0

1015: 18 0b 80 00 movb #128, e2 <IBCR> ; enable IIC hardware

1019: e2


;;; Send 0x02 and the value tdat. Makes target addr 0x01.

103a: 07 2c bsr 1068 <iic_wait_bus>

103c: 1c 00 e2 b0 bset e2 <IBCR> #$b0

1040: c6 02 ldab #2 ; to addr 0x01

1042: 07 13 bsr 1057 <iic_tx>

1044: c5 01 bitb #1

1046: 26 08 bne 1050 ; check for error

1048: f6 10 c9 ldab 10c9 <tdat>

104b: 72 10 c9 inc 10c9 <tdat> ; to vary the data

104e: 07 07 bsr 1057 <iic_tx>

1050: 18 0b 80 00 movb #128, e2 <IBCR> ; end message

1054: e2



;;; IIC transfer subroutines


00001057 <iic_tx>:

1057: 7b 00 e4 stab e4 <IBDR>

105a: 07 12 bsr 106e <iic_wait>

105c: 18 0c 00 e3 movb e3 <IBSR>, 1 <PORTB>

1060: 00 01

1062: 18 0b 02 00 movb #2, e3 <IBSR>

1066: e3

1067: 3d rts


;;; Return when IBB clears (bus not busy)

00001068 <iic_wait_bus>:

1068: 1e 00 e3 20 brset e3 <IBSR> #$20 1068 <iic_wait_bus>

106c: fb

106d: 3d rts


;;; Return when ready to process another byte.

;;; Returns with status in B

0000106e <iic_wait>:

106e: 1f 00 e3 02 brclr e3 <IBSR> #$02 106e <iic_wait>

1072: fb

1073: f6 00 e3 ldab e3 <IBSR>

1076: 7b 00 01 stab 1 <PORTB>

1079: 18 0b 02 00 movb #2, e3 <IBSR>

107d: e3

107e: c5 10 bitb #16

1080: 26 3c bne 10be <icc_err>

1082: 3d rts



Posted: Wed Jul 6, 2005  4:26 am


Thanks so much for taking the time to help but I have managed to fix the problem. I think IBAL was being set for some unknown reason (I don't have a second master) but when I wrote my code in interrupts and only acted when the tcf flag was set it all came to life.


Thanks again for your help.