![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
magestik
Joined: 16 Oct 2008 Posts: 59
|
Problem with 2 18LF4550 and uart |
Posted: Thu Aug 13, 2009 2:05 am |
|
|
Hello,
I am having a big problem using UART, let me explain :
I'm having 2 PIC, one is basicaly getting characters, the other one is sending them.
I posted the full program, which is quite complex, but a few lines are necessary. As you can see below, PIC1 is using fgetc at 9600 bauds.
The PIC2 is basicaly sending 0x08 and 0x0D to PIC1.
Code: | if(taille == 0x08)
{
fputc(taille, PIC2);
}
and
fputc(0x0D, PIC2); |
Both PICs are at 9600 bauds, yet, the fgetc doesn't seem to get the data.
I know the 0x08 and 0x0D are there, i saw them with a scope. Also, i tried to bit bang the incoming result, and i see the bits changing, but can't get the hex character. I really don't understand why the fgetc can't get the 0x08.
I tried to toggle a LED when entering the kbhit function, it does toggle.
So the pic is detecting something, yet can fully get it.
It seems that i can get the 0x08 when PIC1 is at 4800 bauds, while PIC2 is at 9600 bauds, is it possible ???
I might be unclear with so much code, if someone could be of any help, it would really be appreciated.
Code for PIC1 :
Code: | #include <18F4550.h>
#include "usb_bootloader.h"
#fuses HS,NOWDT,NOLVP,NOPROTECT
#use delay(clock=20000000) // 48000000
#use rs232(baud=9600, rcv=PIN_C0, bits=8, STOP=2, STREAM=VNC1L, force_sw)
#include "mmcsd.c"
unsigned int32 compt = 0;
int1 tab50[50];
void main(void)
{
unsigned int8 c;
unsigned int8 i;
unsigned int16 cpt1;
unsigned int1 tabbit[8];
mmcsd_init();
delay_ms(2);
while (true)
{
if (kbhit(VNC1L))
{
c = fgetc(VNC1L);
if (c == 0x08)
{
output_toggle(PIN_A0);
c = fgetc(VNC1L);
if (c == 0x0D)
output_toggle(PIN_A1);
for (i=0; i<8; i++)
c = fgetc(VNC1L);
}
}
}
} |
Code for PIC2 :
Code: | #include <18F4550.h>
#fuses HS,WDT512,NOPROTECT,NOLVP,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,bits=8, STOP=2, stream=VNC1L)
#use rs232(baud=9600,xmit=PIN_D2,bits=8, STOP=2, stream=PIC2)
//Tells the CCS PIC USB firmware to include HID handling code.
#define USB_HID_DEVICE TRUE
//the following defines needed for the CCS USB PIC driver to enable the TX endpoint 1
#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE 8
#define USB_EP2_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP2 for IN bulk/interrupt transfers
#define USB_EP2_TX_SIZE 8
#define USB_EP2_RX_ENABLE USB_ENABLE_INTERRUPT //turn on EP2 for IN bulk/interrupt transfers
#define USB_EP2_RX_SIZE 4
#define LED1 PIN_A5
#define START PIN_D2
#define VNC1L_RTS PIN_D3
#include <pic18_usb.h>
#include <usb_desc_kbmouse.h> //USB Configuration and Device descriptors for this UBS device
#include <usb.c> //handles usb setup tokens and get descriptor reports
void ftdi();
void send_usb();
void change_led_state();
static int8 tx_msg[7]={0,0,0,0,0,0,0}; // 8 bytes array
int1 buffer300[300]; // 8 bytes array
int8 i=0;
int1 ledchange=0;
unsigned char etat_led;
void main(void)
{
int8 led_count;
int16 nbbits=0;
int1 tabbit[9];
int8 taille=0;
int8 cpt1;
delay_ms(2000);
usb_init_cs();
delay_ms(1);
while(1)
{
restart_wdt();
if(input(VNC1L_RTS) == 0)
{
fprintf(VNC1L, "DRD%c", 13);
//output_high(START);
for(nbbits=0; nbbits<300; nbbits++)
{
buffer300[nbbits]=input(PIN_C7);
//delay_us(92);
delay_us(40);
}
//output_low(START);
nbbits = 0;
while (buffer300[nbbits] == 1)
nbbits++;
for(cpt1=0; cpt1<9; cpt1++)
{
tabbit[cpt1] = buffer300[nbbits];
nbbits++;
if(tabbit[cpt1] == buffer300[nbbits])
nbbits++;
}
taille = 0;
for(cpt1=8; cpt1>0; cpt1--)
if(tabbit[cpt1] == 1)
bit_set(taille,cpt1-1);
if(taille == 0x08)
{
fputc(taille, PIC2);
for(i=0; i<9; i++)
{
while(buffer300[nbbits] == 1)
nbbits++;
for (cpt1 = 0; cpt1 < 9; cpt1++)
{
tabbit[cpt1] = buffer300[nbbits];
nbbits++;
if (tabbit[cpt1] == buffer300[nbbits])
nbbits++;
}
if (i>0)
{
taille = 0;
for(cpt1=8; cpt1>0; cpt1--)
if(tabbit[cpt1] == 1)
bit_set(taille, cpt1-1);
tx_msg[i-1] = taille;
}
else
fputc(0x0D, PIC2);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Thu Aug 13, 2009 3:30 am |
|
|
You have a lot more going on, that you imply....
On PIC2, how critical are the 40uSec sampling times?. You are doing looped access to an array of bits. I'd expect the code for this alone, could be easily taking several uSec....
Then, you walk through a bit array, looking for 9 edges. If you don't see these, this part of the code will never exit, and could loop right through memory.
Then, you have a header loading on PIC1, which suggests is i using a USB bootloader. _This_ will have it's own fuses. Normally, if a bootloader is present, it has to have the fuses set the way it needs, and won't change them. One obvious suggestion, is that this doesn't use the HS fuse, but has the PLL selected. If so, the clock rate on this chip will not be 20MHz, but 48MHz (if the rest of the fuses match what you have on PIC2).
Seriously, throw away the code, and prove where the problem is.
You show exactly what you need as 'test' code, at the top of your post, so use it. Make a simple loop, wait a few milliseconds, send a pair of bytes with an easily recognisable data pattern (0xAA 0x55), and loop. _Time_ the waveform, is the frequency what you expect?. If not, you have a timing problem in PIC2. If it is, start looking at PIC1. Have it simply read bytes as received, and toggle an output line. Does the line toggle 1/960th second after the first falling edge?. If not, then you have a timing problem in PIC1.
Simple rule, before posting, _simplify_.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
magestik
Joined: 16 Oct 2008 Posts: 59
|
|
Posted: Thu Aug 13, 2009 6:52 am |
|
|
Oh I didn't know using a bootloader will have its own fuses !!!!!!!!!!
I changed clock=20000000 to clock=48000000, everything works now.
Thank you so much, you saved me .
I never read that information anywhere .
My bootloader is :
Code: |
///////////////////////////////////////////////////////////////////////////
//// USB_BOOTLOADER.H ////
//// ////
//// ////
///////////////////////////////////////////////////////////////////////////
//how big is the bootloader?
//the bootloader will reside from address 0x0000 to this location. the
//application will then sit at this location+1 to the end of program memory.
#define LOADER_SIZE (0xFFF)
#define LOADER_START (0)
#define LOADER_END (LOADER_SIZE)
#define APPLICATION_START (LOADER_SIZE+1)
#define APPLICATION_END (getenv("PROGRAM_MEMORY")-1)
#define APPLICATION_ISR (APPLICATION_START+8)
#ifndef _bootloader
//in the application, this moves the reset and isr vector out of the bootload
//space. it then reserves the loader space from being used by the application.
#build(reset=APPLICATION_START, interrupt=APPLICATION_ISR)
#org 0, LOADER_END {}
#endif
|
Would you have any documentation on how bootloader works ?
Also, where can you see the fuses the bootloader uses ? it isn't written in this code ![Confused](images/smiles/icon_confused.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Thu Aug 13, 2009 7:39 am |
|
|
That is not the bootloader.
That is the code to tell the compiler to leave space _for_ the bootloader.
The bootloader, is another complete program, which executes normally on 'boot' (hence the name), and looks for some 'key' to say that it is to load data from a source into the memory. The 'key', can be an external pin, a particular character, or timing based (all depends on the bootloader involved). When it sees this key, it carries on executing, and loads code. If the key is not seen, it then jumps to your program.
The bootloader, is then a complete program (with fuses), loaded into the chip, which itself then allows you to program the rest of memory (the area where it is not present), without having to use a programmer.
Now the bootloader _must_ know the chip's clock rate, and configuration, or it can't run. If (for instance), the bootloader was written to use 'HS', and you were allowed to reprogram the fuses, and changed them to INT_RC, the bootloader would no longer be able to handle the serial, since the clock had changed...
So, normally the bootloader _won't_ reprogram fuses. You
have to set your main code, to use the same fuses as the bootloader was configured to use. The behaviour is down to the intelligence of the original bootloader. Some will just ignore fuse changes. Some will warn you. Some will allow fuses to change that don't affect the clock. Some will reprogram fuses, and then stop working.....
If you look at 'loader.c' (the CCS example bootloader), you will see, that it only programs data with addresses below 0x300000 (for the 18H chips). 0x300000, is the start of the locations for the configuration data (fuses). So this bootloader, just silently ignores fuse settings in the program it is loading (commonest solution).
Best Wishes |
|
![](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
|