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

Digital inputs

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



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

Digital inputs
PostPosted: Mon Jun 02, 2008 2:06 pm     Reply with quote

I have a program that reads 5 analog pins and 10 digital pins in a pic16f876a and reports back its status when queried via I2C. The analog values come back fine, but sometimes the digital values are correct, and sometimes it reports back 255's. After the 255 it does not report back at all which makes me think it is locking up. But every time it does it, it sends the analog correctly, so it looks like getting the digital values is causing the lockup.
For example, when I get a lockup I get 129 128 126 127 129 255 255 255....

Does anyone see anything silly in my code? I have tried this with 4.11 and 3.249 with the same results.
Thanks
Ringo

Code:
#include <16F876a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use standard_io(B)
#byte PIC_SSPADD=0x93
#define initial_i2c_address  0x82
int     NODE_ADDR  =  initial_i2c_address;// Decimal 130
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x82,slow)
#define Digital_in_0                 PIN_B5
#define Digital_in_1                 PIN_B4
#define Digital_in_2                 PIN_B3
#define Digital_in_3                 PIN_B2
#define Digital_in_4                 PIN_B1
#define Digital_in_5                 PIN_B0
#define Digital_in_6                 PIN_C7
#define Digital_in_7                 PIN_C6
#define Digital_in_8                 PIN_C5
#define Digital_in_9                 PIN_C2

int pin_table[] = {PIN_B5, PIN_B4, PIN_B3, PIN_B2, PIN_B1, PIN_B0, PIN_C7, PIN_C6, PIN_C5, PIN_C2};

int Dio_states[10];
int Dio_value[10];
int Analog_value[5];

int Power_up_state[10];
BYTE address, buffer[0x10];
int bytecounter=0;
int actionflag=0; //0 = nothing, 1 = read, 2 = change address


void Read_Digital_inputs();


#INT_SSP
void ssp_interupt()
{
    int i;
    BYTE incoming, state;
    int pinnumber,pinstate,dummy;
   state = i2c_isr_state();
   if(state < 0x80)                     //Master is sending data
   {
       incoming = i2c_read();
        buffer[bytecounter]=incoming;
        bytecounter++;
   }
   if(state == 0x80)   //Master is requesting data
   {
      actionflag=1; //0 = nothing, 1 = read, 2 = change address
      bytecounter=0;
   }
}

void main ()
{
    int i;
    setup_adc_ports(All_ANALOG);
    setup_adc( ADC_CLOCK_INTERNAL );
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_SSP);
   
    for(i=0;i<10;i++)
    {
        Dio_states[i]=2;//input
        Dio_value[i]=0;
    }       
    delay_ms(500);
    output_high(PIN_B6);
   
    while (1)
    {
      for(i=0;i<5;i++)
        {
            set_adc_channel(0);
            delay_ms(1);
            Analog_value[i]=Read_ADC();
        }

           
        if(actionflag==1) //0 = nothing, 1 = read, 2 = change address 
        {
            Read_Digital_inputs();

          for(i=0;i<5;i++)
            {
                i2c_write(Analog_value[i]);
                delay_ms(1);
            }
           
          for(i=0;i<10;i++)
            {
                delay_ms(1);
              i2c_write(Dio_value[i]);
            }
        }
    }
}
void Read_Digital_inputs()
{
    Dio_value[0]=input(PIN_B5);
    Dio_value[1]=input(PIN_B4);
    Dio_value[2]=input(PIN_B3);
    Dio_value[3]=input(PIN_B2);
    Dio_value[4]=input(PIN_B1);
    Dio_value[5]=input(PIN_B0);
    Dio_value[6]=input(PIN_C7);
    Dio_value[7]=input(PIN_C6);
    Dio_value[8]=input(PIN_C5);
    Dio_value[9]=input(PIN_C2); 
}

_________________
Ringo Davis
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 02, 2008 2:29 pm     Reply with quote

I notice that you set ActionFlag to 1, but then you never clear it
when the process is finished.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Mon Jun 02, 2008 2:35 pm     Reply with quote

