|
|
View previous topic :: View next topic |
Author |
Message |
TT Guest
|
reading the pin |
Posted: Sun Oct 11, 2009 2:38 am |
|
|
Hey all, I'm really sorry but I'm getting stuck on something really simple and I can't figure out where I'm going wrong.
I'm using a pic16f690 and one of its pins (PIN_C1) is programmed to go HIGH every few seconds. Just quickly.
I have verified this with a multimeter and the osc and it does go high. Meanwhile, I've programmed the PIC to read this input and light up an led. But the led doesn't light up at all. I've also programmed the PIC to send info up to the computer if it detects pin C1 at high at any stage. Even this doesn't happen.
Is there something I am overlooking?
My simple code is below
Code: |
#include <16F690.h>
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT
#use delay(clock = 4000000)
#use rs232(baud=19200, xmit=PIN_B7, rcv=PIN_B5)
void main()
{
set_tris_c(0b00100111);
setup_adc_ports(NO_ANALOGS); //Port A/C all digital outputs
for(;;){
contact_slave3();
if(input(PIN_C1) == 1){
printf("\r\nValid RF Message from Slave 3 received\r\n");
}
delay_ms(1000);
}
}
|
contact_slave3 is a simple function that uses rf to get pin_c1 to high. That bit works. Is there something about C1 I should know ?
Thanks all. |
|
|
TT Guest
|
|
Posted: Sun Oct 11, 2009 2:41 am |
|
|
sorry, in the above code, theres meant to be a part on lighting the relevant LED. i removed it while debugging. so just imagine that bits in there and working. |
|
|
Ttelmah Guest
|
|
Posted: Sun Oct 11, 2009 3:16 am |
|
|
The 'odds' are you are just missing it....
You send this 'contact_slave3' command (which you don't show), and presumably the pin is meant to go high at some interval after this. You then test the pin just once, immediately after returning from this, and if it is high, print your message, but if it is not high, _at the exact instant you read the pin_, you pause for a second, and go round again.
So, unless the pin is actually high at the exact moment you test it, you will miss it.
Is the pin just going high at an interval (as you imply), or does it go high in response to the 'contact slave' command?. If the latter, how long after the command is sent, does the event happen?.
You probably need something like:
Code: |
int16 ctr; //at the start of main
for(;;){
contact_slave3();
//Now wait for about 1/10th second to see if there is a response:
for (ctr=0;ctr<8000;ctr++) {
if(input(PIN_C1)) {
ctr=0;
break;
}
}
if (ctr==0)
printf("\r\nValid RF Message from Slave 3 received\r\n");
delay_ms(1000);
}
|
The 'ctr' loop, will probably take about 10 to 15uSec to execute at 4MHz, so looping 8000 times, will be somewhere in the order of 1/10th second. If a 'high' is seen, it'll exit with ctr cleared, otherwise ctr will be 8000 at the exit. So if ctr is zero, then a 'high' was seen, and your message is printed.
The odds are that the slave takes some time to respond to the command, and the line doesn't go high in time for your test.
Best Wishes |
|
|
hobby_85
Joined: 17 Aug 2009 Posts: 50
|
hey |
Posted: Sun Oct 11, 2009 5:21 am |
|
|
hey tlmah,
thanks so much. i know the mistake i was makin. it works now
thanks again |
|
|
hobby_855 Guest
|
timer |
Posted: Sun Oct 11, 2009 6:16 am |
|
|
ttelmah,
if I were to start the timer when the pin went high, and stopped it when another pin went high, would this be ok? the other input is on C5, so im trying to use the CCP capabilities of the PIC.
this is what Ive got so far:
Code: |
#int_ccp1
setup_ccp1(CCP_CAPTURE_RE); //configure pin to capture rise on pin C5
contact_slave3();
for (ctr=0;ctr<16000;ctr++) { //Wait till timeout
if(input(PIN_C1)) {
ctr=0;
break;
}
}
if (ctr==0){
setup_timer_1(T1_INTERNAL); //start timer 1
received_US = CCP_1 ; //stores the timer value into received_US when rising edge is detected
// *at this point, I need to take the difference in timer values, but am getting confused on how to do so*//
}else{
printf("\r\nSlave 3 is uncontactable\r\n");
}
|
could you lead me in the right direction with regard to this. Im getting confused on how to start the timer when pin c1 is high, and stop when pin c5 (ccp pin) is high.
thanks again. |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Sun Oct 11, 2009 7:03 am |
|
|
Why do you want to start/stop the timer? Do you need a measurmet for how long some event took.
Then you can do that in a few ways. One is to wait until the first signal appears and then set corresponding timer to 0 and then wait for another signal and then you just read the value of the timer (no need to start/stop).
Another way would be use of CCP module, but not in a way you wrote it.
The best thing would be that you specify what you want to achieve and we can give you advice/code ... |
|
|
Guest
|
|
Posted: Sun Oct 11, 2009 7:55 am |
|
|
bungee- wrote: | Why do you want to start/stop the timer? Do you need a measurmet for how long some event took.
Then you can do that in a few ways. One is to wait until the first signal appears and then set corresponding timer to 0 and then wait for another signal and then you just read the value of the timer (no need to start/stop).
Another way would be use of CCP module, but not in a way you wrote it.
The best thing would be that you specify what you want to achieve and we can give you advice/code ... |
hey bungee, thanks for the tip. yes, i am trying to find the time between the two pins (c1 and c5) getting high.
im using a pic16f690 so only c5 has a ccp module, and im getting confused on how to use the timer and ccp together. (just so i get a more accurate reading)
how to i go about doing this?
thanks heaps |
|
|
Guest
|
|
Posted: Sun Oct 11, 2009 7:56 am |
|
|
In the meanwhile, I'll trying writing code for the other way....setting the timer to 0 and reading it again.
Thanks heaps |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Sun Oct 11, 2009 2:42 pm |
|
|
If you are not tied to ports, you could use port A/B so you can use "on change" interrupt. That would improve accuracy.
Another option would be use RA2/INT (external interrupt in CCS) for first signal. In ISR for that interrupt you just set timer1 to zero and arm the CCP interrupt. When CCP interrupt would happen you read the value in CCP register save it to your variable and raise the event flag, so the main part of program would know that something happened etc.
Here is the code, that I think can be usefull to you. First signal is inputed in RA2 and the second on RC5.
Code: | #include <16F690.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#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 PUT //Power Up Timer
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#use delay(clock=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B7,rcv=PIN_B5,bits=8,errors)
int tripped=0;
int16 value=0;
#int_EXT
void EXT_isr(void)
{
set_timer1(0);
tripped=0;
value=0;
enable_interrupts(INT_CCP1);
disable_interrupts(INT_EXT);
}
#int_CCP1
void CCP1_isr(void)
{
value=CCP_1;
disable_interrupts(INT_CCP1);
enable_interrupts(INT_EXT);
tripped=1;
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_CAPTURE_RE);
setup_comparator(NC_NC_NC_NC);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
setup_oscillator(OSC_8MHZ);
while (1)
{
if (tripped)
{
printf("Value is: %Lu",value);
tripped=0;
}
}
} |
|
|
|
HOBBY_885 Guest
|
|
Posted: Sun Oct 11, 2009 9:55 pm |
|
|
hey bungee, thanks for your help.
Unfortunately, my ports are tied, so I'm stuck with C1 and C5. But I do understand what your trying to do.
I guess the only other option is to set timer to 0 when the first high signal is received and check its contents when C5 goes high?
Is there no way I can use the CCP on C5 in conjunction with the timer?
Thanks for the help so far, really appreciate it. |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Mon Oct 12, 2009 5:19 am |
|
|
You can use the similar code I wrote. You will just change first ISR so that you'll run it inside main program loop. And the other part could stay almost the same (throw out the EXT interrupt part ;) ) |
|
|
hobby_85
Joined: 17 Aug 2009 Posts: 50
|
|
Posted: Mon Oct 12, 2009 8:36 am |
|
|
bungee- wrote: |
You can use the similar code I wrote. You will just change first ISR so
that you'll run it inside main program loop. And the other part could stay
almost the same (throw out the EXT interrupt part ;) )
|
Hey bungee, I have attached what I think is the right way to do it.\
Can you run your eyes over to see if I managed to get it right?
Here's the code. So basically I want to find out the time difference
between PINC1 going HIGH and PINC5 going high. I'm using a simple for
loop to find C1 going high and the CCP for PINC5.
Code: |
#include <16F690.h>
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT
#use delay(clock = 4000000)
#use rs232(baud=19200, xmit=PIN_B7, rcv=PIN_B5)
int16 ctr;
int16 ctr1;
int tripped=0;
int16 value=0;
#int_CCP1
void CCP1_isr(void)
{
value=CCP_1;
disable_interrupts(INT_CCP1);
enable_interrupts(INT_EXT);
tripped=1;
}
void main()
{
set_tris_a(0b00111111); //sets IO pins
set_tris_b(0b01000000); //sets IO pins
set_tris_c(0b00100111); //sets IO pins
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_ccp1(CCP_CAPTURE_RE);
for(;;){
output_high(PIN_B4); //disable RF output signal
output_low(PIN_C4); //turn off at start LED
contact_slave3(); //After this, PINC1 should go high, followed closely by PINC5 after about 500ms
for (ctr=0;ctr<32000;ctr++) { //Wait for PINC1 to go high until timeout
if(input(PIN_C1)) {
ctr=0; //PINC1 went high, set ctr=0, break
break;
}
}
if (ctr==0){ //at this point, C1 went high, start timer and wait for C5 to go high
printf("\r\nRF Received, Starting timer\r\n");
set_timer1(0); //set timer value to 0
tripped = 0; //set tripped to 0
enable_interrupts(INT_CCP1); //wait for rising edge of pinC5 until timeout
for (ctr1=0;ctr1<32000;ctr1++) { //Wait for PINC5 to go high until timeout
if(tripped) {
printf("Value is: %Lu",value);
tripped=0;
}else{
printf("PINC5 did not go HIGH, Error");
}
}
}else{ //PINC1 did not go high, error
printf("\r\nPINC1 did not go HIGH in the first place\r\n");
}
}
delay_ms(2000);
}
|
When I connect it up, 'Slave 3 contacted' and 'RF Received, Starting timer', but nothing about pin C5.
I must be doing something wrong with the timing. Either I'm polling the
pin too fast or something. Is there something wrong with the code?
I haven't used the compare function of CCP before so I'm still new.
Thanks |
|
|
hobbby_85 Guest
|
|
Posted: Tue Oct 13, 2009 6:09 pm |
|
|
anyone? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 13, 2009 6:24 pm |
|
|
1. Your program above never enables global interrupts, so it will never
get to the #int_ccp routine.
2. You are enabling INT_EXT interrupts inside the #int_ccp1 isr, but you
don't have an #int_ext routine. I don't see anywhere in your code
where you poll the INT_EXT interrupt flag, so presumably you do want
to have an #int_ext isr. If you don't need one, then delete that line
inside the #int_ccp1 isr.
3. You're setting the TRIS at the start of main(), but you don't have
#fast_io() mode specified, so the TRIS will be overridden by the
compiler (if it's different than yours) as required, when it does the
output_low(), output_high(), etc., functions. My advice is to delete
the set_tris_x() functions and let the compiler set the TRIS, unless
you have some compelling reason to set it yourself. |
|
|
HOBBY_855 Guest
|
|
Posted: Tue Oct 13, 2009 7:42 pm |
|
|
Hey PCM, thanks alot for the help. I've fixed the code and posted it below. Ill be checking it tonight, but could you have a look if I've made any mistakes. Sorry about this, I'm still pretty new to CCS and ever used the CCP function.
Here's the code. So basically I want to find out the time difference
between PINC1 going HIGH and PINC5 going high. I'm using a simple for
loop to find C1 going high and the CCP for PINC5.
Code: |
#include <16F690.h>
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT
#use delay(clock = 4000000)
#use rs232(baud=19200, xmit=PIN_B7, rcv=PIN_B5)
int16 ctr;
int16 ctr1;
int tripped=0;
int16 value=0;
#int_CCP1
void CCP1_isr(void)
{
value=CCP_1;
disable_interrupts(INT_CCP1);
tripped=1;
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
enable_interrupts(GLOBAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_ccp1(CCP_CAPTURE_RE);
for(;;){
contact_slave3(); //After this, PINC1 should go high, followed closely by PINC5 after about 500ms
for (ctr=0;ctr<32000;ctr++) { //Wait for PINC1 to go high until timeout
if(input(PIN_C1)) {
ctr=0; //PINC1 went high, set ctr=0, break
break;
}
}
if (ctr==0){ //at this point, C1 went high, start timer and wait for C5 to go high
printf("\r\PIN C5 has gone high\r\n");
set_timer1(0); //set timer value to 0
tripped = 0; //set tripped to 0
enable_interrupts(INT_CCP1); //wait for rising edge of pinC5 until timeout
for (ctr1=0;ctr1<32000;ctr1++) { //Wait for PINC5 to go high until timeout
if(tripped) {
printf("Value is: %Lu",value);
tripped=0;
}else{
printf("PINC5 did not go HIGH, Error");
}
}
}else{ //PINC1 did not go high, error
printf("\r\nPINC1 did not go HIGH in the first place\r\n");
}
}
delay_ms(2000);
}
|
What do you think? |
|
|
|
|
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
|