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

Problem Reading Input from Port C with 16F690

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



Joined: 09 Nov 2009
Posts: 5
Location: Echo Park, Los Angeles, CA

View user's profile Send private message Visit poster's website

Problem Reading Input from Port C with 16F690
PostPosted: Wed Sep 15, 2010 10:52 pm     Reply with quote

Hi,
I can post code if needed... but maybe this is an easy fix. Using PIC16F690. PCW complier v4.099.

I am trying to use Pin C5 to read a digital input from a pushbutton. I have multiple identical inputs using Ports A and B working just fine. Same exact code being used to read pin (and output condition to associated LED).

I can't get the input with C5 working ok. I am using software SPI via:

Code:
#use spi(DO=PIN_C7, CLK=PIN_B6, DI=PIN_A5, MASTER, BAUD=1000, LOAD= PIN_A4, LOAD_ACTIVE = 1, BITS=16, MODE=0)


I'm wondering that using C7 as an output for the SPI is somehow involved?? I've tried using #use FAST_IO and then setting the tris register for Port C, but no luck.

Let me know if full compile-able code would be helpful and I'll post it...

Thanks
ian
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 16, 2010 12:09 pm     Reply with quote

Yes, post a small compilable program that I can test.
imacgreg



Joined: 09 Nov 2009
Posts: 5
Location: Echo Park, Los Angeles, CA

View user's profile Send private message Visit poster's website

PostPosted: Sun Sep 19, 2010 4:32 pm     Reply with quote

Code:
#include <16F690.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                     //Internal RC Osc
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled

#use delay(clock=4000000)


   //FUNCTION PIN DEFINITIONS
#Define MONO_PIN           PIN_A5
#Define LEVEL_PIN          PIN_C6
#Define DIM_PIN            PIN_C5
#Define TB_PIN             PIN_A3

   //MUTE PIN DEFINITIONS
#Define LEFT_MUTE_PIN      PIN_A0
#Define RIGHT_MUTE_PIN     PIN_A1
#Define SUB_MUTE_PIN       PIN_A2

   //INPUT PIN DEFINITIONS
#Define IN_SEL0_PIN        PIN_C0
#Define IN_SEL1_PIN        PIN_C1
#Define IN_SEL2_PIN        PIN_C2
#Define IN_SEL3_PIN        PIN_C3

   //OUTPUT PIN DEFINITIONS
#Define OUT_SEL0_PIN       PIN_B4
#Define OUT_SEL1_PIN       PIN_C4


//           LED_STATE BYTE DEFINITION:
//    MSB............................................................................................................LSB
//    | 15   | 14    | 13    | 12      | 11   | 10   | 9     | 8      || 7    | 6    | 5    | 4   | 3   | 2   | 1   | 0   |
//    | MONO | MUTER | MUTEL | MUTESUB | TB   | DIM  | ERROR | STATUS || OUT3 | OUT2 | OUT1 | IN5 | IN4 | IN3 | IN2 | IN1 |


#Define MONO_LED 0x8000
#Define RIGHT_MUTE_LED 0x4000
#Define LEFT_MUTE_LED 0x2000
#Define SUB_MUTE_LED 0x1000

#Define TB_LED 0x0800
#Define DIM_LED 0x0400
#Define ERROR_LED 0x0200
#Define STATUS_LED 0x0100

#Define OUT3_LED 0x0080
#Define OUT2_LED 0x0040
#Define OUT1_LED 0x0020
#Define IN5_LED 0x0010

#Define IN4_LED 0x0008
#Define IN3_LED 0x0004
#Define IN2_LED 0x0002
#Define IN1_LED 0x0001

//END of HEADER FILE - START PROGRAM FILE BELOW

#use spi(DO=PIN_C7, CLK=PIN_B6, DI=PIN_A5, MASTER, BAUD=1000, LOAD= PIN_A4, LOAD_ACTIVE = 1, BITS=16, MODE=0) //software SPI declaration. Look into ENABLE pin as strobe
#use fast_io(c) 


int16 LED_STATE = 0x0000; //Pendant local LED conditions. 1 is on, 0 is off.
//FUNCTION VARIABLES

int1 LEFT_MUTE_FUNCTION, CURRENT_LEFT_MUTE_SWITCH;
int1 RIGHT_MUTE_FUNCTION,CURRENT_RIGHT_MUTE_SWITCH;
int1 SUB_MUTE_FUNCTION, CURRENT_SUB_MUTE_SWITCH;
int1 MONO_FUNCTION, CURRENT_MONO_SWITCH;
int1 DIM_FUNCTION, CURRENT_DIM_SWITCH;
int1 TB_FUNCTION, CURRENT_TB_SWITCH;