Damn, I had that in there, and accidentally deleted it when compacting the code. This is part of a more complicate program. So when I was taking out the other stuff I killed that line. I had the issue for I took out the line though. I'll put it back in and see if I can still replicate the problem.
Thanks for the quick response.
Ringo
_________________
Ringo Davis
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 12:35 pm     Reply with quote

OK, I have another weird thing going on. I'm using pins on port B and port C. If I set pin B3 as high and then B2 as an input everything is fine. But no matter how I set a pin on port C, if I set another pin on port C as an input then they all go to inputs.
I'm using #use standard_io(C) (even though that is the default), is there something else I need to do?

With the code at the end commented out, it works ok (except I can't read any of the pins). But just putting in any 1 pair of lines hoses up the entire port. So if I set a pin High, I see it blink high but then go immediately off

The code is below, see the comments at the very end.
Code:

#include <16F876a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
//#use rs232(baud=115200, xmit=PIN_b6, rcv=PIN_b7)
#use standard_io(B)
#use standard_io(C)
#byte PIC_SSPADD=0x93
#define initial_i2c_address  0x82
int     NODE_ADDR  =  initial_i2c_address;// Decimal 130
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x82,slow)
#define Digital_in_0                 PIN_B5
#define Digital_in_1                 PIN_B4
#define Digital_in_2                 PIN_B3
#define Digital_in_3                 PIN_B2
#define Digital_in_4                 PIN_B1
#define Digital_in_5                 PIN_B0
#define Digital_in_6                 PIN_C7
#define Digital_in_7                 PIN_C6
#define Digital_in_8                 PIN_C5
#define Digital_in_9                 PIN_C2

int pin_table[] = {PIN_B5, PIN_B4, PIN_B3, PIN_B2, PIN_B1, PIN_B0, PIN_C7, PIN_C6, PIN_C5, PIN_C2};

int Dio_states[10];
int values[15];
int Power_up_state[10];
int Sensors=0;
BYTE address, buffer[0x10];
int bytecounter=0;
int actionflag=0; //0 = nothing, 1 = read, 2 = change address


void Read_Digital_inputs();


#INT_SSP
void ssp_interupt()
{
    int i;
    BYTE incoming, state;
    int pinnumber,pinstate,dummy;
   state = i2c_isr_state();
   if(state < 0x80)                     //Master is sending data
   {
       incoming = i2c_read();
        buffer[bytecounter]=incoming;
        bytecounter++;
        if(bytecounter ==4 )
        {
            if(buffer[1]==1)                           // Set, GPIO
            {
                pinnumber=buffer[2];
                pinstate=buffer[3];
                bytecounter=0;
                Dio_states[pinnumber]=pinstate;
                if(pinstate==0)
                {
                    output_low(pin_table[pinnumber]);
                    values[pinnumber+5]=0;
                }
                else if(pinstate==1)
                {
                    output_high(pin_table[pinnumber]);
                    values[pinnumber+5]=1;
                }
                else if(pinstate==2)
                {
                    Dio_states[pinnumber]=2;
//                    values[pinnumber+5]=input(pin_table[pinnumber]);
                }
                else {}
            }   
        }//end of 4
                   

   }
   if(state == 0x80)   //Master is requesting data
   {
//        if(debug==1)
//           printf("reading\r\n");
      actionflag=1; //0 = nothing, 1 = read, 2 = change address
      bytecounter=0;
   }
}

