|
|
View previous topic :: View next topic |
Author |
Message |
imacgreg
Joined: 09 Nov 2009 Posts: 5 Location: Echo Park, Los Angeles, CA
|
Problem Reading Input from Port C with 16F690 |
Posted: Wed Sep 15, 2010 10:52 pm |
|
|
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
|
|
Posted: Thu Sep 16, 2010 12:09 pm |
|
|
Yes, post a small compilable program that I can test. |
|
|
imacgreg
Joined: 09 Nov 2009 Posts: 5 Location: Echo Park, Los Angeles, CA
|
|
Posted: Sun Sep 19, 2010 4:32 pm |
|
|
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
|
|
Posted: Sun Sep 19, 2010 6:00 pm |
|
|
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: 1934 Location: Norman, OK
|
|
Posted: Mon Sep 20, 2010 6:02 am |
|
|
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
|
|
Posted: Mon Sep 20, 2010 9:21 am |
|
|
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: 1934 Location: Norman, OK
|
|
Posted: Mon Sep 20, 2010 12:43 pm |
|
|
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
|
|
Posted: Tue Sep 21, 2010 1:39 am |
|
|
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
|
|
Posted: Tue Sep 21, 2010 1:59 am |
|
|
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 |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Sep 21, 2010 2:09 am |
|
|
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
|
|
Posted: Tue Sep 21, 2010 2:12 am |
|
|
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
|
|
Posted: Tue Sep 21, 2010 5:27 pm |
|
|
Wow...
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 |
|
|
|
|
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
|