|
|
View previous topic :: View next topic |
Author |
Message |
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
Hardware Specs: |
Posted: Mon Feb 14, 2005 5:31 pm |
|
|
The PIC is powered by a 3.6V lithium cell. It reads 3.53V.
REED is connected to a normally open reed switch. The pullup on the reed switch is 470k Ohm.
AD_IN is the input for the A/D converter. It's connected to COMP_IN and the common line has a 1M Ohm pullup. (There's a very special reason that they are connected in this way.) Draw a lower-case h, put AD_IN on one of the feet, COMP_IN on the other foot, and a 1M on the top of the h, and you'll have a good idea of what I mean.
The pullup resistors and the reed switch are the only things connected to thses pins right now.
AD_IN and COMP_IN are at 3.3 V and will not change; there is nothing on these pins expect the pullup resistors.
REED is at 3.46 when open and 0 V when closed.
Note that I have NOT set CS_GPS to go low during the interrupt. The commented-out line shows that is what I intend later, but I haven't put that part in yet.
Thanks for your help. _________________ In the 90's, I promised myself I'd never use a so-called "smiley icon". I hate what I've become. ;) |
|
|
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
It gets better... |
Posted: Mon Feb 14, 2005 6:14 pm |
|
|
PCM et al:
Here's something even better:
The bug does not repeat NOT happen in compiler version 3.178. It does happen in version 3.218, and it DOES happen in version 3.191. I don't have any other versions available.
I guess when they were "adding support for the newest devices" they took out the part where they support the 16F88. It looks like a bug in the compiler. Is there somewhere where I should send this to? _________________ In the 90's, I promised myself I'd never use a so-called "smiley icon". I hate what I've become. ;) |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 14, 2005 6:32 pm |
|
|
That's a big help. I'll install vs. 3.178 and compare the listings
for the program you posted. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Mon Feb 14, 2005 9:15 pm |
|
|
V3.178 listing
Quote: |
.................... SETUP_ADC_PORTS( NO_ANALOGS );
0075: BSF 03.5
0076: CLRF 1F // ADCON0
0077: CLRF 1B // CCPR2L
....................
|
V3.190 listing
Quote: |
.................... SETUP_ADC_PORTS( NO_ANALOGS );
007A: BSF 03.5
007B: MOVF 1F,W
007C: ANDLW C0
007D: MOVWF 1F // ADCON0
007E: CLRF 1B // CCPR2L
....................
|
V3.178 listing
Quote: | .................... MAGNET_ON = C1OUT;
003A: BCF 03.5
003B: BCF 29.0
003C: BTFSC 1F.6
003D: BSF 29.0
.................... //CS_GPS = FALSE;
.................... }
003E: BCF 0D.6
003F: BCF 0A.3
0040: GOTO 022
Configuration Fuses:
Word 1: 3934 WDT PUT MCLR NOBROWNOUT NOLVP NOCPD WRT NODEBUG CCPB0 NOPROTECT INTRC_IO
|
V3.190 listing
Quote: | .................... MAGNET_ON = C1OUT;
003A: BCF 03.5
003B: BCF 29.0
003C: BSF 03.5
003D: BTFSS 1C.6
003E: GOTO 042
003F: BCF 03.5
0040: BSF 29.0
0041: BSF 03.5
.................... //CS_GPS = FALSE;
.................... }
0042: BCF 03.5
0043: BCF 0D.6
0044: BCF 0A.3
0045: GOTO 022
Configuration Fuses:
Word 1: 3934 WDT PUT MCLR NOBROWNOUT NOLVP NOCPD WRT NODEBUG CCPB0 NOPROTECT INTRC_IO
Word 2: 3FFF FCMEN IESO
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 14, 2005 9:27 pm |
|
|
I looked at the listing for vs. 3.178 and it's got serious problems.
The register address for CMCON is wrong. It's supposed to be 0x9C
for the 16F88, but 3.178 is using 0x1F. That's the CMCON address for
a 16F628.
Also the address of the C1OUT bit is incorrect in vs. 3.178.
This bit is defined in 16F88.H as 0x1F.6, and it should be 0x9C.6.
What's happening with 3.178 is that the power-up state of the
comparators is "off", and because of the incorrect register
addresses, it's left in that condition. You reported earlier that
if the comparators are not setup, then your code works.
So that's why 3.178 appears to work.
I'll continue to look at the problem. I will get a 16F88 in on Wednesday,
so you might not get an answer until later in the week. Of course,
anyone else who wants to help can do so. |
|
|
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
|
Posted: Tue Feb 15, 2005 5:42 pm |
|
|
Thanks, PCM.
The GPS engine is not capable of turning that line low. It's really the enable pin on a very precise voltage regulator which in turn powers the GPS engine. The voltage regulator will only shut off if the voltage frops below 2.2V, and that's not what the scope is showing. Based on the differing behaviour with different software versions and comparator configureations, I'm really leaning towards a problem internal to the PIC.
Yes, looking at the schematic, I've got a ferrite bead and the enable pin on a tristate buffer leading from the CS_GPS pin. Unless the ferrite bead is somehow haunted, the CS_GPS turnoff isn't coming from there.
Grr. If only the ICE plugin for the 16F88 wasn't so bloody expensive. I guess it makes more financial sense for me to waste thousands of dollars in labour than it does to buy the $1000 emulator. </irony> _________________ In the 90's, I promised myself I'd never use a so-called "smiley icon". I hate what I've become. ;) |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 18, 2005 12:48 am |
|
|
I received my 16F88 and I was able to duplicate the problem.
It's a RMW problem. When the comparators are configured
in Mode 2, all the input pins (RA0-RA3) are set as analog inputs.
It doesn't matter what state the CIS bit is in, they are still configured
as analog inputs. You can override part of this by setting pin A3
as a digital pin with the ANSEL register. But the input latch for
pin A3 has a logic '0' on it, due to the analog-input configuration
and you can't change it. Because of this, if you read pin A3 you
will always read a logic '0'.
This causes a problem because when you write code like this,
you are doing a RMW on all pins of Port A. The PIC reads all
Port A pins into a temporary register. Then it modifies the
VHF_MOD bit (it sets bit 4 = logic high) in that register. Finally,
it writes the entire register to the Port A output latches.
But because it read a 0 on pin A3, it writes a 0 back to it.
That's why calling the vhf_chirp() function causes CS_GPS to go low.
Both of the lines of code, VHF_MOD = HIGH or VHF_MOD = LOW
do the RMW and will cause CS_GPS to go low.
The solution is to use a shadow register to hold the Port A bit values.
You update the shadow register and then write its contents to Port A.
I stripped your program down to the minimum necessary to show the
problem. In the code below, I have redefined the #bit variables, so
they are in a shadow register, instead of being directly on Port A.
I also declare a shadow register and initialize it to 0. There is also
a macro which I defined, in order to make it easier to update the code.
Every place in your code where you access a bit on Port A, must be
changed to use the new "update_Port_A()" function (macro).
For example, if you have
then you must change it to this:
Code: | update_Port_A(VHF_MOD, HIGH); |
You have to do this everywhere you access a Port A pin.
If you miss even one place, it'll do the RMW and set CS_GPS low.
Code: | #include <16F88.H>
#fuses INTRC_IO,NOWDT,PUT,NOPROTECT,NOBROWNOUT,MCLR,NOLVP,WRT
#use delay( clock=4000000 )
#ignore_warnings 203
#byte PORT_A = 0x05
int8 Shadow_Port_A = 0;
#bit REED = Shadow_Port_A.0 // 470K pullup.
#bit AD_IN = Shadow_Port_A.1 // Wired to COMP_IN
#bit COMP_IN = Shadow_Port_A.2 // and has a 1Meg pullup.
#bit CS_GPS = Shadow_Port_A.3
#bit VHF_MOD = Shadow_Port_A.4
#bit MCLR = Shadow_Port_A.5
#bit MORT = Shadow_Port_A.6 // pullup
#bit CS_RTC_READ = Shadow_Port_A.7
// This macro updates Port A bits via a shadow register.
#define update_Port_A(bit ,value) bit = value; PORT_A = Shadow_Port_A
#byte OSC_CON = 0x8F
#byte TRIS_A = 0x85
#byte COMREF = 0x9D
#byte ANSEL = 0x9B
#byte CMCON = 0x9C
//=========================================
void main()
{
OSC_CON = 0x62;
setup_comparator( A0_VR_A1_VR );
//set the voltage reference for about 1/2 way.
COMREF = 0b10000111;
TRIS_A = 0b01100111;
setup_adc_ports(sAN0 | sAN1 | sAN2);
update_Port_A(CS_GPS, 1);
//CS_GPS = 1;
delay_ms(3000);
update_Port_A(VHF_MOD, 1);
//VHF_MOD = 1; // This line makes CS_GPS go low
delay_ms(5000);
update_Port_A(CS_GPS, 1);
// CS_GPS = 1;
while(1);
} |
-----------------------------
I found a few other things in your code:
1. You have several places where you're doing this
Code: | PORT_A = PORT_A;
PORT_B = PORT_B; |
I'm not sure what your intention is, but the compiler optimizes that
code away. No assembly language instructions are generated.
You can see this in the .LST file.
2. According to the 16F88 data sheet, in the comparator ISR
you need to read the CMCON register and clear the CMIF bit
before you exit the ISR. The compiler inserts code to clear
the CMIF bit, but it doesn't take care of reading CMCON, so
you need to do that. The isr should be modified as shown
in bold below.
#byte CMCON = 0x9C // Put this above main()
#int_comp
void magnetic_interference()
{
char c;
OSC_CON = 0b01100010;
//The comparator has just been triggered. Set the MAGNET_ON
//to sync with the comparator. The reed switch is on A0, and that
//is comparator one. The pin will go low when the reed switch is
//activated, so the negative rail of the comparator will go below
//the positive rail, making C1 out low.
MAGNET_ON = C1OUT;
//CS_GPS = FALSE; (this was commented out by you)
c = CMCON; // Read the CMCON register before exiting
}
3. In your initialize() function, you have one line like this:
Code: | TRIS_A = 0b00100101; |
That's setting pin A1 to an output. But pin A1 is the Vin- pin
for Comparator #1. So I think it should be:
Code: | TRIS_A = 0b00100111; |
I did note that CCS is still using the obsolete TRIS instruction in
their built-in function, set_tris_a(), so I think it's a good idea to
set it manually as you're doing. I mean, TRIS may work, but
it's not in the published instruction set in the data sheet, so why
take the chance ? I've told them about this, but they don't
seem to want to change it. |
|
|
theMagni
Joined: 21 May 2004 Posts: 48 Location: Victoria, BC
|
|
Posted: Fri Feb 18, 2005 11:48 am |
|
|
Well, wow.
Where did you learn that? That's certainly a solution I couldn't have come up with. That's just... fantastic. Thank you very much. Can I send you some beer or something?
As for the PORTA = PORTA thing, the intent was to let the external wiring set the logic levels on the pins after I write a value to them. In the interrupts, the intent is to clear the interrupt flag. The manual told me that any write or read of the port clears the flag. Those lines were in the old code that I inherited, and I assumed that that was why they were there. I graduated in June and was hired to sort out and organize all the code here. My assembly is really, really, really poor, so I don't check the LST files. If it doesn't generate code then I'll take the lines out.
The reason I set the A1 pin to an output was because I made a mistake. Thanks for catching that.
All this time I thought you worked for CCS. Huh. _________________ In the 90's, I promised myself I'd never use a so-called "smiley icon". I hate what I've become. ;) |
|
|
|
|
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
|