void main ()
{
    int flashcounter=0;
    int i,dummy;
    int data1;
    int temp_node_address;

    setup_adc_ports(All_ANALOG);
    setup_adc( ADC_CLOCK_INTERNAL );

    enable_interrupts(GLOBAL);
    enable_interrupts(INT_SSP);
    delay_ms(500);
    output_high(PIN_B6);
   
      while (1)
    {
      for(i=0;i<5;i++)
        {
            set_adc_channel(0);
            delay_ms(1);
            values[i]=Read_ADC();
        }
            Read_Digital_inputs();
           
        if(actionflag==1) //0 = nothing, 1 = read, 2 = change address 
        {
            actionflag=0; 
          for(i=0;i<15;i++)
            {
                delay_ms(1);
              i2c_write(values[i]);
            }
        }
    }
}
void Read_Digital_inputs()
{
    if(Dio_states[0]==2)//input
        values[5]=input(PIN_B5);
    if(Dio_states[1]==2)//input
        values[6]=input(PIN_B4);
    if(Dio_states[2]==2)//input
        values[7]=input(PIN_B3);
    if(Dio_states[3]==2)//input
        values[8]=input(PIN_B2);
    if(Dio_states[4]==2)//input
        values[9]=input(PIN_B1);
    if(Dio_states[5]==2)//input
        values[10]=input(PIN_B0);
    if(Dio_states[6]==2)//input        If I uncomment any of these that use port C
        values[11]=input(PIN_C7);      // then when I set a pin high, it immediately goes back to input
//    if(Dio_states[7]==2)//input         so if I only umcomment the 2 lines that deal with C7, it affects all the
//      values[12]=input(PIN_C6);      //   port C pins.
//    if(Dio_states[8]==2)//input
//      values[13]=input(PIN_C5);
//    if(Dio_states[9]==2)//input
//      values[14]=input(PIN_C2); 
}

_________________
Ringo Davis
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 1:03 pm     Reply with quote

What compiler version did you test this with ? The version numbers
are in this format: x.xxx
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 1:06 pm     Reply with quote

4.11
_________________
Ringo Davis
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 1:13 pm     Reply with quote

Quote:
4.11

The version numbers are in this format: x.xxx
(That's why I put that comment in my post).
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 1:26 pm     Reply with quote

Sorry, I missed a digit
CCS PCM C Compiler, Version 4.011, 34836
_________________
Ringo Davis
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 1:52 pm     Reply with quote

What I would do to fix this, or trouble-shoot it, is to strip out all the i2c
slave code, and run the program as a standalone test program.
Display the output in a terminal window with printf() statements, and
thus prove that the basic i/o is actually working, or not. Currently you
have two processes going -- Doing the i/o, and then transmitting it
through i2c. I would separate out those two processes, and prove that
each one works correctly, separately. Then combine them later.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 2:11 pm     Reply with quote

It works without the I2C stuff in there, so I started experimenting.
I'm assuming it is a compiler issue, because in the I2C routine,
this does not work:
Code:

else if(pinstate==1)
  {
    output_high(pin_table[pinnumber]);
    values[pinnumber+5]=1;
   }


But this does:
Code:

else if(pinstate==1)
  {
    values[pinnumber+5]=1;
    switch(pinnumber)
      {
       case 0: output_high(PIN_B5);
                   break;
       case 1: output_high(PIN_B4);
                   break;
       case 2: output_high(PIN_B3);
                   break;
       case 3: output_high(PIN_B2);
                   break;
       case 4: output_high(PIN_B1);
                   break;
       case 5: output_high(PIN_B0);
                   break;
       case 6: output_high(PIN_C7);
                   break;
       case 7: output_high(PIN_C6);
                   break;
       case 8: output_high(PIN_C5);
                   break;
       case 9: output_high(PIN_C2);
                   break;
      }                       
}

_________________
Ringo Davis
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Fri Jun 06, 2008 1:52 pm     Reply with quote

I thought it was working, but I can read the board a few times, then it locks up. I took out the pin array so I'm using 3.249 now. I've striped the code down to bare essentials. It just returns an array of 15 over I2C. I put an led blinking routine in there so I can see when it locks up. sometimes it is on the first read, sometimes it makes it to 6 or 7, but not usually beyond that. any ideas here?
Code:

#include <16F876a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
//#use rs232(baud=115200, xmit=PIN_b6, rcv=PIN_b7)
#use standard_io(B)
#use standard_io(C)
#byte PIC_SSPADD=0x93
#define initial_i2c_address  0x82
int     NODE_ADDR  =  initial_i2c_address;// Decimal 130
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x82,slow)

