![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
chrhartz
Joined: 29 Aug 2008 Posts: 7
|
PIC12F1822: PWM int-flag problem on mask level 9 |
Posted: Fri May 23, 2014 3:43 pm |
|
|
Hi,
I am using PIC12F1822 to generate a sine wave via pwm.
The code was written and tested on silicium mask level 8.
But now I got mask level 9 and the code does not work anymore.
After some testing I found out that the pwm int-flag may cause
the problem.
This is my code:
Code: |
while(1)
{
// check PWM int-flag
if( (PIR1 & 0x02) == 0x02 )
{
// set new pwm value
set_pwm1_duty( sine[ sine_ptr ] );
// read next pwm value from table
if( sine_ptr < 49 ) sine_ptr++;
if( sine_ptr >= 49 )
{
if( input( EN_PIN ) )
sine_ptr = 0;
poti = read_adc( );
poti >>=5;
}
// clear PWM int-flag
PIR1 &= 0xfd;
for( c=0; c<poti; c++ );
}
}
|
This is the init code:
Code: |
void HW_Init ()
{
// Set internal oscillator to 16 MHz
setup_oscillator(OSC_16MHZ|OSC_INTRC);
// Set Timer 2 clock to internal osc, no prescaler, used for PWM timing
setup_timer_2(T2_DIV_BY_1, 99, 1); // 40 KHz
// enable CCP1 for PWM mode
setup_ccp1( CCP_PWM );
setup_comparator(NC_NC_NC_NC);
// Setup Ports for ADC operation
setup_adc_ports(sAN3|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
// Set ADC-Channel for next conversion
set_adc_channel(3);
}
|
The program does not pass the first if statement.
In Mask level 8 it does. Very strange.
The program is used to generate a sine wave with
variable (voltage controlled) frequency for engine
warning signals for zeppelin pilots.
Next week are FAA tests so this problem is very urgent.
If anyone has an idea, please help!
Best wishes,
Chris |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 23, 2014 4:25 pm |
|
|
I assume you're talking about Microchip silicon Rev. A9 for the 12F1822.
Where did you buy the PICs ? A reputable supplier ?
1. Post a complete test program. I don't mean post your whole
proprietary program, but I mean post the #include, all #device
statements, #fuses, #use delay, all necessary variable declarations,
main(), etc., so that we can compile and test the problem.
If you're changing the default behavior of the compiler in any way,
such as changing the #opt level, be sure to tell us.
Test the program before you post it, to confirm that you still get
a failure.
2. Post your CCS compiler version. It's given at the top of the .LST file
after a successful compilation. It's a 4 digit number in this format: x.xxx
Example: http://www.ccsinfo.com/devices.php?page=versioninfo
3. What's the Vdd voltage for your PIC during testing ?
What power supply are you using ? Have you checked it with a scope
for a constant, low noise DC voltage ?
4. Are you using a 12F1822, or is it the "LF" version ? Look at the
markings on the PIC package.
5. What package are you using ? DIP, SOIC, or DFN ?
6. Did you follow all standard design practice rules, such as putting
a 100 nF ceramic SMD capacitor to ground, very close to the PIC's Vdd pin ?
7. Describe the test conditions. Does the A/D voltage come from a
trimpot that you turn with your hand ? What is the voltage range
that you are sending to the AN3 pin with the trimpot during the test ?
Does the problem occur at any particular A/D input voltage ? |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri May 23, 2014 6:58 pm |
|
|
is
SINE[] an int8 or int16 ??
adc, is it in 8 bit or 10 bit output mode ?
poti 16 bit or 8 ?
what is the purpose of var c ??
defining CCP1IF by a #bit directive would be
another way to do the detect and clear thing you coded ...
I do heartily agree with PCMP that too much is still concealed to
have a strong opinion about what is wrong...
what i do suspect is that the later silicon is less broken than what you worked with at first from Microchip
![Very Happy](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19366
|
|
Posted: Sat May 24, 2014 12:43 am |
|
|
As a general comment though, use the #BIT ability to access the flag.
Code: |
#BIT PWMFLAG=PIR1.1
//then the if becomes
if (PWMFLAG)
//and the reset becomes
PWMFLAG=FALSE;
|
Fiddling around with mask bits and bytes, is silly, since the processor has bit test and set functions, and using the #bit command, the compiler will access these. Smaller, faster, less likely to have problems.
Too much 'missing' (as PCM programmer says), to know what is wrong. There is not any visible erratum that would cause this. However look carefully at the errata for the older chip as well - could a compiler fix for one of these give problems with the newer chip?. |
|
![](templates/subSilver/images/spacer.gif) |
chrhartz
Joined: 29 Aug 2008 Posts: 7
|
|
Posted: Sat May 24, 2014 5:21 am |
|
|
@Ttelmah
finally I found the problem. It was the bit setting of the PIR1 register.
I do not really understand the reason. Can anyone explain this?
Why is
if( (PIR1 & 0x02) == 0x02 )
not the same like
if( PWMFLAG ) ?
And I do not understand why the code works with silicon rev. 8
and not with rev. 9. I have both revisions here and can change the
chips easily. With the bit set and test code it runs on both revisions!
If anyone needs a simple tone generator with sine output,
frequency adjustable in 64 steps from 160 to 1.6 KHz and enable,
this is the code:
Code: | /***********************************************************************/
// Compiler Directives
#device adc=10 // 10 Bit ADC result
#FUSES NOWDT // No Watch Dog Timer
#FUSES INTRC_IO // Internal RC Oscillator with I/O on OSC-Pins
#FUSES BROWNOUT // Enable Brownout
/***********************************************************************/
// defines
// Input Pins
#define EN_PIN pin_A5 // (1 = active, Sine enable)
// Internal register definitions
#byte PIR1 = 0x11
#bit PWMFLAG = PIR1.1
/***********************************************************************/
// global vars
unsigned int8 sine_ptr;
/***********************************************************************/
// constants
byte sine[50] = {52,57,62,66,70,74,77,80,82,84,85,86,86,
86,85,83,81,78,75,72,69,65,61,56,52,
48,44,39,35,31,28,25,22,19,17,15,14,14,
14,15,16,18,20,23,26,30,34,38,43,48};
/***********************************************************************/
// Main Program
void main()
{
int16 c;
int16 poti = 0;
// Set internal oscillator to 16 MHz
setup_oscillator(OSC_8MHZ|OSC_NORMAL|OSC_PLL_ON);
// Set Timer 2 clock to internal osc, no prescaler
setup_timer_2(T2_DIV_BY_1, 99, 1); // 40 KHz
// enable CCP1 for PWM mode
setup_ccp1( CCP_PWM );
setup_comparator(NC_NC_NC_NC);
// Setup Ports for ADC operation
setup_adc_ports(sAN3|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
// Set ADC-Channel for next conversion
set_adc_channel(3);
// table pointer to first value
sine_ptr = 0;
//------------------------------------------------------------------
while(1)
{
// check PWM int-flag
if( PWMFLAG )
{
// set new pwm value
set_pwm1_duty( sine[ sine_ptr ] );
// read next pwm value from table
if( sine_ptr < 49 ) sine_ptr++;
if( sine_ptr >= 49 )
{
if( input( EN_PIN ) )
sine_ptr = 0;
poti = read_adc( );
poti >>=5;
}
// clear PWM int-flag
PWMFLAG = FALSE;
for( c=0; c<poti; c++ );
}
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat May 24, 2014 8:23 am |
|
|
Glad it worked out for you.
do you use any low pass analog filtering on the "sine wave"?
8-bit PWM generated "sine" waves have a really significant
even order harmonic content that can be very troublesome in
many applications. 2nd harmonic of only -10db or so for what you
generate this way.
for really excellent, high purity ( 10 bits worth) sine generation
(unfiltered harmonics at -45 db or so ) you might consider
the analog devices Ad9833 and similar DDS chips instead.
as a bonus it makes really linear tri-waves too
( for fans of ODD order harmonics )
just my 2 cents ![Very Happy](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Sat May 24, 2014 8:55 am |
|
|
Quote: | Why is
if( (PIR1 & 0x02) == 0x02 )
not the same like
if( PWMFLAG ) ? |
The only thing I can suggest is to look at the lst file for both forms and see if you see anything obvious. It certainly looks reasonable to me, however, processors don't always see things the same way I do
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19366
|
|
Posted: Sun May 25, 2014 1:47 am |
|
|
It's going to be very different code.
Testing the bit as I show uses a single machine instruction. It'll use either a BTFSC, or a BTFSS instruction to just test the one bit and jump.
The original code, has to load the whole byte from the register, then perform an '&' on this with the constant 2, then take the result, and test if this is equal to 2 (another subtraction). Probably four or five instructions. So using the bit is always going to be quicker, and smaller code. On clearing the bit again using the #bit form, will just use the BCF instruction, while the load and mask form again takes several instructions. However the original form should work.
On a couple of other chips in the PIC12 family there is an erratum concerning byte operations on the PIR register. It's not listed as a problem for this chip, but it sounds as if revision 9, may have added this problem....
If I remember correctly, it was if a bit set in the same instruction as you read it, it could sometimes fail to set. This would give exactly the problem seen here...
Leave everything else unchanged.
Compile with the original code, and save this small part of the assembler. Verify it doesn't work.
Then re-compile with the #bit form, and verify this does work. Again save the assembler section.
Then send the two sections to Microchip, with the simple explanation that the former works with the Rev8 chip, and not with the Rev9 chip....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
chrhartz
Joined: 29 Aug 2008 Posts: 7
|
|
Posted: Sun May 25, 2014 3:26 pm |
|
|
@Ttelmah
Thank you for the explanation. I didnĀ“t know that the #bit directive
uses bit set, test and clear instead of byte operations. I will use this
in the future.
@asmboy
I have found this website from Roman Black:
http://www.romanblack.com/onesec/Sine1kHz.htm
There is a very good description about signal quality and improvements.
I am using his sine table and idea to check the pwm int bit. I have
added the enable signal and start/stop at null point of the sine wave.
Best wishes,
Chris |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|