View previous topic :: View next topic |
Author |
Message |
Username
Joined: 01 Nov 2011 Posts: 17
|
Can someone tell me why this doesn't code work |
Posted: Tue Nov 22, 2011 6:28 pm |
|
|
Code: |
#include "C:\Users\Admin\Documents\CCS Projects\main.h"
#define GP0 PIN_A0
#define GP1 PIN_A1
#define GP2 PIN_A2
#define GP3 PIN_A3
#define GP4 PIN_A4
#define GP5 PIN_A5
void ledflashsr()
{
static int8 mode;
if (mode==1)
{ output_high(GP5);
delay_ms(500);
output_low(GP5);}
else if(mode==2)
{output_high(GP5);
delay_ms(500);
output_low(GP5);
delay_ms(500);
output_high(GP5);
delay_ms(500);
output_low(GP5);}
else if(mode==3)
{output_high(GP5);
delay_ms(500);
output_low(GP5);
delay_ms(500);
output_high(GP5);
delay_ms(500);
output_low(GP5);
delay_ms(500);
output_high(GP5);
delay_ms(500);
output_low(GP5);}
}
void main()
{
static int8 mode, mode_led_flash;
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ);
mode=3;
mode_led_flash=1;
while(1){
if (input(GP4)==1)
++ mode;
mode=mode%3;
if (mode!=mode_led_flash)
mode_led_flash=mode;
ledflashsr();
}
}
|
This is a simple push button mode changing application. This doesn't include the modes. My question is why isn't it working correctly? There is probably something simple im missing.
I also am wondering why if I declare a variable in the main(), even as static, I have to delcare it in the subroutine. Won't this lead to 2 separate but same named variables?
Thanks |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Nov 22, 2011 7:24 pm |
|
|
Quote: |
simple push button mode changing
|
yes that seems to indeed be the case if by any chance
GP4 is your push button.
You might ask yourself
" How does my button debouncer work ?"
another good question is:
"How do all my cumulative delays impact execution ?"
and a question to you:
" are you gonna USE any of those timers you set up
to help yourself?"
as to:
Quote: |
Won't this lead to 2 separate but same named variables?
|
Have you looked at the LST file this creates?
The answer is there for you. |
|
|
Username
Joined: 01 Nov 2011 Posts: 17
|
|
Posted: Tue Nov 22, 2011 7:50 pm |
|
|
Sorry, I never thought to check that. Okay, so it did create 2 different variables. How can I make it create just one global variable?
As to the debouncer, I think I remember reading about something like that once. How would I go about doing that?
What do you mean by cumulative delays?
And what timers did I set up?
Thanks |
|
|
W4GNS
Joined: 28 Sep 2010 Posts: 14 Location: Virginia, USA
|
|
Posted: Tue Nov 22, 2011 8:45 pm |
|
|
Username wrote: |
As to the debouncer, I think I remember reading about something like that once. How would I go about doing that?
Thanks |
A good starting point would be here http://www.ganssle.com/debouncing.htm then come back to this forum and use the search function using debounce as a keyword, and you'll be all set _________________ PCWH 4.14 |
|
|
Username
Joined: 01 Nov 2011 Posts: 17
|
|
Posted: Tue Nov 22, 2011 10:08 pm |
|
|
So do you think if I implement this code it will work?
Code: |
int count;
Void Push_Button()
{
static int1 pushed = false;
if (!pushed && !button1) // Pressed
{
pushed = true;
if (++count > 4)
count = 1;
} else if (button1) // Released
pushed = false; |
And should debouncing that button press make the code actually work, or are there other things wrong with my code that aren't listed? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Nov 23, 2011 4:12 am |
|
|
Username wrote: | And should debouncing that button press make the code actually work, or are there other things wrong with my code that aren't listed? | Get real! What do you think yourself?
- Did you fix the problem with the 2 mode variables?
- Have you looked at the suggestion for the problem with the extreme long delays? How long does the user have to press the key before being detected by the program?
Then there are at least a few other problems:
- All 3 flashing modes are the same, you won't see a difference.
- All flashing modes have another delay problem, for example try to think what happens in mode1, how long will GP5 be low?
And I suggest you get your C reference guide to look up the purpose of the static keyword inside a function. That's all I found in looking at your code for 2 minutes, there might be more. |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Nov 23, 2011 8:39 am |
|
|
You've committed sin #1 of the lazy programmer, namely using the delay_ms construction, and you're paying for it.
If you used an interrupt running off a timer, you wouldn't have to worry about what happens when the user pushes the button during the flash routine, and you wouldn't have to worry about debouncing the button. But it's so easy just to put in those delays, isn't it? |
|
|
Username
Joined: 01 Nov 2011 Posts: 17
|
|
Posted: Wed Nov 23, 2011 3:04 pm |
|
|
Thanks for all of your responses. I have a few questions though.
How will all of the modes be the same when it comes to flashes. If there was no input detected after execution the flashing, it wouldn't go back to the flashing. And after the program finishes flashing, wouldn't it return to main through ledflashsr()?
How can i go about adding a timer interrupt into the program?
Thanks again. By the way, im trying to teach myself to do this, so please don't be critical of me. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Nov 23, 2011 3:08 pm |
|
|
If you haven't done this.. press F11 when you're in your project. It opens the CCS OnScreen Helpfile. TONS of important, easy to understand information at your fingertips !!
I keep it open all the time...very handy reference.
Also go to the Examples folder and look at some of the examples. Printing them out may help to understand better how CCS C is used. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Nov 23, 2011 3:35 pm |
|
|
ok - still very much in fundamental C language bad-lands U R
(A)
HOW MANY values can 'mode' have with this statement present?
my belief is that the complete state list
for 'mode ' can only be 0,1,2
- and, ummmmmm, what are you trying to display??
(B)
now i want you to think HARD about this next bit
Code: |
if (input(GP4)==1)
++ mode;
|
and answer if the button is held down for LESS than one "mode's worth"
of display time - and also for MORE than that
HOW often can / will MODE be "++'d" under each condition ??
hint: learn to think in the time domain , and consider the "states"
your code will define. I think U will find it works so much better.
(c)
Here is an idea:
Look up this page to the header area.
See the link called SEARCH?
Try a search like "TIMER INTERRUPT" and see what happens .
I am not going to tell you what you need to find out YOURSELF -
Other wise you are not learning - and i am not teaching....
Then you are only being the lucky recipient of the generosity of others who DID do the work already , the hard way.....
|
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Thu Nov 24, 2011 7:45 pm |
|
|
Using a timer is incredibly easy and incredibly important.
In the main() function you just use something like this:
Code: |
setup_timer_2( T2_DIV_BY_16, 250, 1); // Repeat rate is 2000000/(16 * 250) = 500/sec or 2 msec
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
|
And the interrupt routine itself is just like any function, except that it will have no arguments and it won't return anything. It's all in the manual.
Code: |
#int_timer2
tmr2_isr()
{
// Read pushbuttons, flash lights etc
}
|
|
|
|
Username
Joined: 01 Nov 2011 Posts: 17
|
|
Posted: Sat Nov 26, 2011 11:18 pm |
|
|
I understand that after a certain amount of time, it returns a value on overflow. The one thing I can't understand after looking at countless uses of timer interrupts is:
How is it any different when it comes to being time specific?
And how is it any different than a regular function? What makes it an interrupt? How is it called in an interrupt way?
And why should it be called instead of using delay?
I can usually understand things from looking at them, but can someone just give a detailed explanation please. Everything I have looked at doesn't make it clear to me, im not really sure why. I understand using the search button to find things myself, its just that I can't grasp the idea of how to implement timers from the examples I've looked at.
Thanks
Edit:
After thinking about it... So I would use the timer to check for a mode change, say every 2 ms. That way, even while in a loop, the mode would be allowed to change. Is this how I would implement it? |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Sun Nov 27, 2011 1:11 pm |
|
|
An interrupt is a special function that doesn't have to be called. It runs automatically if the defined conditions occur, with a jump from the regular code, and then a jump back to the same place in regular code. You shouldn't have to think about when or how this happens. The reason to use an interrupt rather than a delay() function is that with the delay, the processor simply waits and does nothing else, even if there are events that should be responded to, like a button press.
So you might have this in your code (assume the button is a connection to Gnd on Portb.1 and an LED is on Portb.2):
Code: |
#int_timer2 // 2msec
tmr2_isr()
{
static int button_count, blinky;
if (!bit_test(portb, 1)) // Button pressed?
{ // Yes
if (button_count < 25) // 25 * 2msec = .02 sec
{
if (++button_count == 25) // Just reached 25?
button_press = 1;
}
}
if (bit_test(++blinky, 7) && blinker_on) // Wraps at about 2/sec
bit_set(portb, 2);
else
bit_clear(portb, 2);
}
|
So here you get a flag set if the button is newly pressed, and an LED will blink if another flag is set. These flags have to be global in scope, so they're accessible in both the interrupt and in main(). If the program needs anything else done on the basis of elapsed time or at regular intervals, you can always add more tasks in the interrupt, and the main() code can keep doing the basic processing without pausing. |
|
|
Username
Joined: 01 Nov 2011 Posts: 17
|
|
Posted: Sun Nov 27, 2011 1:19 pm |
|
|
Okay. So thats kind of what I assumed. The thing I still don't understand is what conditions have to happen for the timer interrupt to be executed? |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sun Nov 27, 2011 2:04 pm |
|
|
Timing hum?
Well the PIC has a frequency set by an oscillator. This oscillator provides a ticking effect just like a clock. A timer is a circuit that can be set up within the PIC that while ticking doesn't impact anything else. However after a chosen number of ticks this circuit will interrupt the process running in the PIC. The execution is routed to your service routine which must be short and then returned to the running process. A delay_xx also counts ticks but it is always in the main process so when counting the main process is blocked. With the interrupt the main process is only suspended for the duration of the interrupt. A GPS most often squawks when it pleases ( is asynchronous) so you code must always be ready. This is rarely possible without an interrupt (#RDA) and a circular buffer. Any delay_xx statements in your code make the need for the #RDA and a circular buffer almost essential. |
|
|
|