CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C slave no ACK bit help.

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
frank_the_programmer



Joined: 05 Feb 2024
Posts: 7

View user's profile Send private message

I2C slave no ACK bit help.
PostPosted: Mon Feb 05, 2024 2:28 pm     Reply with quote

This is my first CCS project and I'm running into some problems implementing a dsPIC33FJ128GP204 as an I2C slave device. I hooked up an Arduino to act as the master for testing purposes. Everything seems to be correct except I can't get past the acknowledgment bit. I hooked up my O-scope to the data lines and I can see the correct address. The PIC also fires off the interruption, but It won't pull down the ACK bit to continue the data transmission.

As far as software goes I've copied over and slightly modified one of the examples called ex_slave.c. I attempt to print out the buffer, but it's all zeros.


Code:
// #include <main.h>
#include <33FJ128GP204.h>
#include <stdint.h>
#include <stdbool.h>

#define RX_PIN PIN_C6
#define TX_PIN PIN_C7

#device ICSP = 1
#use delay(internal = 20000000)

#fuses NOWDT  // No Watch Dog Timer
#fuses CKSFSM // Clock Switching is enabled, fail Safe clock monitor is enabled

// setup the uart
#use rs232(UART1, baud = 115200, XMIT = TX_PIN, RCV = RX_PIN, stream = UART_PORT1, ERRORS)

#use i2c(SLAVE, I2C1, FORCE_HW, ADDRESS = 0x10)

uint8_t address, buffer[16] = {0};
uint8_t incoming = 0;
bool rec = FALSE;

#INT_SI2C
void i2c_interrupt(void)
{
   uint8_t state;

   state = i2c_isr_state();

   if (state <= 0x80) // Master is sending data
   {
      if (state == 0x80)
         incoming = i2c_read(2); // Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      else
         incoming = i2c_read();

      if (state == 1) // First received byte is address
         address = incoming;
      else if (state >= 2 && state != 0x80) // Received byte is data
         buffer[address++] = incoming;
   }

   if (state >= 0x80) // Master is requesting data
   {
      i2c_write_slave(buffer[address++]);
   }

   rec = TRUE;
}

void main()
{

   // wait for uart to setup
   delay_ms(1000);
   // setup interrupts
   enable_interrupts(INTR_GLOBAL);
   enable_interrupts(INT_SI2C);

   // forever loop
   while (TRUE)
   {

      // check i2c
      if (rec == TRUE)
      {
         for (int i = 0; i < 16; i++)
         {

            printf("buf %u) %u\r\n", i, buffer[i]);
         }
         rec = FALSE;
      }
   }
}


Does anyone know what I could be doing wrong? If it's not the software I think it might be a hardware issue (on my part) Thank you!
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Feb 05, 2024 4:20 pm     Reply with quote

what is VDD ?
what are I2C pullups ?
frank_the_programmer



Joined: 05 Feb 2024
Posts: 7

View user's profile Send private message

PostPosted: Mon Feb 05, 2024 6:52 pm     Reply with quote

3V for VDD and two 3V pull-ups on both lines. Do I have to enable the ack in the software?
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Tue Feb 06, 2024 7:39 am     Reply with quote

The buffer will be zeros, since the data has not yet been received. You are
setting the 'rec' flag every time the code leaves the interrupt. So in the
read of the address byte, etc... You need to wait till the count gets to 16
bytes received before setting this.
What are you pull up resistors?.
How fast are you driving the bus?.
As I read it, you are trying to receive 16bytes?.
There is an issue with your address. In I2C 7bit addresses under 0x10
are 'reserved'. Now the PIC uses an 8bit address. So if your Arduino is
talking to it's address 0x10, the PIC needs to be set to use 0x20.
frank_the_programmer



Joined: 05 Feb 2024
Posts: 7

View user's profile Send private message

PostPosted: Sun Feb 18, 2024 11:43 pm     Reply with quote

Thank you for the reply, but I'm still encountering issues with the I2C. I was aware of the 8-bit address as I found out the hard way, but the issue still remains. Even though the I2c interrupt fires off, I can get the PIC (slave) to turn off the ACK bit. Since then I've switched over to an STM32 and I have the same situation. I'm using 10k Pullup resistors on the PIC side and nothing is set on the SMT32 side. Both are 3.3v devices and use 100khz (slow) speed.

I've simplified the problem below as the STM32 attempts to send 2 bytes and I can see the PIC fire off the interrupt. I can scope the correct address and the R/W bit is low for writing from the master. For some reason, the ACK bit never seems to be pulled down which I assume ends the transmission. The STM32 also will print a timeout error. The code below should help demonstrate the issue because when running this the state never changes from 0. Maybe I'm doing something wrong.

Code:

#use i2c(SLAVE, SLOW, I2C1, FORCE_HW, ADDRESS=0x20)

#INT_SI2C
void i2c_interrupt(void)
{
    uint8_t state;

    state = i2c_isr_state();
    i2c_read();
    printf("%u\r\n",state);
}



If anyone knows of any troubleshooting ideas I'd appreciate it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Mon Feb 19, 2024 2:21 am     Reply with quote

OK.

First thing, 10K is too large. On 5v 12C, with a reasonably short bus, 4K7
is OK, but on 3.3v 3K is the equivalent value. So reduce this.

Then the printf, will cause problems. It could be sending up to 5 bytes.
You don't say what your baud rate is, but the routine needs to exit in
a few uSec. The hardware buffering is not enough for such a long message.

Then are you sure about your address???. Is the STM talking to address
0x10?. It needs to be. Remember the PIC uses 8bit addressing. Most
devices use 7bit addressing. A NACK after the address byte means no
slave is responding.

You don't need to specify a 'speed' in the slave device.
frank_the_programmer



Joined: 05 Feb 2024
Posts: 7

View user's profile Send private message

PostPosted: Mon Mar 11, 2024 2:30 pm     Reply with quote

I've reduced the resistors to 4.7k and removed the print function. I still get the interrupt but no ACK bit :(

I'm certain about the address as I've run a bus scanner to test what addresses respond, but no luck. Not sure what to do from here.

[img]https://forum.microchip.com/servlet/rtaImage?eid=a58V40000005fP7&feoid=00N3l00000FRqlI&refid=0EMV4000000Y56v[/img]
frank_the_programmer



Joined: 05 Feb 2024
Posts: 7

View user's profile Send private message

PostPosted: Tue Mar 12, 2024 1:47 pm     Reply with quote

I GOT IT! Turns out I was testing on some damanged hardware.
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Tue Mar 12, 2024 2:34 pm     Reply with quote

Happens to us all. Glad you have it sorted.
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Mar 12, 2024 7:53 pm     Reply with quote

Yes, I got nailed for months when 'they' decided to reverse the usage of pins 2 and 3 when 'RS-232- connectors went from 25 pin to 9 pin.
I'd love to know WHO changed it and WHY !!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Wed Mar 13, 2024 7:56 am     Reply with quote

They didn't!...... Very Happy

If you look the standard connector on the 25pin serial on a PC, was the
DB-25F. The 9 pin serial is a DE-9M. The switch of size was also a switch
in gender, and implicitly there was also a swap on the assumption of
whether a PC was going to be a DCE or a DTE device. DCE and DTE devices
have the use of the two pins swapped.
The smaller connector was setup on the assumption the PC would not
be a 'terminal' any more.
Also designed to confuse.... Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group