AnsweredAssumed Answered

Comms Issues with ADG2188 from PIC18F

Question asked by ec2000 on Sep 28, 2016
Latest reply on Sep 30, 2016 by mayp

Hi,

I am having trouble communicating with an ADG2188 Analog Switch Array to the extent that I'm stuck for what to try next. I'm talking to it from a PIC18F, firmware coded in C via MPLAB using the XC8 compiler. the I2C bus is working as there are other components on the board which I'm successfully interacting with via I2C. The ADG2188 code has now been hived off into a separate project to try and debug what's going on.

 

Essentially, I do the setup as per the ADG2188 data sheet and get correct 0 responses from the WriteI2C function calls. I then go to read back the config byte from the switcher, again following the process laid out in the data sheet. However, regardless of what I set the switching config to be, the channel readback byte is always 0b11111111 in the second byte (i.e. after the "don't care" one). We're putting a sine wave into the input we're working with (X5), but when we check the output (Y0) with a scope there's nothing. We've traced the sine wave through the board and it is definitely arriving and the switcher X5 pin. So, I suspect the ADG2188 is just not interpreting things correctly despite the I2C functions suggesting that it's returning a success value in response to communications.

 

I'd really appreciate some input on this please. Can anyone spot anything I'm doing wrong, or could anyone even post working example code in this dev environment which I could compare mine to?

 

Here's my code below:

 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

 

void main(void) {
   
   // Test routine to prove I2C comms with ADG2188 from PIC18F45K22
   
   // vars
   char result;                        // result of the write function
   char msg20[] = "a";           // Initialise with a known, dummy value
   uint16_t switchConfig;        // to store received data
 
    // Setup
    OSCCONbits.IRCF = 0b111;   // setting clock to 16MHz
    while(OSCCONbits.HFIOFS != 1);  // wait for clock to be stable
  
   // ports setup. SDA is on RC4, SCL on RC3
   TRISCbits.RC4 = 1;       // set RC4 to be input
   ANSELCbits.ANSC4 = 0;    // set RC4 to be digital.
  
   TRISCbits.RC3 = 1;       // set RC3 to be input
   ANSELCbits.ANSC3 = 0;     // set RC3 to be digital
  
  
       Open1USART(USART_TX_INT_OFF     &
               USART_RX_INT_OFF     &
               USART_ASYNCH_MODE    &
               USART_EIGHT_BIT      &
               USART_CONT_RX        &
               USART_BRGH_LOW,
               25);
 

   // set up / initialise I2C
   CloseI2C1();                  // definitively closed for start
   OpenI2C1(MASTER, SLEW_OFF);   // PIC is master, SLEW_OFF for 100 kHz comms
   SSP1ADD = 0x3;     // 0x3 = 1Mhz. 0x1 = 1.7MHz. 0x27 = 39 in decimal.

                                 // That gives an SCL pin clock period of 0.00001 @ 16MHz clock  = 100KHz
 

   while(1)
   {
     putrs1USART("Starting loop");


       IdleI2C1();      // Wait til bus is idle
       StartI2C1();     // Send START condition onto bus
       IdleI2C1();      // Wait til bus is idle - START condition implemented
      
       // First send switcher address with write bit set:
       // 1110---- = hard-coded device id
       // ----111- = device address on I2C bus
       // -------0 = write flag
      
       result = WriteI2C1(0b11101110);
      
       // now send Video switching map -
       // 1st byte is switching config:
       // 1------- = On
       // -0101--- = Input  X5
       // -----000 = Output Y0
       result = WriteI2C1(0b10101000); // map input (X)5 to output (Y)0
      
       // next, send second byte. Only bit 0 matters. 1 means 'do it now'
       result = WriteI2C1(0b00000001);

       // note - above two WriteI2C1 calls replaced with this:
       //        result = putsI2C1(0b1010100000000001); 
       //        at one point, but doing so seemed to make no difference
     

       IdleI2C();

       // Restart communication for read back of config byte
       // Note - Tried using explicit stop, idle, start instead of restart but it made no difference
       RestartI2C();
      
       // Note - Tried using explicit idle, stop, idle, start, idle instead of restart but it made no difference
       IdleI2C1();
      
       // write address bit with write flag set (bit zero = 0)
       result = WriteI2C1(0b11101110);
      
       // now tell the switcher which register we're wanting the config byte for       
       result = WriteI2C1(0b00110100); // Write which output we're interested in. In this case, X0

 

       // switch now wants a second, "don't care" byte
       result = WriteI2C1(0b00000000);
       // note - tried the above two WriteI2C1s with a putsI2C1(0b0011010000000000) but it made no difference

 

       IdleI2C1();

 

       // now restart in order to read the config data back
       RestartI2C1();

       IdleI2C1();
      
       // Send read command to switcher  (bit zero = 1)
       result = WriteI2C1(0b11101111);
       // note - tried using result = putsI2C1(0b11101111); instead but it made no difference
      
       IdleI2C1();
      
       // retrieve the data from the
       getsI2C1(&switchConfig,2);
       // note - tried doing this in two ReadI2C1s with interim Ack() then concatenating bytes but made no difference
      
       NotAckI2C();
       StopI2C();
 
       // Output config data received form switcher unit. MSB is "don't cares"
       putrs1USART("Point 1, read second byte - real data");
       sprintf(msg20,"Point 2, Data is %u", switchConfig);
       putrs1USART(msg20);
       // note - this returns "...Point 10, Data is 28415", which I believe equates to 110111011111111.
       //        Would have expected XXXXXXXX00110100 (where X = don't care)
    
   }
      
}

 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Outcomes