int Dio_states[10];
int values[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
int Power_up_state[10];
BYTE address, buffer[0x10];
int bytecounter=0;
int actionflag=0; //0 = nothing, 1 = read, 2 = change address


#INT_SSP
void ssp_interupt()
{
    int i;
    BYTE incoming, state;
    int pinnumber,pinstate,dummy;
   state = i2c_isr_state();
   if(state < 0x80)                     //Master is sending data
   {   }
   if(state == 0x80)   //Master is requesting data
   {
      actionflag=1; //0 = nothing, 1 = read, 2 = change address
      bytecounter=0;
   }
}

void main ()
{
    int i;
    int32 counter=0;
    int toggle=0;

    setup_adc_ports(All_ANALOG);
    setup_adc( ADC_CLOCK_INTERNAL );
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_SSP);

    for(i=0;i<10;i++)
    {
        Dio_states[i]=2;//input
        //values[i+5]=0;
    }       

    delay_ms(500);
    output_high(PIN_B6);
   
      while (1)
    {
      counter++;
      if(counter>10000)
      {
          counter=0;
          if(toggle==0)
          {
              toggle=1;
              output_high(Pin_B7)   ;
          }
             else
            {
              toggle=0;
              output_low(Pin_B7)   ;
            }   
        }
        if(actionflag==1) //0 = nothing, 1 = read, 2 = change address 
        {
            actionflag=0; 
          for(i=0;i<15;i++)
            {
                delay_ms(1);
              i2c_write(values[i]);
            }
        }
    }
}

_________________
Ringo Davis
Ttelmah
Guest







PostPosted: Sat Jun 07, 2008 4:18 am     Reply with quote

4.011, has problems, so you are 'right' to try with 3.249.

In your demo code, you _must_ perform the required I2C operations in your interrupt handler. So, you should read the contents of the buffer register, when you are expected to read a byte, and write the new byte for the write. The SSPOV flag will become set with the current code, since the register has not been read. So, something like:
Code:

#INT_SSP
void ssp_interupt() {
    int i;
    BYTE incoming, state;
    int pinnumber,pinstate,dummy;
    state = i2c_isr_state();
    if(state < 0x80)  {               //Master is sending data
       incoming=I2C_READ();
    }
    if(state == 0x80)  {            //Master is requesting data
      actionflag=1; //0 = nothing, 1 = read, 2 = change address
      bytecounter=0;
      I2C_WRITE(1);                //Dummy write
   }
}

The data sheets, do not say what the effect of the SSPOV flag being set actually 'is', but you should avoid error conditions when testing.

Best Wishes
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Mon Jun 09, 2008 10:53 am     Reply with quote

I'm reading 15 bytes of data from the slave. I put the I2C_write code in the int, but I still get the same thing. A few good reads of the slave, then it all goes to 255's.
Here is the modifed code.
Code:
#include <16F876a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
//#use rs232(baud=115200, xmit=PIN_b6, rcv=PIN_b7)
#use standard_io(B)
#use standard_io(C)
#byte PIC_SSPADD=0x93
#define initial_i2c_address  0x82
int     NODE_ADDR  =  initial_i2c_address;// Decimal 130
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x82,slow)