int SPI_Update_Ctr = 0;

#int_TIMER2
void TIMER2_isr(void) // ISR occurs every 500 usecs, used to scan digital inputs and update local SPI
{   


 //LEFT_MUTE ------------------------------------------------------------------------------------------------- 
   if (input(LEFT_MUTE_PIN) && (CURRENT_LEFT_MUTE_SWITCH ==0)){ // if left mute button wasn't previously pressed and is now pressed
   LEFT_MUTE_FUNCTION = !LEFT_MUTE_FUNCTION; //toggle the left mute function. If the mute was on, turn off and visa versa   
   CURRENT_LEFT_MUTE_SWITCH = 1; //switch is now seen as being pressed
  }
  if ((CURRENT_LEFT_MUTE_SWITCH ==1) && !input(LEFT_MUTE_PIN)){ //if button used to be pressed and is now released
   CURRENT_LEFT_MUTE_SWITCH = 0; //set the new current switch state as released 
  }
 
  if(LEFT_MUTE_FUNCTION){ // if the mute function is true - speaker is muted
  LED_STATE = LED_STATE | LEFT_MUTE_LED; // bitwise OR the LED_STATE word with the location of the LEFT_MUTE LED to turn it on
   }
   else{
      LED_STATE = LED_STATE & ~LEFT_MUTE_LED; //bitwise AND the LED_STATE word with the NOT location of the LEFT_MUTE LED to turn it off
   }

     //RIGHT_MUTE-------------------------------------------------------------------------------------------------   
   if (input(RIGHT_MUTE_PIN) && (CURRENT_RIGHT_MUTE_SWITCH ==0)){ // if RIGHT mute button wasn't previously pressed and is now pressed
   RIGHT_MUTE_FUNCTION = !RIGHT_MUTE_FUNCTION; //toggle the RIGHT mute function. If the mute was on, turn off and visa versa   
   CURRENT_RIGHT_MUTE_SWITCH = 1; //switch is now seen as being pressed
  }
  if ((CURRENT_RIGHT_MUTE_SWITCH ==1) && !input(RIGHT_MUTE_PIN)){ //if button used to be pressed and is now released
   CURRENT_RIGHT_MUTE_SWITCH = 0; //set the new current switch state as released 
  }
 
  if(RIGHT_MUTE_FUNCTION){ // if the mute function is true - speaker is muted
  LED_STATE = LED_STATE | RIGHT_MUTE_LED; // bitwise OR the LED_STATE word with the location of the RIGHT_MUTE LED to turn it on
  }
   else{
      LED_STATE = LED_STATE & ~RIGHT_MUTE_LED; //bitwise AND the LED_STATE word with the NOT location of the RIGHT_MUTE LED to turn it off

  }
       //SUB_MUTE-------------------------------------------------------------------------------------------------   
   if (input(SUB_MUTE_PIN) && (CURRENT_SUB_MUTE_SWITCH ==0)){ // if SUB mute button wasn't previously pressed and is now pressed
   SUB_MUTE_FUNCTION = !SUB_MUTE_FUNCTION; //toggle the SUB mute function. If the mute was on, turn off and visa versa   
   CURRENT_SUB_MUTE_SWITCH = 1; //switch is now seen as being pressed
  }
  if ((CURRENT_SUB_MUTE_SWITCH ==1) && !input(SUB_MUTE_PIN)){ //if button used to be pressed and is now released
   CURRENT_SUB_MUTE_SWITCH = 0; //set the new current switch state as released 
  }
 
  if(SUB_MUTE_FUNCTION){ // if the mute function is true - speaker is muted
  LED_STATE = LED_STATE | SUB_MUTE_LED; // bitwise OR the LED_STATE word with the location of the SUB_MUTE LED to turn it on
  }
   else{
      LED_STATE = LED_STATE & ~SUB_MUTE_LED; //bitwise AND the LED_STATE word with the NOT location of the SUB_MUTE LED to turn it off
   }
   
          //MONO------------------------------------------------------------------------------------------------- 
   if (input(MONO_PIN) && (CURRENT_MONO_SWITCH ==0)){ // if MONO button wasn't previously pressed and is now pressed
   MONO_FUNCTION = !MONO_FUNCTION; //toggle the MONO function. If the MONO was on, turn off and visa versa   
   CURRENT_MONO_SWITCH = 1; //switch is now seen as being pressed
  }
  if ((CURRENT_MONO_SWITCH ==1) && !input(MONO_PIN)){ //if button used to be pressed and is now released
   CURRENT_MONO_SWITCH = 0; //set the new current switch state as released 
  }
 
  if(MONO_FUNCTION){ // if the MONO function is true - speaker MONO
  LED_STATE = LED_STATE | MONO_LED; // bitwise OR the LED_STATE word with the location of the MONO LED to turn it on
  }
   else{
      LED_STATE = LED_STATE & ~MONO_LED; //bitwise AND the LED_STATE word with the NOT location of the MONO LED to turn it off
   }
   
             //DIM------------------------------------------------------------------------------------------------- 
   if (input(DIM_PIN) && (CURRENT_DIM_SWITCH ==0)){ // if DIM button wasn't previously pressed and is now pressed
   DIM_FUNCTION = !DIM_FUNCTION; //toggle the DIM function. If the DIM was on, turn off and visa versa   
   CURRENT_DIM_SWITCH = 1; //switch is now seen as being pressed
  }
  if ((CURRENT_DIM_SWITCH ==1) && !input(DIM_PIN)){ //if button used to be pressed and is now released
   CURRENT_DIM_SWITCH = 0; //set the new current switch state as released 
  }
 
  if(DIM_FUNCTION){ // if the DIM function is true - speaker is DIM
  LED_STATE = LED_STATE | DIM_LED; // bitwise OR the LED_STATE word with the location of the DIM LED to turn it on
  }
   else{
      LED_STATE = LED_STATE & ~DIM_LED; //bitwise AND the LED_STATE word with the NOT location of the DIM LED to turn it off
   }

             //TalkBack (TB)-------------------------------------------------------------------------------------------
   if (input(TB_PIN)){ // if TB button is pressed
   TB_FUNCTION = 1; //Turn TB function on.
   DIM_FUNCTION = 1; //Also turn DIM on
  }
  if (!input(TB_PIN)){ //if button used to be pressed and is now released
   TB_FUNCTION = 0; //Turn TB function off.
   DIM_FUNCTION = 0; //Also turn DIM off
  }
 
  if(TB_FUNCTION){ // if the TB function is true - Talkback engaged and speaker is DIM
  LED_STATE = LED_STATE | TB_LED | DIM_LED; // bitwise OR the LED_STATE word with the location of the DIM and TB LEDs to turn it on
  }
   else{
      LED_STATE = LED_STATE & ~TB_LED & ~DIM_LED; //bitwise AND the LED_STATE word with the NOT location of the DIM and TB LEDs to turn it off
   }

         //Local SPI Update, only happens once every 20mSec-----------------------------------------------------------
if(SPI_Update_Ctr >= 40){ //if 20mSec has elapsed, then output LED State over SPI and reset counter
   SPI_Update_Ctr = 0;
   spi_xfer(LED_STATE); 
}

else{
   SPI_Update_Ctr++; //else if 20mSec has not elapsed, then increment SPI_Update_Ctr.
}

}
void main()
{

    setup_adc_ports(NO_ANALOGS|VSS_VDD);
 // setup_adc(ADC_CLOCK_DIV_2);
    setup_timer_0(RTCC_INTERNAL);
    setup_timer_1(T1_DISABLED);
    setup_timer_2(T2_DIV_BY_1,166,6);  // Generates interrupt every 500 usec
    enable_interrupts (int_TIMER2);
    enable_interrupts(global);
    setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
    setup_ccp1(CCP_OFF); //disable CCP module

   set_tris_c(0b01111111); // set all port C to inputs, except C7


//    SET INITIAL STATES

LEFT_MUTE_FUNCTION = 1; // default is Left channel muted
CURRENT_LEFT_MUTE_SWITCH = 0; //sets the current Left Mute switch condition to not pressed.

RIGHT_MUTE_FUNCTION = 1; // default is Right channel muted
CURRENT_RIGHT_MUTE_SWITCH = 0; //sets the current Right Mute switch condition to not pressed.

SUB_MUTE_FUNCTION = 1; // default is Sub channel muted
CURRENT_SUB_MUTE_SWITCH = 0; //sets the current Sub Mute switch condition to not pressed.

MONO_FUNCTION = 0; // default is Mono not engaged
CURRENT_MONO_SWITCH = 0; //sets the current Mono switch condition to not pressed.

DIM_FUNCTION = 0; // default is Dim not engaged
CURRENT_DIM_SWITCH = 0; //sets the current Dim switch condition to not pressed.

TB_FUNCTION = 0; // default is TB not engaged
CURRENT_TB_SWITCH = 0; //sets the current TB switch condition to not pressed.


   
  while(TRUE){

   }



  }
 
 


