|
|
View previous topic :: View next topic |
Author |
Message |
John Morley
Joined: 09 Aug 2004 Posts: 97
|
Problem with serial output on 12F675 |
Posted: Fri Jun 24, 2011 1:38 pm |
|
|
Hi All,
I'm having a problem sending serial data from a 12F675. This design uses two A/D inputs to measure the output of a couple of sensors, and then controls a warning lamp connected to an output pin. There is also a pin assigned to send diagnostic messages for troubleshooting/development purposes.
Everything is basically working OK, but my diagnostic messages are not printing correctly. I have a stripped down version of the code that shows the problem:
Code: |
#include <12F675.h>
#device ADC=10
#fuses INTRC_IO, NOWDT, NOBROWNOUT, NOPROTECT, NOPUT, MCLR
// Here we configure the internal 4 MHz oscillator....
#use delay(clock=4000000)
#define Range_Input PIN_A3
#define Current_Input PIN_A2
#define Lamp_Output PIN_A5
#define Data_Output PIN_A0
// Here we configure the diagnostic serial LCD module....
#use rs232(baud=9600, xmit=Data_Output, stream = LCD)
void Blink_LED(int8 NumBlinks)
{
int8 iIndex;
for (iIndex = 1 ; iIndex <= NumBlinks ; iIndex++)
{
output_high(Lamp_Output);
delay_ms(350);
output_low(Lamp_Output);
delay_ms(350);
}
}
void main()
{
int16 Value;
int1 bIs28V;
// Here we turn off unused peripherals....
setup_timer_1(T1_Disabled);
setup_comparator(NC_NC_NC_NC);
setup_vref( FALSE );
//Here we set the initial state of the lamp output
output_low(Lamp_Output);
// Here we configure the A/D converter module....
// Range Sensing will be on pin 'AN3' and Current Sensing will be on pin 'AN2'....
setup_adc_ports(sAN2 | sAN3 | VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL );
set_adc_channel(Range_Input);
delay_us(10); // Delay to allow the channel to be acquired
Value=read_adc();
if (Value > 600)
{
Blink_LED(6);
bIs28V = True;
}
else
{
Blink_LED(3);
bIs28V = False;
}
// Here we have some basic diagnostic printing....
fprintf(LCD, "Range: %lu\n\r", Value);
fprintf(LCD, "Is28V: %u", bIs28V);
fprintf(LCD, "\n\r");
while(1); //end here
}
|
When I run this code, I see the following printed to a Hyperterminal window:
V: 0
As you can see, most of the diagnostic message is cut off, except for the last few characters of the 2nd line.
Interestingly, if I comment out the call to the 'Blink_LED' subroutine above, it prints correctly. The problem is NOT this subroutine, however, because the issue returns if I insert any small delay directly ahead of the fprintf statements.
I assume that my serial output pin is not being configured properly, but I don't know what that issue might be. I tried to turn off all other pin functions that I'm not using.
127675 is being powered by a well filtered 7805 voltage regulator.
My compiler is v4.050
Thanks,
John _________________ John Morley |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 24, 2011 2:01 pm |
|
|
What's the manufacturer and part number of the LCD ?
Has it ever worked ?
What happens if you strip the program down, cutting out 90% of the
code and merely have a main() with a delay at the start (say, 1000 ms)
and then do a printf with a while(1) at the end ? Does it then work ?
Aside from that, here are a few other comments:
Quote: |
#define Range_Input PIN_A3
set_adc_channel(Range_Input);
|
ADC channel numbers must be 0, 1, 2, 3, etc., not CCS pin numbers.
Quote: |
#fuses INTRC_IO, NOWDT, NOBROWNOUT, NOPROTECT, NOPUT, MCLR
#define Range_Input PIN_A3
12F675 Data sheet pinout for pin 4: GP3/MCLR/VPP
|
If GP3 is configured as the MCLR pin, it can't be used for i/o and must
have a 10K pull-up on it. It's dedicated to being an MCLR (reset) pin only.
In fact, is it possible that you're resetting the PIC with an analog signal
coming into the MCLR pin ? Remove everything from that pin except the
10K pullup.
Quote: | setup_adc(ADC_CLOCK_INTERNAL ); |
The 12F675 data sheets says (in the ADC section), to use this divisor
for 4 MHz operation:
|
|
|
John Morley
Joined: 09 Aug 2004 Posts: 97
|
|
Posted: Fri Jun 24, 2011 2:59 pm |
|
|
Hi,
When things did not go as expected, I added a MAX232 to my circuit, and I'm now viewing the diagnostic messages on Hyperterminal. I also tried RealTerm, so it's not the terminal client that is causing the problem.
I have a 10K pull-up on MCLR, and I changed the ADC clock to "ADC_Clock_DIV_8"
I think a problem is my confusion with physical pin numbers, pin references, and analog input references? I think I've corrected that, but the problem persists.
My hardware is connected as follows:
The digital output to the lamp is on physical Pin #2
One analog input is physical pin #3
One analog input is physical pin #5 (not used in my test example)
Diagnostic data is sent to physical pin #7
The datasheet lists pins GP0 thru GP5, and the pin references in the 12F675 header file are Pin_A0 thru Pin_A5. I assume they correspond? The A/D references are 'sAN0', 'sAN1', 'sAN2', and 'sAN3'.
Here is an updated version of the code:
Code: |
#include <12F675.h>
#device ADC=10
#fuses INTRC_IO, NOWDT, NOBROWNOUT, NOPROTECT, NOPUT, MCLR
// Here we configure the internal 4 MHz oscillator....
#use delay(clock=4000000)
#define Range_Input PIN_A4
#define Current_Input PIN_A2
#define Lamp_Output PIN_A5
#define Data_Output PIN_A0
// Here we configure the diagnostic serial LCD module....
#use rs232(baud=9600, xmit=Data_Output, stream = LCD)
void Blink_LED(int8 NumBlinks)
{
int8 iIndex;
for (iIndex = 1 ; iIndex <= NumBlinks ; iIndex++)
{
output_high(Lamp_Output);
delay_ms(350);
output_low(Lamp_Output);
delay_ms(350);
}
}
void main()
{
int16 Value;
int1 bIs28V;
// Here we turn off unused peripherals....
setup_timer_1(T1_Disabled);
setup_comparator(NC_NC_NC_NC);
setup_vref( FALSE );
//Here we set the initial state of the lamp output
output_low(Lamp_Output);
// Here we configure the A/D converter module....
// Range Sensing will be on pin 'AN3' and Current Sensing will be on pin 'AN2'....
setup_adc_ports(sAN2 | sAN3 | VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(3);
delay_us(10); // Delay to allow the channel to be acquired
Value=read_adc();
if (Value > 600)
{
Blink_LED(6);
bIs28V = True;
}
else
{
Blink_LED(3);
bIs28V = False;
}
// Here we have some basic diagnostic printing....
fprintf(LCD, "Range: %lu\n\r", Value);
fprintf(LCD, "Is28V: %u", bIs28V);
fprintf(LCD, "\n\r");
while(1); //end here
}
|
If the 'Blink_LED' routine is executed, the diagnostic message is not printed correctly. If I comment this part out, I see the message as expected with a valid A/D reading being displayed.
Thanks,
John _________________ John Morley |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 24, 2011 4:25 pm |
|
|
It works for me. I get this output on TeraTerm:
Quote: |
Range: 56
Is28V: 0
Range: 127
Is28V: 0
|
I ran the program twice. That's why there are two sets of output.
I didn't use a MAX232. I used a direct rs232 connection, just to save time.
I took your latest program and added the INVERT parameter to the
#use rs232() statement. Then I connected pin A0 directly to the Rx pin
on the COM port connector on my PC (with a cable). Also, I connected
ground from the board to the ground pin on the COM port. The board
is a Microchip "low pin count" board. I programmed the 12F675, and
then removed the Pickit 2, and supplied power to the board from a
+5v bench power supply. The program was compiled with vs. 4.050.
I'm sure it would work just fine if I used a Max232 and didn't use the
INVERT option.
My guess is, maybe look for a solder short on your board ? Or check the
power supply voltage and stability ? |
|
|
John Morley
Joined: 09 Aug 2004 Posts: 97
|
|
Posted: Sun Jun 26, 2011 7:51 pm |
|
|
Hi pcm!
Thanks for making those tests for me!
I'm not sure whats going on, but I can reliably cause the serial output to become corrupted simply by including the Blink_LED routine. It's a handwired prototype, so it's possible that there is a short, or some crosstalk going on that is specific to this prototype. I'm going to have a PCB built now for this project, and I'll report back when I have it to let you know whether the problem is solved or not!
Thanks,
John _________________ John Morley |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Jun 27, 2011 2:41 am |
|
|
You have got a resistor between the PIC output, and the LED?. If not you will be overloading the PIC when you 'blink' the LED, and anything could happen....
Best Wishes |
|
|
John Morley
Joined: 09 Aug 2004 Posts: 97
|
|
Posted: Mon Jun 27, 2011 9:21 am |
|
|
Hi,
The 'LED' will actually be an incandescent warning lamp in the final application, so it's being drive by a small N-channel MOSFET connected to the PIC output pin.
Thanks for the suggestion!
John _________________ John Morley |
|
|
|
|
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
|