int Dio_states[10];
int values[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
int Power_up_state[10];
BYTE address, buffer[0x10];
int bytecounter=0;
int actionflag=0; //0 = nothing, 1 = read, 2 = change address
int data_counter=0;

#INT_SSP
void ssp_interupt()
{
    int i;
    BYTE incoming, state;
    int pinnumber,pinstate,dummy;
   state = i2c_isr_state();
   if(state < 0x80)                     //Master is sending data
   {   }
   if(state == 0x80)   //Master is requesting data
   {
          for(i=0;i<15;i++)
            {
                delay_ms(1);
              i2c_write(values[i]);
            }
      actionflag=1; //0 = nothing, 1 = read, 2 = change address
      bytecounter=0;
   }
}

void main ()
{
    int i;
    int32 counter=0;
    int toggle=0;

    setup_adc_ports(All_ANALOG);
    setup_adc( ADC_CLOCK_INTERNAL );
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_SSP);

    for(i=0;i<10;i++)
    {
        Dio_states[i]=2;//input
        //values[i+5]=0;
    }       

    delay_ms(500);
    output_high(PIN_B6);
   
      while (1)
    {
      counter++;
      if(counter>10000)
      {
          counter=0;
          if(toggle==0)
          {
              toggle=1;
              output_high(Pin_B7)   ;
          }
             else
            {
              toggle=0;
              output_low(Pin_B7)   ;
            }   
        }
        if(actionflag==1) //0 = nothing, 1 = read, 2 = change address 
        {
            actionflag=0; 
//          for(i=0;i<15;i++)
//            {
//                delay_ms(1);
//              i2c_write(values[i]);
//            }
        }
    }
}


Any other ideas?
Ringo
_________________
Ringo Davis
Ttelmah
Guest







PostPosted: Mon Jun 09, 2008 2:48 pm     Reply with quote

You have put the I2C write code in, but _not_ the read code. This is the essential part, since when you send the address byte, followed by the command byte, there are two successive bytes, and the first must be read, if the overflow bit is not going to be set...

Best Wishes
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Thu Jun 26, 2008 11:16 am     Reply with quote

Here is a new issue. I have the code working great for the 16F876A. I changed over to an 18F2221. I thought the code would work as is. It has the same # pins with the same functions, etc. The only difference is that with the 876 I'm using a 20mhz crystal, and with the 2221 I'm using the internal 8mhz.
I set it up like this;
Code:

#if defined(__PCM__)
    #include <16F876a.h>
    #fuses HS,noWDT,NOPROTECT,NOLVP
    #use delay(clock=20000000)

#elif defined(__PCH__)
    #include <18F2221.h>
    #fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP
    #use delay(clock=8000000)
    #byte SSPCON2 = 0xFC5
    #bit SEN = SSPCON2.0

#endif

Should this cause a problem?

Here is what I'm seeing. Reading works the same for either chip. However when I write. Using the 876 I get buffer[0] as the address, so buffer[1] is the command. However with the 2221 I get buffer[0] as the command.
It is a small difference, but I didn't think there should be any at all. is this really a chip difference, or am I missing the first byte because of the 8mhz?

I'm sending a command to set an I/O pin High. The address is 130, the command number is 1, so to set pin 1 high I send
130 1 1 1.

Here is the INT code.

Code:

#INT_SSP
void ssp_interupt()
{
    int i;
    BYTE incoming, state;
   state = i2c_isr_state();
   if(state < 0x80)                     //Master is sending data
   {
       incoming = i2c_read();
        buffer[bytecounter]=incoming;
        bytecounter++;
        if(bytecounter ==3 )// this one works for the 2221
        {
//        printf("%d %d %d %d\r\n",buffer[0],buffer[1],buffer[2],buffer[3]);
            if(buffer[0]==1)                           // Set, GPIO
            {
                pinnumber=buffer[1];
                pinstate=buffer[2];
                bytecounter=0;
                Dio_states[pinnumber]=pinstate;
                actionflag=3;
            }   
        }
        if(bytecounter ==4 )// this works for the 876A
        {
            if(buffer[1]==1)                           // Set, GPIO
            {
                pinnumber=buffer[2];
                pinstate=buffer[3];
                bytecounter=0;
                Dio_states[pinnumber]=pinstate;
                actionflag=3;
            }   
        }//end of 4

   }
   if(state == 0x80)   //Master is requesting data
   {
          for(i=0;i<15;i++)
            {
                delay_ms(1);
              i2c_write(values[i]);
            }

      actionflag=1; //0 = nothing, 1 = read, 2 = change address
      bytecounter=0;
   }
}


The 876A code is compiled with 3.249
the 2221 I have tried with 3.249 and 4.074
Ringo
_________________
Ringo Davis
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