|
|
View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Mar 22, 2010 11:46 am |
|
|
Somewhere else in the code you posted, you have changed something so that it doesn't work. Instead searching for the problem, I'm just going to post some working code. This code was tested with vs. 4.057 and vs. 4.105.
I set my function generator to give 10 Hz, and I got this output:
Quote: |
9.99
10.00
10.00
10.00
|
I set it to put out approximately 20 Hz, and I got this output on the
terminal window:
Quote: |
20.01
20.00
19.98
19.98
19.99
20.00
19.98
19.98
20.00
|
Then I set it for 150Hz, and I got this output. Even my scope's frequency
counter jumps around a little bit, so I don't think the B&K function
generator is perfectly stable. In other words, I don't think the variation
below is caused by the PIC program. It's the function generator.
But anyway, it's still very close to 150 Hz.
Quote: |
149.86
149.94
149.88
149.96
149.92
149.90
150.01
149.96
149.97
149.91
149.97
150.08
|
Here is the test program:
Code: |
#include <16F628.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use rs232 (baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)
#priority CCP1, TIMER1
#define BytePtr(var, offset) (char *)((char*)&var + offset)
#byte PIR1 = 0x0C
#bit TMR1IF = PIR1.0
int8 gc_timer1_extension = 0;
int8 gc_capture_flag = FALSE;
int32 g32_ccp_delta;
//------------------------------------------------------
#int_timer1
void timer1_isr(void)
{
gc_timer1_extension++;
}
//------------------------------------------------------
#int_ccp1
void ccp1_isr(void)
{
char timer_ext_copy;
int32 current_ccp;
static int32 old_ccp = 0;
gc_capture_flag = TRUE;
current_ccp = (int32)CCP_1;
// Get local copy of the timer ext.
timer_ext_copy = gc_timer1_extension;
if(TMR1IF)
{
if(*BytePtr(current_ccp, 1) < 2) // Was CCP captured after Timer1 wrapped?
timer_ext_copy++; // If so, inc the copy of the timer ext.
// Since we know a timer interrupt is pending, let's just
// handle it here and now. That saves a little load off
// the processor.
gc_timer1_extension++; // Increment the real timer extension
TMR1IF = 0; // Then clear the Timer1 interrupt
}
// Insert the timer extension into the proper place in the 32-bit
// CCP value.
// ie., Insert it into location "EE" as follows: 0x00EEnnnn
// (nnnn = the CCP).
*BytePtr(current_ccp, 2) = timer_ext_copy;
g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
// Save the current ccp value for next time.
old_ccp = current_ccp;
}
//=======================
void main()
{
float frequency;
int32 current_ccp_delta;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
// Enable interrupts.
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
if(gc_capture_flag == TRUE)
{
disable_interrupts(GLOBAL);
current_ccp_delta = g32_ccp_delta;;
enable_interrupts(GLOBAL);
frequency = (5000000L / (float)current_ccp_delta);
printf("%4.2f\n\r", frequency);
gc_capture_flag = FALSE;
}
else
{
printf("No signal\n\r");
}
delay_ms(500);
}
}
|
|
|
|
Salenko
Joined: 08 Sep 2008 Posts: 84
|
|
Posted: Mon Mar 22, 2010 2:10 pm |
|
|
Hi PCM,
finally I got a working code !
the error in my code was the use of:
Code: | #byte CCPR1_REG = 0x15 // Adress of CCPR1L
current_ccp = (int32)CCPR1_REG; // Read the current CCP
|
instead of :
Code: | current_ccp = (int32)CCP_1; |
thank you for making a hardware test. |
|
|
vsmguy
Joined: 13 Jan 2007 Posts: 91
|
|
Posted: Thu Jul 08, 2010 4:51 am |
|
|
PCM programmer wrote: |
Code: |
// Get local copy of the timer ext.
timer_ext_copy = gc_timer1_extension;
if(TMR1IF)
{
if(*BytePtr(current_ccp, 1) < 2) // Was CCP captured after Timer1 wrapped?
timer_ext_copy++; // If so, inc the copy of the timer ext.
// Since we know a timer interrupt is pending, let's just
// handle it here and now. That saves a little load off
// the processor.
gc_timer1_extension++; // Increment the real timer extension
TMR1IF = 0; // Then clear the Timer1 interrupt
}
// Insert the timer extension into the proper place in the 32-bit
// CCP value.
// ie., Insert it into location "EE" as follows: 0x00EEnnnn
// (nnnn = the CCP).
*BytePtr(current_ccp, 2) = timer_ext_copy;
|
|
I have a question:
I am assuming that CCS clears an interrupt flag ( IF ) *only* after the corresponding ISR has executed.
Hence, in your code ( I am putting only the comment )
Code: |
// Check if a Timer1 interrupt is pending. If so, check if
// the CCP capture occurred before or after the Timer rolled
// over. We can tell if it occurred after it rolled over, if
// the CCP's MSB is zero. ie., if the CCP is somewhere between
// 0x0000 and 0x00FF.
|
Is not the check for overflow redundant as the Timer1 IF set inside the CPP1 ISR *implies* that the overflow was not accounted for?
Can there be cases when the ISR for an interrupt has been serviced but its IF is still set? ( only under these circumstances, if any, will your extra check above make sense )
I am sure my assumption is wrong as a lot of people have used your code, so this is really an effort to clear up my understanding :-) |
|
|
alextee89
Joined: 01 Apr 2011 Posts: 2
|
|
Posted: Sat Apr 02, 2011 2:57 am |
|
|
Here is the test program:
Code:
#include <16F628.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use rs232 (baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)
#priority CCP1, TIMER1
#define BytePtr(var, offset) (char *)((char*)&var + offset)
#byte PIR1 = 0x0C
#bit TMR1IF = PIR1.0
int8 gc_timer1_extension = 0;
int8 gc_capture_flag = FALSE;
int32 g32_ccp_delta;
//------------------------------------------------------
#int_timer1
void timer1_isr(void)
{
gc_timer1_extension++;
}
//------------------------------------------------------
#int_ccp1
void ccp1_isr(void)
{
char timer_ext_copy;
int32 current_ccp;
static int32 old_ccp = 0;
gc_capture_flag = TRUE;
current_ccp = (int32)CCP_1;
// Get local copy of the timer ext.
timer_ext_copy = gc_timer1_extension;
if(TMR1IF)
{
if(*BytePtr(current_ccp, 1) < 2) // Was CCP captured after Timer1 wrapped?
timer_ext_copy++; // If so, inc the copy of the timer ext.
// Since we know a timer interrupt is pending, let's just
// handle it here and now. That saves a little load off
// the processor.
gc_timer1_extension++; // Increment the real timer extension
TMR1IF = 0; // Then clear the Timer1 interrupt
}
// Insert the timer extension into the proper place in the 32-bit
// CCP value.
// ie., Insert it into location "EE" as follows: 0x00EEnnnn
// (nnnn = the CCP).
*BytePtr(current_ccp, 2) = timer_ext_copy;
g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
// Save the current ccp value for next time.
old_ccp = current_ccp;
}
//=======================
void main()
{
float frequency;
int32 current_ccp_delta;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
// Enable interrupts.
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
if(gc_capture_flag == TRUE)
{
disable_interrupts(GLOBAL);
current_ccp_delta = g32_ccp_delta;;
enable_interrupts(GLOBAL);
frequency = (5000000L / (float)current_ccp_delta);
printf("%4.2f\n\r", frequency);
gc_capture_flag = FALSE;
}
else
{
printf("No signal\n\r");
}
delay_ms(500);
}
}
if i am using 16f877a, izit just change to #include <16F877a.h> ? |
|
|
SergioGM17
Joined: 25 Apr 2019 Posts: 2
|
|
Posted: Thu Apr 25, 2019 9:01 pm |
|
|
Hi!! First of all, sorry to bump this old thread.
Im using this code (ver 5.0xx), almost the same posted above, just using a LCD instead of a rs232, internal clock (4Mhz), to measure low freqs (0-3hz):
Code: | #include <16F628A.h>
#FUSES NOWDT,NOBROWNOUT,NOLVP,PUT,NOPROTECT
#use delay(internal=4MHz)
//#priority CCP1, TIMER1
#define LCD_ENABLE_PIN PIN_B5
#define LCD_RS_PIN PIN_A4
#define LCD_RW_PIN PIN_B7
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B2
#define LCD_DATA6 PIN_B1
#define LCD_DATA7 PIN_B0
#include <LCD.C>
#define BytePtr(var, offset) (char*)((char*)&var + offset)
//#byte CCPR1_REG = 0x15
#byte PIR1 = 0x0c
#bit TMR1IF = PIR1.0
int8 gc_timer1_extension = 0;
BOOLEAN gc_capture_flag = FALSE;
int32 g32_ccp_delta;
//------------------------------------------------------
#int_timer1
void timer1_isr(void)
{
gc_timer1_extension++;
}
//------------------------------------------------------
#int_ccp1
void ccp1_isr(void)
{
char timer_ext_copy;
int32 current_ccp;
static int32 old_ccp = 0;
gc_capture_flag = TRUE;
current_ccp = (int32)CCP_1;
// Get local copy of the timer ext.
timer_ext_copy = gc_timer1_extension;
if(TMR1IF)
{
if(*BytePtr(current_ccp, 1) < 2) // Was CCP captured after Timer1 wrapped?
timer_ext_copy++; // If so, inc the copy of the timer ext.
// Since we know a timer interrupt is pending, let's just
// handle it here and now. That saves a little load off
// the processor.
gc_timer1_extension++; // Increment the real timer extension
TMR1IF = 0; // Then clear the Timer1 interrupt
}
// Insert the timer extension into the proper place in the 32-bit
// CCP value.
// ie., Insert it into location "EE" as follows: 0x00EEnnnn
// (nnnn = the CCP).
*BytePtr(current_ccp, 2) = timer_ext_copy;
g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
// Save the current ccp value for next time.
old_ccp = current_ccp;
}
//=======================
void main()
{
float frequency;
int32 current_ccp_delta;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
lcd_init();
// Enable interrupts.
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
if(gc_capture_flag == TRUE)
{
disable_interrupts(GLOBAL);
current_ccp_delta = g32_ccp_delta;;
enable_interrupts(GLOBAL);
frequency = ((1000000L + (current_ccp_delta >> 1)) / (float)current_ccp_delta);
printf(lcd_putc,"%4.2f Hz\n\r", frequency);
// printf("%lu Hz, delta = %lx \n\r", frequency, current_ccp_delta);
gc_capture_flag = FALSE;
}
/* else
{
printf(lcd_putc,"No signal\n\r");
}
*/
delay_ms(500);
}
} |
I got it working, simulating on Proteus showed the variable freqs. But then I changed something that don't know what it was (apart from changing from int to float), making the simulation show a static value (10, and in float 10.79), and not working as expected. And if I activate the
Code: | /* else
{
printf(lcd_putc,"No signal\n\r");
}
*/
|
It jumps to that, even with a signal
Any guess of what it could be?
Thx in advance |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 26, 2019 12:43 am |
|
|
To find the differences between your code and the forum's code:
1. Download ExamDiff from: https://www.prestosoft.com/edp_examdiff.asp
I have been using vs. 1.8 for years. I notice they are now up to vs. 1.9.
2. Make a new folder on your Windows desktop.
3. Copy the forum's code into a text editor and save it as "working.c"
in that folder.
4. Save your code into the same folder as problem.c or whatever you call it.
5. Run Examdiff and select those two files in the new folder to compare.
6. Examdiff will load both and show differences highlighted in yellow.
You can go to the View menu and have it show differences only, if you want.
Now start to undo the changes you made in your program, as you test
which one is causing the problem. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Fri Apr 26, 2019 5:08 am |
|
|
Couple of comments, possible shortcuts to save time and pots of coffee..
Sounds like you always edit the same program, over and over again.
What I do with every PIC project is 1st, create a '1Hz LED' program, get it working then save it. I then copy the source, naming it 'pictype_program_v2.c', where pictype is the type of PIC, program is then name of the project. V2 means version 2.
I then edit the V2 version, compile, burn, test. I then copy v2 --> v3.
I then edit the V3 version,compile,burn, test. I then copy v2 --> v4.
Yes, it mkes for a LOT of files on the harddrive BUT I can go back to any previous version and not lose a day wondering which of the 3 or 4 or ?? changes I made didn't work. I have 1,000s of PIC files on this HD, but tons of room, have yet to 'clean up'.
I do something similar with 'fuses'. Since today's PIC have more fuses than instructions, I create a #INCLUDE file that has EVERY fuse in it, ONE per line, WITH a comment. Once I have the 1Hz LED program running, I save the 'fuses' file as 'pictype_1HZ_fuses.c'. This does 2 things. One, I have a set of known WORKING fuses for basic PIC operation. I copy/edit/save this for project specific requirements. Two, it 'cleans up' the main project. Just one #INCLUDE line not 20-30 lines of fuses information. 3rd, It saves me a LOT of typing AND retyping ! Say you decide to not use the WDT but you forget to type in 'no'WDT. You could spend hours not seeing why 'it worked before but not now'........
Jay |
|
|
SergioGM17
Joined: 25 Apr 2019 Posts: 2
|
|
Posted: Thu May 02, 2019 8:52 am |
|
|
Hi, thank you for your responses.
Started from zero, with a signal generator + pic + virtual terminal (rs232) and the code worked perfectly.
Now, using with my own input signal, works with the virtual terminal, but when I use the LCD (16x1, LM020L on proteus) on A or B ports, or mixed, it seems like the CCP stops functioning, showing the "no signal" msg.
Adding to that, the #include lcd.c is below the #define pins, and the lcd_init() is on main().
In the meantime I will test with another lcd module.
EDIT: Apparently was a problem with the printf's and something on proteus, seems like it is solved.
TY! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Fri May 03, 2019 5:36 am |
|
|
You do KNOW that Proteus is NOT 100% functional ? It's full of bugs, errors and faulty DRCs !! |
|
|
|
|
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
|