|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
Compiler Issue w/ UART |
Posted: Thu Oct 12, 2006 10:54 pm |
|
|
I am having a strange issue with RS232 and CCP1. I detect data with my CCP and then store it in an array and convert the read in bits into hex and it works fine and dandy. The kicker is that when I add in a single fprintf statement to print out a newline (\r\n) or a > symbol to signal the end of transmission, it no longer appears to even acquire the data and this boggles my mind. Code listed below:
Code: |
#include <18F2580.h>
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,INTRC_IO
#use delay(clock=20000000)
#use fast_io(A)
#use fast_io(B)
#use standard_io(C)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=talk)
boolean txcomplete = false;
unsigned long data[90];
short dataBits[88];
char dataBytes[11];
int datalength = 0;
unsigned long pastval = 0;
unsigned long pulse = 0;
int bitpos = 0;
int length;
int convertPWMToBits();
void implodeToBytes();
#int_ccp1
void ccp_isr()
{
set_timer0(0);
data[bitpos] = CCP_1;
bitpos++;
}
#int_rtcc
void rtcc_isr()
{
txcomplete = true;
}
void main()
{
int i;
set_tris_a(0b10111001);
set_tris_c(0b10111111);
setup_ccp1(CCP_CAPTURE_RE);
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL);
enable_interrupts(GLOBAL);
while(true)
{
setup_ccp1(CCP_CAPTURE_RE);
enable_interrupts(INT_CCP1);
bitpos = 0;
txcomplete = false;
while(input(PIN_C2));
set_timer0(0);
enable_interrupts(INT_RTCC);
while(!txcomplete);
disable_interrupts(INT_RTCC);
setup_ccp1(CCP_OFF);
disable_interrupts(INT_CCP1);
length = convertPWMToBits();
implodeToBytes();
for(i = 0; i < length/8; i++)
{
fprintf(talk,"%X", dataBytes[i]);
}
fprintf(talk,"\r\n"); //Problem occurs here
}
/*---------------------------------------------------------------------------*/
int convertPWMToBits()
{
long pastval = 0;
short skinny = 1;
int pulsewidth = 0;
int i,bitindex;
bitindex = 0;
for(i = 1; i < bitpos; i++)
{
pastval = data[i-1];
pulsewidth = data[i] - pastval;
if (pulsewidth <100>= 140)
{
skinny = 0;
}
dataBits[bitindex] = skinny;
bitindex++;
}
return bitindex;
}
/*---------------------------------------------------------------------------*/
void implodeToBytes()
{
char hold=0;
int i, j;
for (i=0; i<length/8; i++)
{
hold = 0;
for (j=0; j<7; j++)
{
hold += dataBits[i*8 + j];
hold <<= 1;
}
hold += dataBits[i*8 + 7];
dataBytes[i] = hold;
}
}
} |
When the final fprintf statement is included (I commented it out for testing) it is the only thing that prints (I also tested various characters with the same results) because the rest of the code doesn't appear to execute (the value of the variables bitpos and length have been verified to be 0). If this fprintf statement is left out the code executes flawlessly. Any clues on why this might be happening? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Oct 12, 2006 11:32 pm |
|
|
Quote: | #include <18F2580.h>
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,INTRC_IO
#use delay(clock=20000000) |
The 18F2580 data sheet says (in section 2.6, on the Internal Osc.):
Quote: | The main output (INTOSC) is an 8 MHz clock source |
So with the INTRC_IO, the highest value you can put into the
#use delay() statement is 8 MHz.
Normally, the compiler will setup the OSCCON register to the
correct value automatically for you, by inserting start-up code
at the beginning of main(). However, because you put in an
illegal value for the internal oscillator (20 MHz), the compiler
doesn't initialize the OSCCON register. Also, it doesn't warn
you that it's not doing this.
So OSCCON is left in the power-on reset default state, which is
for 1 MHz. But because your #use delay() is set for 20 MHz,
all the timing parameters calculated by the compiler for the
various library routines, etc., are completly wrong. That's
why nothing works very well.
You need to change your #use delay() to 8 MHz.
Also, if you still need help, you need to fix the posting of your
code. You posted it with HTML enabled, so parts of it got
clobbered. Edit the post, delete all the code. Paste in new
code, and select the checkbox, which is right below the posting
window, and select "Disable HTML in this post". |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Thu Oct 12, 2006 11:59 pm |
|
|
Sorry, forgot to log in before. I tried changing the INTRC_IO, but this was not the issue - I think this is because I am using the EPIC programmer and you set the clocktype in the programmer configuration settings. I set this to HS and it has worked (I tested it with a timer toggling a bit and the calculations hold up for a 20 MHz). Here is the adjusted code as you requested:
Code: |
#include <18F2580.h>
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,HS
#use delay(clock=20000000)
#use fast_io(A)
#use fast_io(B)
#use standard_io(C)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=talk)
boolean txcomplete = false;
unsigned long data[90];
short dataBits[88];
char dataBytes[11];
int datalength = 0;
unsigned long pastval = 0;
unsigned long pulse = 0;
int bitpos = 0;
int length;
int convertPWMToBits();
void implodeToBytes();
#int_ccp1
void ccp_isr()
{
set_timer0(0);
data[bitpos] = CCP_1;
bitpos++;
}
#int_rtcc
void rtcc_isr()
{
txcomplete = true;
}
void main()
{
int i;
set_tris_a(0b10111001);
set_tris_c(0b10111111);
setup_ccp1(CCP_CAPTURE_RE);
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL);
enable_interrupts(GLOBAL);
while(true)
{
setup_ccp1(CCP_CAPTURE_RE);
enable_interrupts(INT_CCP1);
bitpos = 0;
txcomplete = false;
while(input(PIN_C2));
set_timer0(0);
enable_interrupts(INT_RTCC);
while(!txcomplete);
disable_interrupts(INT_RTCC);
setup_ccp1(CCP_OFF);
disable_interrupts(INT_CCP1);
length = convertPWMToBits();
implodeToBytes();
for(i = 0; i < length/8; i++)
{
fprintf(talk,"%X", dataBytes[i]);
}
fprintf(talk,"\r\n"); //Problem occurs here
}
/*---------------------------------------------------------------------------*/
int convertPWMToBits()
{
long pastval = 0;
short skinny = 1;
int pulsewidth = 0;
int i,bitindex;
bitindex = 0;
for(i = 1; i < bitpos; i++)
{
pastval = data[i-1];
pulsewidth = data[i] - pastval;
if (pulsewidth <100>= 140)
{
skinny = 0;
}
dataBits[bitindex] = skinny;
bitindex++;
}
return bitindex;
}
/*---------------------------------------------------------------------------*/
void implodeToBytes()
{
char hold=0;
int i, j;
for (i=0; i<length/8; i++)
{
hold = 0;
for (j=0; j<7; j++)
{
hold += dataBits[i*8 + j];
hold <<= 1;
}
hold += dataBits[i*8 + 7];
dataBytes[i] = hold;
}
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 13, 2006 12:11 am |
|
|
Quote: | if (pulsewidth <100>= 140) |
When you reposted your code, I don't think you disabled HTML.
Or you didn't do a fresh copy and paste from your editor.
Also I notice you're using an array of bits (shorts). That means
you're using vs. 4.xxx. I don't have that version installed on my
computer because I consider it Beta, and I don't want to deal with it.
If you can edit your 2nd post and get it to display the correct code,
I can look at it for problems, but I can't compile and test it. |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Fri Oct 13, 2006 5:48 pm |
|
|
Finally solved the problem - It turns out that this statement was messing with the compiler:
Code: |
#use rs232(baud=9600, rcv=PIN_C7, stream=blueout)
|
This line worked correctly:
Code: |
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=blueout)
|
Apparently the PIC needs a receive and transmit pin set even if all the user is doing is receiving to work properly. Any thoughts on why this might be the case? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Fri Oct 13, 2006 6:09 pm |
|
|
Yes - if you onoly specify one pin you are using a software UART. If you define both and they both map to the respective UART pins then you are using the hardware UART.
So you problem is actually related to how you aer using the software UART. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 13, 2006 6:13 pm |
|
|
Your posts didn't show that code.
But anyway, the answer is that you must specify both hardware UART
pins in the #use rs232() statement, to get the compiler to generate
code for a hardware UART.
If you only specify one pin , it will generate code for a software UART.
The soft UART is much more sensitive. It can't be interrupted, or it will
lose an incoming character. Also, #int_rda only works with a hardware
UART. You can't use it with a soft UART.
---------
Edit: Oops, you beat me to it, asmallri. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Fri Oct 13, 2006 6:49 pm |
|
|
PCM programmer wrote: |
Oops, you beat me to it, asmallri. |
And about time too :-) |
|
|
Ttelmah Guest
|
|
Posted: Sat Oct 14, 2006 5:18 am |
|
|
It is worth adding though, that if you want to just use one pin on the hardware, specify both, and then just use the other pin as normal. Code to actually send/receive the bytes is only generated when you perform these operations, and normal I/O, will override the hardware.
Best Wishes |
|
|
|
|
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
|