|
|
View previous topic :: View next topic |
Author |
Message |
viki2000
Joined: 08 May 2013 Posts: 233
|
|
Posted: Thu Jul 16, 2015 1:12 am |
|
|
OK, then here we are without interrupts:
Code: | #include <10F322.h>
#use delay(internal=16000000)
#use FIXED_IO( A_outputs=PIN_A2,PIN_A0 )
#define LATA 0x07
#define NCO1ACCL 0x27
#define NCO1ACCH 0x28
#define NCO1ACCU 0x29
#define NCO1INCH 0x2B
#define NCO1INCL 0x2A
#define PIR1 0x0C
#BIT NCO1IF = PIR1.4
void main()
{
SETUP_ADC(ADC_OFF);
SETUP_NCO(NCO_ENABLED|NCO_OUTPUT|NCO_ACTIVE_LOW|NCO_PULSE_FREQ_MODE|NCO_PULSE_WIDTH_1|NCO_CLOCK_HFINOSC, 736);
while(TRUE){
if (NCO1IF){
//OUTPUT_TOGGLE(PIN_A0);
#asm
MOVLW 0x01
XORWF LATA, F
#endasm
if (input(PIN_A0)){
// set_nco_inc_value(736);
#asm
MOVLW 16
MOVWF NCO1INCH
MOVLW 105
MOVWF NCO1INCL
#endasm
}
else{
// set_nco_inc_value(471);
#asm
MOVLW 1
MOVWF NCO1INCH
MOVLW 6
MOVWF NCO1INCL
#endasm
}
// set_nco_accumulator(0);
#asm
CLRF NCO1ACCL
CLRF NCO1ACCH
CLRF NCO1ACCU
#endasm
//clear_interrupt(INT_NCO1);
#asm
BCF PIR1, 0x4
#endasm
}
}
} |
The delay introduced by testing the NCO1IF and loading new numbers in NCO increment registers is around 4.3-4.4us measured on scope.
With the code above I expect 20us on and 255us off and I get 19.6-20.0us on and 254.0-254.4us off.
The jitter is 0.4us coming directly from internal RC oscillator.
But important is that the code is reduced to 6% RAM and 9% ROM, finally at the size comparable with XC8.
Then I tried to get rid of the ASM code and I found that only the loading of NCO increment registers is working right “set_nco_inc_value()”, so I replaced only that with ASM code and then the program worked fine. The delay introduced is around 5.1us. The code is 6% RAM and 10% ROM.
The precision/jitter is the same 0.4us.
The code below is expected to produce 20us on and 255us off. I measured 19.5-19.9us and 254.9-255.3us.
Code: |
#include <10F322.h>
#use delay(internal=16000000)
#use FIXED_IO( A_outputs=PIN_A2,PIN_A0 )
#define LATA 0x07
#define NCO1ACCL 0x27
#define NCO1ACCH 0x28
#define NCO1ACCU 0x29
#define NCO1INCH 0x2B
#define NCO1INCL 0x2A
#define PIR1 0x0C
#BIT NCO1IF = PIR1.4
void main()
{
SETUP_ADC(ADC_OFF);
SETUP_NCO(NCO_ENABLED|NCO_OUTPUT|NCO_ACTIVE_LOW|NCO_PULSE_FREQ_MODE|NCO_PULSE_WIDTH_1|NCO_CLOCK_HFINOSC, 3277);
while(TRUE){
if (NCO1IF){
OUTPUT_TOGGLE(PIN_A0);
if (input(PIN_A0)){
#asm
MOVLW 17
MOVWF NCO1INCH
MOVLW 46
MOVWF NCO1INCL
#endasm
}
else{
#asm
MOVLW 1
MOVWF NCO1INCH
MOVLW 6
MOVWF NCO1INCL
#endasm
}
set_nco_accumulator(0);
NCO1IF=0;
}
}
} |
|
|
|
viki2000
Joined: 08 May 2013 Posts: 233
|
|
Posted: Thu Jul 16, 2015 6:09 am |
|
|
And next step was analyzing the long width for “on” and “off” with better precision.
For example when I try 10ms then the jitter error + the error delay generated by code ads itself. But the main error noticed comes from increment. We have a fixed space of 1048575 to fill with a fixed increment. At high delays, the increment value multiplied by needed times does not match exactly the accumulator of the NCO.
Therefore, instead of working with NCO overflow flag, no matter if is NCO interrupt or polling NCO overflow flag in a loop, I found better next solution:
- Increment only with 1 pulse the NCO accumulator.
- Check the value of the NCO accumulator in a loop.
The precision obtained is 20us jitter at 10ms width “on” or “off”.
Here is the XC8 working code:
Code: | #include <xc.h>
#define _XTAL_FREQ 16000000
__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF & WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);
void main(){
OSCCON=0b01110000;
TRISA=0b00001010;
LATA=0b00000000;
ANSELA=0b00000000;
ADCON=0b00100000;
OPTION_REG=0b00000000;
WPUA=0b00000000;
INTCON=0b00000000;
PIE1=0b00000000;
PIR1=0b00000000;
NCO1INCH = 0;
NCO1INCL = 1;
NCO1CLK = 0b0000010;
NCO1CON = 0b11100001;
while(1){
if (LATA0==1 & NCO1ACC>=160000){
LATA0=0;
NCO1ACC=0;
}
if (LATA0==0 & NCO1ACC>=160000){
LATA0=1;
NCO1ACC=0;
}
}
} |
The CCS code I could not make it run. First of all I noticed in “10F322.h” file the function “_bif int16 get_nco_accumulator(void);”, but the NCO accumulator is 20 bits, so it suppose to be int32 function. I think is the same error as for “_bif void set_nco_accumulator(int16 value);” which I tried to use to reset the NCO accumulator.
The code does not work with the function “get_nco_accumulator()”
Here is the code that I tried, but still not functional:
Code: | #include <10F322.h>
#use delay(internal=16000000)
#use FIXED_IO( A_outputs=PIN_A2,PIN_A0 )
#define NCO1ACCL 0x27
#define NCO1ACCH 0x28
#define NCO1ACCU 0x29
void main()
{
SETUP_ADC(ADC_OFF);
SETUP_NCO(NCO_ENABLED|NCO_OUTPUT|NCO_ACTIVE_LOW|NCO_PULSE_FREQ_MODE|NCO_PULSE_WIDTH_1|NCO_CLOCK_HFINOSC, 1);
while(TRUE){
if (input(PIN_A0)){
if ((NCO1ACCH>=15)&(NCO1ACCL>=160)){
output_low(PIN_A0);
#asm
CLRF NCO1ACCL
CLRF NCO1ACCH
CLRF NCO1ACCU
#endasm
}
}
if (!input(PIN_A0)){
if ((NCO1ACCH>=15)&(NCO1ACCL>=160)){
output_high(PIN_A0);
#asm
CLRF NCO1ACCL
CLRF NCO1ACCH
CLRF NCO1ACCU
#endasm
}
}
}
} |
|
|
|
viki2000
Joined: 08 May 2013 Posts: 233
|
|
Posted: Thu Jul 16, 2015 6:34 am |
|
|
Sometimes, when I test I use the real chip, and other times simulators or debuggers.
As simulators I tried mostly MPLABX and Proteus.
PIC10 Simulator does not work with PIC10F322:
http://www.oshonsoft.com/pic10.html
The same with Real PIC Simulator:
http://digitalelectrosoft.com/pic-simulator
For the present tests I tried besides MPLABX, the Proteus 8.2 SP2 which has a small “bug”, or better say a missed update.
PIC10F322 has updated the datasheet regarding the NCOxCLK: NCOx INPUT CLOCK CONTROL REGISTER.
The new devices and the new datasheet 2011-2014, page 125 bottom, have:
https://drive.google.com/file/d/0BwXmKaSw75eKU2hQRGdRTUFBemc/view
bit 1-0 NxCKS<1:0>: NCOx Clock Source Select bits
11 = LC1OUT
10 = HFINTOSC (16 MHz)
01 = FOSC
00 = NCO1CLK pin
The old datasheet 2011, page 135 bottom, indicates a different order:
https://drive.google.com/file/d/0BwXmKaSw75eKaVNySl9FVHdKWVU/view
NxCKS<1:0>: NCOx Clock Source Select bits
11 = NCO1CLK
10 = LC1OUT
01 = FOSC
00 = HFINTOSC (16 MHz)
Proteus 8.2 SP2 works with the info from old datasheet 2011.
Any suggestions how to debug the not functional last CCS code above? |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Jul 16, 2015 8:08 am |
|
|
it looks to me like you did solve it with your post of
Thu Jul 16, 2015 1:12 am
Any info produced by Proteus - is of no help really.
But i would not be surprised to find that the CCS code for the NCO on
your 10F... part is sketchy. This is not so much CCS fault as the
fact that in the 20us/250us mode , jamming the control register pair as you do is not performed in a vacuum.
In the most successful version you coded here is what is happening:
The accumulator is already "counting up" for every i-cycle that occurs in your code stream. Your test for which value to load into the double buffer compare register presently checks for the LONGER time cycle first.
I think You should reverse the order and test for the ELSE case first .
When you zero the accumulator at the end of the test/load code you are "off the timing mark" by the time it has taken to do the tests.
Slightly less jitter will occur if you test for !input(pin) case FIRST ..
But all in all - a bigger problem is still there.
the NCO was designed i think to generate steady frequencies without the jamming you do on every cycle of the counter .
I think you might get better performance yet if you
clear the flag on every detection BUT if the recorded state of the INPUT control pin has not changed - then DO NOT re-jam the counter on every pass.
if the control pin has not changed - just clear the flag and exit.
Only set the alternative register value if the control pin has changed state .
That ought to further cut down on jitter.
Unless i am missing something about your schematic ( which you never posted) i can't suggest anything else. |
|
|
viki2000
Joined: 08 May 2013 Posts: 233
|
|
Posted: Fri Jul 17, 2015 4:58 am |
|
|
Thank you for the suggestions.
I do not think is a hardware jamming of the NCO as long as the XC8 code with 1 increment and the same poling of the accumulator works.
I find rather a problem of CCS when the code is compiled in assembly and when NCO functions are wrong declared in “10F322.h” as 16bits instead of 24bits, knowing that NCO accumulator is 20bits.
The INPUT control pin is in fact the same as OUTPUT control pin. I set it on or off.
I have no schematic. I use only a breadboard with PIC10F322, stabilized 5VDC and one DSO 350MHz.
To program I use ICD-U64 programmer inside the CCS IDE and PicKit 3 programmer with MPLABX.
It is just a test, not a real application.
I tested one more NCO function in XC8, which again is not working in CCS.
It is a microseconds delay function using NCO working in the range 20us-250us with a precision of +/-1us + oscillator jitter.
I increment the NCO slowly and I am looking at the NCO accumulator. It is more precisely than polling NCO overflow flag or using NCO interrupt, because NCO increment does not match always the NCO accumulator exactly.
I tried NCO1INCL also with 1, but the delay function cannot coop with such speeds and there is no signal generated. The NCO1INCL with 2 works, but is still too fast to get a good precision for the function in the range 20us-250us.
Code: | #include <xc.h>
#define _XTAL_FREQ 16000000
__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF & WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);
void NCO_delay(unsigned short long dly);
void main(){
OSCCON=0b01110000;
TRISA=0b00001010;
LATA=0b00000000;
ANSELA=0b00000000;
ADCON=0b00100000;
OPTION_REG=0b00000000;
WPUA=0b00000000;
INTCON=0b00000000;
PIE1=0b00000000;
PIR1=0b00000000;
NCO1INCH = 0;
NCO1INCL = 3;
NCO1CLK = 0b00000010;
NCO1CON = 0b10000001;
while(1){
LATA0=0;
NCO_delay(11760);
LATA0=1;
NCO_delay(720);
}
}
//The number passed to the NCO_delay() function
//is calculated as (wanted delay in us-5)*48
// The 48 comes from 16MHz*NCO1INCL
//The "-5" is a compensation of the NCO_delay() function execution
void NCO_delay(unsigned short long dly){
NCO1ACC=0;
while(NCO1ACC<dly);
} |
My intention was to test NCO and use it in 3 ways, based on the fact that its accumulator is 20 bits, is linear, has input clock 16MHz (62.5ns), so I said is a better precision:
- As replacement for Timer0 or Timer2 interrupt.
- As a precise signal generator for a limited number of signal periods.
- As a precise microseconds delay function.
I can do that now, but most of the tests are successful with XC8. For the time being I will not go further with CCS on this matter, but I will inform the CCS Technical support about NCO PIC10F322 found problems. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 17, 2015 8:05 am |
|
|
Quote: | I tested one more NCO function in XC8, which again is not working in CCS. |
Post your CCS compiler version. It's given at the top of the .LST file.
It's a 4-digit number like this: http://www.ccsinfo.com/devices.php?page=versioninfo |
|
|
viki2000
Joined: 08 May 2013 Posts: 233
|
|
|
viki2000
Joined: 08 May 2013 Posts: 233
|
|
Posted: Fri Jul 17, 2015 1:37 pm |
|
|
Here is the official answer just received from technical support:
Quote: | The function set_nco_accumulator() will accept a 32 bit variable and the get_nco_accumulator() function will return a 32 bit variable. It's just an error with the function prototype, I have correct the prototype which will be corrected in the next compiler release we do.
I also found an issue with the set_nco_inc_value() and set_nco_accumulator() functions writing to incorrect registers. I have updated the compiler and the fix will be available in the next compiler release. |
|
|
|
|
|
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
|