View previous topic :: View next topic |
Author |
Message |
Wouhou Guest
|
Led flickering and functions ... |
Posted: Wed Aug 24, 2005 7:47 am |
|
|
Hello,
i am using a pic 18F458 with ccs 3.206.
What i wanted to do is to switch on and off a led to make it flicker that shows that a device is switched on.
But the device should wait for data and execute a command.
So i tried to do that with an interrupt but it is not working ...
Code: | #define HIGH_START 114
byte seconds, high_count;
#INT_RTCC
clock_isr() {
if(--high_count==0) {
output_high(PIN_B0);
delay_us(5);
output_low(PIN_B0);
high_count=HIGH_START;
}
}
main() {
high_count=HIGH_START;
set_rtcc(0);
setup_counters(RTCC_INTERNAL, RTCC_DIV_64);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while(TRUE)
{
// do something;
}
} |
where should i put this Code: | high_count=HIGH_START; |
to make an overflow ? Everywhere that i have a new while ? Because i have lots of while in my while :p
Any ideas ?
Thanks |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
|
Posted: Wed Aug 24, 2005 8:15 am |
|
|
Five microseconds is MUCH TOO SHORT to be able to see an LED flicker on. Try 100 milliseconds.
It's not a great idea to be hanging out in an interrupt routine for 100 ms, depending on what else you want your program to do. If you have a second timer available, its much better to use one timer, like you're doing, to set the frequency of the LED. That interrupt should turn the bit on, and start a second timer that controls the duration of the LED on time. When that interrupt triggers, turn the LED bit off, and stop the duration timer.
Scott |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
|
Posted: Wed Aug 24, 2005 8:27 am |
|
|
Aah--
I see what you're trying to do now. It doesn't make any sense the way you're looping. Pin B0 is going to go high for 5microseconds, and then low for a few instruction cycles, and then high again.
Also, somewhere in main, make sure you define pin B0 as an output.
Place HIGH_START into your counter
set_timer0(HIGH_START);
So:
Code: | #INT_RTCC
clock_isr() {
output_high(PIN_B0);
delay_ms(50);
output_low(PIN_B0);
set_timer0(HIGH_START); //there are more accurate ways to do this
} |
It's hard to know if the timing is right without knowing your clock frequency. You probably want to blink the LED for 50-100ms every 2 seconds or so.
But consider using one interrupt for frequency, and one for duration, as discussed before. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Aug 24, 2005 8:52 am |
|
|
Code: |
#define HIGH_START 114
byte high_count;
#INT_RTCC
clock_isr() {
high_count--;
if(!high_count)
{
output_toggle(PIN_B0);
high_count=HIGH_START;
}
}
main() {
high_count=HIGH_START;
set_rtcc(0);
setup_counters(RTCC_INTERNAL, RTCC_DIV_64);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while(TRUE)
{
// do something;
}
}
|
Humberto |
|
|
Wouhou Guest
|
|
Posted: Thu Aug 25, 2005 1:45 am |
|
|
Thanks for your responses :
could you tell me how to do this ? Using 2 interrupts please ?
I don't really sure to understand.
Humberto your programm is not working i don't know why ... |
|
|
Wouhou Guest
|
|
Posted: Thu Aug 25, 2005 3:06 am |
|
|
If i try to it this way in the interrupt :
Code: | counter =0;
#INT_RTCC
clock_isr() {
if(system_on)
{
if(counter == 0) {output_high(LED);}
if(counter == 10) {output_low(LED); counter = 0;}
counter++;
}
} |
It is better to not use a delay, so i tried this way but it is not accurate, could you tell me why ? |
|
|
Wouhou Guest
|
|
Posted: Thu Aug 25, 2005 3:07 am |
|
|
Maybe it is better if you could tell me how to use 2 interrupts i think it will be the better way to do it !
HELP ! |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Aug 25, 2005 5:08 am |
|
|
Wouhou wrote: | If i try to it this way in the interrupt :
Code: | counter =0;
#INT_RTCC
clock_isr() {
if(system_on)
{
if(counter == 0) {output_high(LED);}
if(counter == 10) {output_low(LED); counter = 0;}
counter++;
}
} |
It is better to not use a delay, so i tried this way but it is not accurate, could you tell me why ? | What do you mean with 'not accurate'?
It will only work for the first cycle and then fail. When counter reaches 10 you reset counter to 0 but then immediately add 1, so the next times you enter the interrupt the test for 0 will always fail. |
|
|
Wouhou Guest
|
|
Posted: Thu Aug 25, 2005 5:42 am |
|
|
Ok ! Thanks for that !
I fixed it out but the led is switched on and off too long.
I tried this :
Code: |
counter++;
if(counter == 1) {output_high(LED);}
if(counter == 2) {output_low(LED); counter = 0;} |
Do ou know how i could do this but to have something like this for 50-100ms every 2 seconds or so ?
i putted counter as an int. How can i do ?
Many thanks. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Aug 25, 2005 6:51 am |
|
|
Given the clock frequency of your CPU you can calculate the timing for the timer0 interrupt: Code: | interrupts per second = Clock freq. / (4 x prescaler x counter max.) |
with Code: | setup_counters(RTCC_INTERNAL, RTCC_DIV_64); | the timer is setup with a prescaler that divides by 64 and the interrupt fires when the counter overflows (at 256 for an 8 bit counter).
You didn't tell us your clock frequency, but let's assume it is 4MHz, then you get the following calculation: Code: | interrupts per second = 4MHz / (4 x 64 x 256) = 61 times per second |
Change your code then to Code: | #define TWO_SECONDS (2 * 61)
#define MSEC_100 (6)
counter++;
if (counter == TWO_SECONDS) {output_high(LED);}
if (counter == (TWO_SECONDS + MSEC_100) {output_low(LED); counter = 0;} |
|
|
|
Wouhou Guest
|
|
Posted: Thu Aug 25, 2005 8:11 am |
|
|
Ok many thanks ! |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Aug 25, 2005 12:07 pm |
|
|
Wouhou wrote:
Quote: |
Humberto your programm is not working i don't know why ...
|
For your info the code I posted is right and tested.
The code is pretty simple. I used 16F628 and 8Mhz crystal and I get in the scope a
clear and symetrical toggling in PINB0 every 930ms.
Check your hardware, tools and test procedure.
Humberto |
|
|
Bart
Joined: 12 Jul 2005 Posts: 49
|
|
Posted: Thu Aug 25, 2005 2:38 pm |
|
|
Hello Humberto or Wouhou,
Can you explain me how you come to, our how you calculated, the 114 value ? (Can you eventualy use 20 Mhz as clockspeed as example calculation ?)
Thanks.
Code: |
#define HIGH_START 114
|
_________________ I like Skype (www.skype.com), my username is BplotM |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Aug 25, 2005 3:33 pm |
|
|
Quote: |
Can you explain me how you come to, our how you calculated, the 114 value ?
|
It doesn�t have any special meaning, it is a constant value assigned in compilation time
to the preprocessor identifier HIGH_START using the preprocessor directive #define
In the posted code it is used to reload a decremented counter when it reach zero.
In the statement
if(--high_count==0)
high_count is decremented and tested if it is = 0.
If high_count==0 it is loaded with the value 114, wich is replaced
using the identifier HIGH_START to repeat the cycle.
high_count=HIGH_START;
Quote: |
Can you eventualy use 20 Mhz as clockspeed as example calculation ?)
|
Yes of course. (assuming you are talking about ckielstra example calculation)
Read this excelent thread posted by newguy:
http://www.ccsinfo.com/forum/viewtopic.php?t=22467
Humberto |
|
|
|