|
|
View previous topic :: View next topic |
Author |
Message |
asdf85
Joined: 03 Jan 2011 Posts: 34
|
UART 1 doesnt work if UART 2 is used |
Posted: Mon Nov 14, 2011 3:23 am |
|
|
Hi,
I've having difficulities getting the 2 UARTS to work. What happens is, if I remove the '#USE RS232(UART1 ....' line, the rx/tx of UART2 works. If i dont remove it, it wont work. I havent really programmed anything for UART1 yet, but i need to use it.
My compiler version is 4.093, and im using pic18f26j11
Here is my code. I didnt post some of the functions coz its too long , and unescessary coz im sure thats not where the problem lies.
Could someone tell me whats causing this problem? Thanks
Code: |
#include "18F26j11.h"
#include <stdio.h>
#fuses HS,NOPROTECT,NOWDT,NODEBUG
#use delay(clock=20000000)
#pin_select RX2=pin_c5
#pin_select TX2=pin_c4
//#use RS232(UART1,baud=9600,parity=n,stream=disp,enable=pin_a5,xmit=PIN_C6,rcv=PIN_C7)
#use RS232(UART2,baud=9600,parity=n,stream=plc,ERRORS)
//===============================
//==================================CRC Variables=================================================================
int16 gencrc(int16 *msg,int msglen); //function to generate CRC; pointer has to be used to send array.
int16 r[12]={0x01}; //bytes received placed in this array
int16 r2[12]={0x00};
int16 s[26]; //bytes to send stored in this array
int16 *rPtr= r; //pointer to array 'r', used to call crc generation function
int16 *sPtr= s; //pointer to array 's', used to call crc generation function
int16 hexs=0xFFFF;
int k;
//=============================================REGISTERS=================================================
int16 inputreg=0b1100101011110000;
//int16 holdreg[16]={0x0007,0x0008,0x0009,0x00AA,0x00BB}; //now its directly stored in eeprom 30-61
int16 coilreg=0; //eeprom MSB=21, LSB=22
//int1 coilreg1[16]={0x01};
//int1 coilreg2[8]={0x01};
//================================================MODBUS Functions===================================================
void fc1();
void fc2();
void fc3();
void fc4();
void fc5();
void fc6();
void fc15();
void fc16();
void exceptioncode(int ec);
void csa(); //change slave address
//==============================================General Variables=============
int channel[512]={0};
int16 counter=0;
int slaveadd=0x01;
int j;int crc1=0; int crc2=0;
int16 regadd=0;int16 noofadd=0;int16 regdata=0;
//=============================================RDA interrupt variables==========
int idl=0; //incoming data length
int1 readyplc=0;
int1 readydisp=0;
int16 x=0;int y=0;
int1 packetend=0;
int1 incomingdata=0;
int biggesty=0;
//=====================================MAIN PROGRAM========================
int temp=0;
void main()
{ clear_interrupt(int_rda2);
enable_interrupts(int_rda2);
// clear_interrupt(int_rda);
// enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
output_high(pin_c2);
output_low(pin_c3);
while(1)
{
if(readyplc==1)
{ readyplc=0;
// output_toggle(pin_c2);
// for(temp=0;temp<idl;temp++)
// { fputc(r[temp],disp);
// }
if(r[0]==slaveadd)
{ output_toggle(pin_c2);
gencrc(&*rPtr,idl-2);
crc1=make8(hexs,0);
crc2=make8(hexs,1);
if(crc1==r[idl-2]&&crc2==r[idl-1])//check the 2 CRC bytes to make sure its correct with the one calculated
{
if(r[1]==1) //function code 1 - read coil status
{ exceptioncode(1);
//fc1();
}
// else if(r[1]==2) //function code 2 - read input status
// { fc2();
// }
else if(r[1]==3) //function code 3 - read holding registers
{ fc3();
}
// else if(r[1]==5) //function code 5 - force single coil
// { fc5();
// }
else if(r[1]==6) //function code 6 - preset single register
{
fc6();
}
// else if(r[1]==0x0F) //function code 15 - force multiple coils
// { fc15();
// }
else if(r[1]==0x10) //function code 16 - preset multiple registers
{
fc16();
}
else
{
exceptioncode(1); // illegal function
}
output_high(pin_b0);
delay_ms(100);
output_low(pin_b0);
}
else
{ exceptioncode(7); //negative acknowledge (wrong CRC)
}
}
else if(r[0]==0)
{
gencrc(&*rPtr,idl-2);
crc1=make8(hexs,0);
crc2=make8(hexs,1);
if(crc1==r[idl-2]&&crc2==r[idl-1])//check the 2 CRC bytes to make sure its correct with the one calculated
{
csa();
}
}
}
}
}
//====================================================Interrupts==============================
#INT_RDA2
void RDA2_isr()
{ r[y]=fgetc(plc);
y++;
x=0;
while(x<1500&&kbhit()==0)
{ x++;
if(kbhit()==1)
{break;
}
}
if(kbhit()==0)
{ idl=y;
y=0;
readyplc=1;
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Mon Nov 14, 2011 5:20 am |
|
|
I don't see that your interrupt is ever going to work properly.
When the interrupt triggers, it says 'one character is waiting'. Nothing more.
A second character will take just over 1mSec to arrive - some 4000 instruction times.
Now your interrupt reads the character, clearing the character waiting flag, and then sets x to 0. So, on your 'while' test, x is _always_ going to be less than 1500, and kbhit, is always going to be 0, and characters are only going to be put into the first location in the array...
Perhaps some rethinking of what you are trying to do is needed?.
Then, why on earth use an int16 array to store characters received?. Wasteful of space, and time.
Then, you can't just 'clear' an RDA interrupt. You _must_ read the character, or it'll reset immediately. Like a lot of hardware interrupts (INT_RB for example), the hardware event that is triggering the interrupt, has to be cleared first.
Best Wishes |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Nov 14, 2011 5:30 am |
|
|
Possibly as you've specified an enable pin in UART1 it has implemented it as a software UART. The hardware doesn't support an enable. It may also give you a software UART because you've specified the tx & rx pins.
I'm not 100% sure why this matters, but looking at your code, I see your kbhit() in your isr calls don't specify which stream. They will default to UART1 if that use rs232 line is in. I think you'll need to change them to kbhit(plc).
One more thing, I see why you need an enable: you are implementing MODBUS. CCS provides MODBUS support in modbus.c. There's an example ex_modbus.c. Take a look, it could save you a lot of time and effort. It did for me.
RF Developer |
|
|
asdf85
Joined: 03 Jan 2011 Posts: 34
|
|
Posted: Wed Nov 16, 2011 7:55 pm |
|
|
Thanks.
I got it working finally.
Initially the problem was with the kbhit() not having the stream name mentioned. But after that there was the problem with the timing due to the delays in the int_rda. I only did that too determine if there's a next byte within the next few milliseconds, but now I removed all delays and used timer interrupts and I got it working. |
|
|
|
|
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
|