Z80<->PCF8584 I2C interface problem - Page 1
Forum section: electronics / projects

author: nockieboy
author_rank: Super Contributor
timestamp: May 04, 2019, 09:45:36 am
content: Hi everyone,I'm trying to get a PCF8584 working with my DIY Z80 computer (thanks again for the chip, CJay). I've built a breadboard prototype for the I2C interface using a PCF8584, 74F521 giving an I/O range of 0x0A-0x0B for the PCF8584 and a couple of 4K7 pull-up resistors on the SDA and SCL lines. SDA and SCL are not connected to anything else at the moment, other than my logic analyser, so I can see the I2C transactions from the PCF8584 whilst I test that I've got it wired up correctly and work on developing the driver software for it.I have some basic test software, which initialises the PCF8584 in master-transmit mode at 45 KHz, assigns it a slave address (for no reason other than I think it needs one?) and then sends three bytes of data before sending the STOP command. This is all based off the flowcharts in the PCF8584 datasheet,available here(pages 15 & 16 specifically).I have the PCF8584 RESET pin connected to my system's cold reset line, which isn't suitable as the cold reset is a button-operated active-low to reset the Z80 and rest of the system. According to the PCF8584 datasheet, RESET needs to be a specific-length pulse whilst the clock is still running, so obviously the system reset is no good for that (but that's another issue for me to sort later). The system clock runs at 4 MHz and is connected to the PCF8584's clock input.So to the problem. The interface is initialising and sending the three bytes, but the STOP condition isn't being generated properly by the PCF8584. Here's a trace from the logic analyser, missing the initial setup, but showing the START condition and rest of the transaction up to where the STOP condition should be generated. Instead, all I'm getting is SDA pulled LOW and SCL remaining LOW.The I2C SELECT lane at the top shows the OUTs to the PCF8584 from the Z80. The SDA lane in the middle shows activity on the data line, correctly decoded by the I2C analyser in the software (I'm sending a randomly-chosen slave address of 0x54, then data bytes of 0xAA, 0x55 and - randomly - 0x46, or the hex equivalent of 'F'). SCL lane speaks for itself.The point of interest is the final pulse on the top lane (I2C SELECT) where the Z80 writes the value 0xC3 to the PCF8584's S1 register, in accordance with the datasheet flow charts, to make it send the STOP condition. As you can see, it just causes the 8584 to pull SDA LOW and do nothing with SCL.What I want to happen is for the I2C transaction to STOP and the bus be released, so I can try another transaction. Instead, the PCF8584 just reports the bus is constantly busy after this and I have to power-cycle the computer in a hard reset to start again. This is likely because I haven't set up a proper RESET circuit for the 8584 (I'll likely do this using an extra I/O port and just write a pulse to the RESET pin on the 8584). Once hard reset, I am able to send another I2C transaction like the one above.Here's the output from my computer for the trace:Attached is the code I'm using to test the I2C/PCF8584.Anyone with more experience with PCF8584's and electronics in general able to shed some light or point me in a direction?

author: bson
author_rank: Unknown
timestamp: May 04, 2019, 05:13:05 pm
content: Did you follow the flow chart on page 16 of the datasheet? In particular, note the need for A0=HIGH when sending the stop...

author: nockieboy
author_rank: Super Contributor
timestamp: May 04, 2019, 08:00:46 pm
content: Quote from: bson on May 04, 2019, 05:13:05 pmYes, absolutely.If you take a look at lines 102-103 in TEST_I2C.ASM, you'll see where I send the 'STOP' command to the PCF8584:Code:LDA,0C3hOUT(I2C_CSR),A; Send 'STOP' signal to PCF85840xC3 is the STOP command, according to the flow charts on pages 15-16, and corresponds with the bit flags in the S1 register for setting PIN, ESO, STO and ACK. That command is sent to the I2C_CSR I/O port, which is specified on line 28 of the same program listing:Code:I2C_CSR.EQU0Bh; PCF8584 S1 & othersOn the breadboard, the PCF8584's I/O address space is configured as 0x0A and 0x0B - 0x0B being the address with A0 HIGH and accessing the S1 register where the STOP command is sent to. Think I might add another logic analyser lane to monitor the A0 line, though, just to confirm that it is working as expected - but the initialisation and data sending routines work okay...

author: nockieboy
author_rank: Super Contributor
timestamp: May 04, 2019, 08:37:23 pm
content: Image above focuses on where the 0xC3 (STOP) byte is sent to register S1 - as confirmed by the A0 lane at the top showing A0 HIGH at the time the PCF8584 is selected via the 74F521.

author: nockieboy
author_rank: Super Contributor
timestamp: May 05, 2019, 12:03:33 pm
content: Okay, so I think my only option at the moment is to order some new PCF8584s and see if it's the DIP chip that's faulty.

author: mk279
author_rank: Newbie
timestamp: October 12, 2019, 12:31:40 pm
content: Similar issue here.A PCF8584 connected to a M68000.Spuriously there is no stop condition send by the PCF8584.Did you solve your problem?I worked around that by retrying to set the register until BB is not asserted anymore.Until now this works reliably.Code:static inline void pcf8584_master_stop(){/* send stop condition */pcf8584_writereg(S1, S1_PIN | S1_ESO | S1_STO | S1_ACK);}static inline void pcf8584_master_stop_force(){/* send stop condition */pcf8584_master_stop();while ((pcf8584_readreg(S1) & S1_BB) == 0) {pcf8584_master_stop();};}Furthermore did you checkout ANZ96003 from Philips?I did not check the data bus timing

author: nockieboy
author_rank: Super Contributor
timestamp: October 12, 2019, 01:59:53 pm
content: Yes, I fixed it in the end - turned out I had a bad ground connection, once I'd sorted that it worked perfectly.Edit: Haven't heard of the ANZ96003, but will check it out.

author: mk279
author_rank: Newbie
timestamp: October 12, 2019, 06:53:32 pm
content: Just to share my results: I just fixed my problem.Two points:Now I configured the fclk correctly. Before I configured 8MHz, while a 3MHz clock was connected.I inserted now 2 nop after each register access. Here the PCF8584 is a bit picky. Maybe I should try using 8MHz as fclk so that the PCF8584 could handle register access with 0 or 1 nop.Anyhow running well now

author: grantb5
author_rank: Regular Contributor
timestamp: December 06, 2020, 04:01:06 am
content: I was using one of these as an I2C monitor some years ago (you just set the device address to 0x00), and attached to an 8031 port, I had to use 3 NOPs between commands. I'm guessing this came from some old Philips App Note, but I'm not sure. I was thinking of resurrecting this since it made a nice I2C bus snooper.