Ok.... here's my current code, header file at the top. I have bunch of buttons (interfaced to digital inputs) for things like left mute, right mute, etc. The button that I am having issues with is the DIM. You can see in the header file that this is defined at pin_c5.

The program basically uses an interrupt routine to read the state of all the buttons and updates status LEDs every 20mSec. There are other functions that will be implemented later and I may change my overall routine, add de-bouncing, etc. I'm just trying to figure out why Pin C5 is not working.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Sep 19, 2010 6:00 pm     Reply with quote

My purpose is the narrow topic of: Can pin C5 be made to work with
a push-button switch on a 16F690 with vs. 4.099 of the compiler ?
(I don't really want to work on anything more than this).

I cut your program down in size until I could get it small enough so I
could sort of understand it and make it do something.

I compiled the program shown below with vs. 4.099 and ran it on a 3M
breadboard. When I hold down the pushbutton on Pin C5, the LED goes
on, and when I release it, the LED goes off. So it is responding to pin C5.
Here is a schematic of the push-button circuit that I used:
Code:

           +5v
            |
            <
            > 4.7K       
            <         ___ Push button switch 
To          |        _|_|_
PIC -----------------o   o------
pin                            |             
                              --- GND
                               -   


To make it work I added a few lines and changed a few things.
Code:

#include <16F690.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                     //Internal RC Osc
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN             

#use delay(clock=4000000)

#Define DIM_PIN  PIN_C5
#define LED_PIN  PIN_C4

int1 CURRENT_DIM_SWITCH;

#int_TIMER2
void TIMER2_isr(void) // ISR occurs every 500 usecs, used to scan digital inputs and update local SPI
{   
 
if((input(DIM_PIN) == 0) && (CURRENT_DIM_SWITCH ==0)){ // if DIM button wasn't previously pressed and is now pressed
   CURRENT_DIM_SWITCH = 1; //switch is now seen as being pressed
   output_high(LED_PIN);
  }

if((CURRENT_DIM_SWITCH == 1) && (input(DIM_PIN) == 1)){ //if button used to be pressed and is now released
   CURRENT_DIM_SWITCH = 0; //set the new current switch state as released 
   output_low(LED_PIN);
  }
 
}


void main()
{
CURRENT_DIM_SWITCH = 0;

setup_timer_2(T2_DIV_BY_1,166,6);  // Generates interrupt every 500 usec
enable_interrupts (int_TIMER2);
enable_interrupts(global);
   
while(TRUE);
}
 
dyeatman



Joined: 06 Sep 2003
Posts: 1938
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Sep 20, 2010 6:02 am     Reply with quote

imacgreg,

question: Why are you using 500usec for the scan rate? That seems much
too fast and just eats up CPU resources. I think 50-75ms would be still be
fast enough and leave much more time for other things you want to do (like
communications which typically takes much longer than one 500usec
interval).
_________________
Google and Forum Search are some of your best tools!!!!


Last edited by dyeatman on Mon Sep 20, 2010 1:44 pm; edited 1 time in total
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Mon Sep 20, 2010 9:21 am     Reply with quote

dyeatman wrote:
question: Why are you using 500usec for the scan rate? That seems much
too fast and just eats up CPU resources. I think 50-75ms would be still be
fast enough and leave much more time for other things you want to do (like
communications which typically takes much longer than one 500usec
interval).


LOL

Why is PCM programmer doing what the original poster should have done in the first place ? The sample rate that PCM programmer is using is irrelevant, he is not trying to write the code for imacgreg, just show that the problem is not the PIC.

PCM programmer should be commended on going well out of his way to help imacgreg in this respect.

Well done, and don't do it again ;)
or we may all have to go to extremes for people!
dyeatman



Joined: 06 Sep 2003
Posts: 1938
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Sep 20, 2010 12:43 pm     Reply with quote

I wasn't referring to PCM or his code at all. I was asking the original poster!
I guess I wasn't clear... I have now fixed that.
_________________
Google and Forum Search are some of your best tools!!!!
imacgreg



Joined: 09 Nov 2009
Posts: 5
Location: Echo Park, Los Angeles, CA

View user's profile Send private message Visit poster's website

PostPosted: Tue Sep 21, 2010 1:39 am     Reply with quote

PCM programmer wrote:
My purpose is the narrow topic of: Can pin C5 be made to work with
a push-button switch on a 16F690 with vs. 4.099 of the compiler ?
(I don't really want to work on anything more than this).

I cut your program down in size until I could get it small enough so I
could sort of understand it and make it do something.


Ok... I compiled this and loaded it on to my PIC board and yes it works. Thanks for taking the time to cut my code down... I was in a hurry to get it posted here so I just posted the whole thing.

So I anticipated the next step was to verify that the simple pin C5 test program would also work with the SPI driven serial registers (that control 16 LEDs on my board). See the code below:

Code:

#include <16F690.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                     //Internal RC Osc
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN             

#use delay(clock=4000000)

#Define DIM_PIN  PIN_C5
#define LED_PIN  PIN_C4
#use spi(DO=PIN_C7, CLK=PIN_B6, DI=PIN_A5, MASTER, BAUD=1000, LOAD= PIN_A4, LOAD_ACTIVE = 1, BITS=16, MODE=0) //software SPI declaration.


int1 CURRENT_DIM_SWITCH;

#int_TIMER2
void TIMER2_isr(void) // ISR occurs every 500 usecs, used to scan digital inputs and update local SPI
{   
 
if((input(DIM_PIN) == 0) && (CURRENT_DIM_SWITCH ==0)){ // if DIM button wasn't previously pressed and is now pressed
   CURRENT_DIM_SWITCH = 1; //switch is now seen as being pressed
   output_high(LED_PIN);
   spi_xfer(0xFFFF);
   delay_ms(10);
  }

if((CURRENT_DIM_SWITCH == 1) && (input(DIM_PIN) == 1)){ //if button used to be pressed and is now released
   CURRENT_DIM_SWITCH = 0; //set the new current switch state as released 
   output_low(LED_PIN);
   spi_xfer(0x0000);
   delay_ms(10);
  }
 
}


void main()
{
CURRENT_DIM_SWITCH = 0;

setup_timer_2(T2_DIV_BY_1,166,6);  // Generates interrupt every 500 usec
enable_interrupts (int_TIMER2);
enable_interrupts(global);
   
while(TRUE);
}


The above code works just fine. So my issue has nothing to do with SPI, right?

Note: Removing the #fast_io and set_tris_c does not "fix" my original code.

So at this point, I'm still a little stumped as to why my original code wasn't working properly with respect to receiving an input from PIN_C5. I do notice a few differences between your test code and my original code... but I'm not clear on why any of the differences could be causing this issue..


Ohh... and the ISR timing is just left over from another piece of code that I "snagged" from a previous program. At some point, I will need to iron out some of the timing and may need to add proper debouncing, but currently, I'm just trying to get some basic functionality.

I really appreciate your time and help!

Ian
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Tue Sep 21, 2010 1:59 am     Reply with quote

dyeatman wrote:
I wasn't referring to PCM or his code at all. I was asking the original poster!
I guess I wasn't clear... I have now fixed that.


I appologise, I thought you were refering to PCM Embarassed
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Tue Sep 21, 2010 2:09 am     Reply with quote

Does the DIM_LED turn on and off then you toggle the TB button ?
imacgreg



Joined: 09 Nov 2009
Posts: 5
Location: Echo Park, Los Angeles, CA

View user's profile Send private message Visit poster's website

PostPosted: Tue Sep 21, 2010 2:12 am     Reply with quote

Wayne_ wrote:
Does the DIM_LED turn on and off then you toggle the TB button ?


Yes (i assume you mean "when" I toggle the TB button). This is how I figured that the problem was on the DIM switch input side and not on the LED side.

The TB function (which acts as a momentary function) does turn on both the TB and DIM LEDs when the TB button is pressed.
imacgreg



Joined: 09 Nov 2009
Posts: 5
Location: Echo Park, Los Angeles, CA

View user's profile Send private message Visit poster's website

PostPosted: Tue Sep 21, 2010 5:27 pm     Reply with quote

Wow...

Embarassed

Think I figured it out... Has nothing to do with the input pin and everything to do with the TB routine negating any changes made by the DIM section.

Thanks for all your help!

Ian
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