|
|
View previous topic :: View next topic |
Author |
Message |
NEUTRONJOHN Guest
|
USART 2 interrupt service not working on 18f8722 |
Posted: Thu Sep 24, 2009 1:23 am |
|
|
I am having trouble getting an interrupt to fire on USART2 with a 9th bit protocol....similar code works fine in other applications.
I can see Transmit_STB() working after detection of the INT0IF, the other controller I am talking to answers...but I never see an interrupt generated, PIN_D4 or D5 never goes high. Once into the routine it would validate the 1st address byte is correct, etc. , and accept the rest of the response, but it never gets there.
I have played with using SFRs directly and setting the Baud rate directly...but no joy.
I apologize for the LONG code segment...any help is appreciated: PCWH version is 4.092.
Code: |
#use delay(clock=40M, oscillator=10M)
#use rs232(UART1,baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS,STREAM=HOST)
#use rs232(UART2,baud=115200,parity=N,xmit=PIN_G1,rcv=PIN_G2,bits=9,ERRORS,STREAM=STB)
#include <Telem_TEST1.h>
#include <Telem_TEST_vars.h>
// SubRoutine Templates
void SPI_Service(void);
void Transmit_STB(void);
void Receive_STB(void);
void Save_STB(void);
void Xmit_ULink(void);
void InitQ(void);
#int_RDA
void RDA_isr(void)
{
// handler for input commands from the Host PC would go here...
}
//**************************************************************************
// STB Serial ISR
//
// Receive Interrupt - when address bit is set
// in 1st xmission matches the BoardAddress
//**************************************************************************
#int_RDA2
void RDA2_isr(void)
{
int CS;
output_high(PIN_D4); // SET WHEN WE GET A SERIAL INTERRUPT
NewPacket = 0;
SerialError = 0;
ReceivedAddress = RCREG2; //get byte from receive buffer, CHECK FOR ALL LEGAL ADDRESSES
if ( ReceivedAddress == 30 )
{
output_high(PIN_D5); // for debug!!!! Set while wating for next byte
NewPacket = 1; //set flag for new packet is coming
ADDEN2 = 0; //allow receiver to get the rest of the packet
output_low(PIN_D5);
Buff[0] = ReceivedAddress; //shove address into 1st slot...
//Receive packet size High Byte
Tout = RecvTimeout;
while(RC2IF == 0) //wait for next byte in receiver
{
Tout--;
output_high(PIN_D5); // for debug!!!!Set while wating for next byte
if(Tout == 0)
{
SerialError = 130; //Timeout error
goto ErrorTest;
}
}
output_low(PIN_D5); // for debug!!!! 2nd byte arrived
Buff[1] = RCREG2; //get size byte from serial port
// Receive packet size Low byte
Tout = RecvTimeout;
while(RC2IF == 0) //wait for next byte in receiver
{
Tout--;
output_high(PIN_D5); // for debug!!!!Set while wating for next byte
if(Tout == 0)
{
SerialError = 130; //Timeout error
goto ErrorTest;
}
}
output_low(PIN_D5); // for debug!!!!last size byte arrived
Buff[2] = RCREG2; //get byte from serial port
RecvPacketSize = Buff[2]; //add size and checksum to packet size
// --- receive packet
RecvPointer = 3; //position pointer at first byte
// receive rest of packet past the packet size bytes.....
while(RecvPointer < (RecvPacketSize+1))
{
Tout = RecvTimeout;
while(RC2IF == 0)
{
Tout--;
output_high(PIN_D5); // for debug!!!!Set while wating for next byte
if(Tout == 0)
{
SerialError = 130; //Timeout error = 0x82
goto ErrorTest;
}
}
output_low(PIN_D5); // for debug!!!! next byte here
Buff[RecvPointer] = RCREG2; //save packet data in buffer array
RecvPointer++;
}// end of while RCVpointer <= RecvPacetsize
CS = 0;
RecvPointer = 1;
while(RecvPointer < Buff[2])
{
CS = CS + Buff[RecvPointer];
RecvPointer++;
}
CS = ~(CS) + 1; //CheckSum is now 2's complement
RecvPacketSize = Buff[2];
if (CS != Buff[RecvPacketSize])
{
SerialError = 129; //checksum error = 0x81
}
}// End of IF Rc'd addr = Board Address
ErrorTest:
ADDEN2 = 1; //enable interrupt when address bit is set
output_low(PIN_D4); // clr when doen with ISR
}// end of RDA2 ISR
void main()
{
setup_adc_ports(AN0_TO_AN5|VREF_VREF);
setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_20);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_spi2(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
//setup_timer_0(RTCC_OFF );
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED, 0,1);
setup_timer_3(T3_DISABLED);
setup_timer_4(T4_DISABLED, 0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_low_volt_detect(FALSE);
// Ninth bit protocol set-up USART2
SYNC2 = 0; //Select Async mode USART2
SPEN2 = 1; //Enable Serial port USART2
BRGH2 = 1; //Set for High Baud rate
BRG16_2 = 1;
SPBRG2 = 86; // Set up BAUD rate = 115.2, actual - 114.943 kB
SPBRGH2 = 0; // high byte set to zero
CREN2 = 1; //Rx Enable
TX9D2 = 0; //9th bit of transmitted data is always low
TX92 = 1; //Enable 9-bit transmits
RX92 = 1; //Enable 9-bit receives
ADDEN2 = 1; //enables interrupt when address bit is set
RC2IE = 1; //Rx USART2 interrupt Enable
CB = RCREG2; //3x read to clear out RX Reg and 2 byte FIFO
CB = RCREG2;
CB = RCREG2;
set_tris_a(0xFF); // all inputs
set_tris_b(0xFF); // all inputs
set_tris_c(0x80); //Set up for UART1 = HOST_PC on C7(Rx)Input and C6 (TX) and all others are outputs
set_tris_d(0); //All outputs to drive diodes and diagnostics
set_tris_e(0xFF); // all inputs
set_tris_f(0xFF); // all inputs
set_tris_g(0xFE); // all inputs except TX2
set_tris_h(0xFF); // all inputs
set_tris_j(0); // all Outputs, for later development
// setup_uart(115200, HOST_PC);
// setup_uart(115200, STB);
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
// Crive pin D0 high to turn on diode D1
output_high(PIN_D0); //Turn on D1 to signify we made it this far!!!
output_high(PIN_D1);
output_high(PIN_D2);
output_high(PIN_D3);
output_high(PIN_D4);
output_high(PIN_D5);
output_high(PIN_D6);
output_high(PIN_D7);
delay_ms(100);
output_low(PIN_D1);
output_low(PIN_D2);
output_low(PIN_D3);
output_low(PIN_D4);
output_low(PIN_D5);
output_low(PIN_D6);
output_low(PIN_D7);
Timer0_Clk = 0;
BankSwapTimer = 0;
// Interrupt Set-up
//enable_interrupts(INT_RDA);;
clear_interrupt(INT_RDA2);
enable_interrupts(INT_RDA2);
//enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
Checksum = 0;
// setup_wdt(WDT_ON); // Set up WDT for 512 x 4 msec - or 2.048 sec
// restart_wdt();
// Q set-up
maxQ = 1000;
InitQ(); //Reset circular buffer
//******************************************************************************
// Main Loop
//******************************************************************************
while (1)
{
// restart_wdt();
output_toggle(PIN_D7); //loop monitor
//When a packet is received on the tool bus, NewPacket is set.
//Process received packet and reply.
if(SWAP) // respond to 1 seconds bank swap INT0
{
output_high(PIN_D6);
SWAP = 0; // Clear INT flag
delay_us(25);
output_low(PIN_D6);
//add rest of code here...
/****** Get NEAR DATA **********************************************/
// if(SPI_BYTE) SPI_Service();
T_Buff[0] = 30; //address for SHORT SPACE
T_Buff[1] = 0; //hi byte of packet size
T_Buff[2] = 5; //low byte of packet size
T_Buff[3] = 20; //send counts
T_Buff[4] = 133; //send 133 gates
Transmit_STB(); //transmit packet over tool bus
// if(SPI_BYTE) SPI_Service();
ExpectedSize = 272; //= address echo (byte) + byte cound
// (word) + cmd echo (byte) + 266 data
// (bytes) + temp (byte) + status
// (byte) + checksum (byte) - 1
SerialError = 0;
//delay_us(250);
//Receive_STB(); //receive STB packet assume done by ISR???
BusStatus_A = SerialError;
//Save_STB(); //write packet to FIFO buffer
//After all STB transactions and Buffer
// saves are done...Xmit FIFO Up
//Xmit_ULink(); //Xmit the contents of the Data Q
//enable_interrupts(INT_EXT);
}//end of SWAP Detect
if (NewPacket)
{
Save_STB();
}
// 1x per second do diagnostic xmit, TMRO disabled for now
if (Timer0_Clk >= 100)
{// check for one second to elapse
Timer0_Clk = 0; //clear 1 second timer for next time...
//fputs( "| HI !|",HOST);
output_toggle(PIN_D0); //Toggle the D0 D1 pin pattern
rs232_errors = 0; // clear errors just to clear warning...
}
// delay_us(25); // Add arbitrarry delay to slow down the main loop to better simulate a tool controller
}//end of MAIN LOOP
}// Program end
/********************************************************************
* Transmit STB Packet *
********************************************************************/
void Transmit_STB(void)
{
CREN2 = 0; //turn off receiver
T = RCREG2; //RCREG buffer is 2 deep, 1x
T = RCREG2; //2x
T = RCREG2; //and once more with feeling....
output_high(PIN_D6);
PacketSize = make16(T_Buff[1],T_Buff[2]);
Checksum = 0;
for(RecvPointer = 1; RecvPointer < PacketSize; RecvPointer++)
{
Checksum = Checksum + T_Buff[RecvPointer];
}
T_Buff[PacketSize] = ~Checksum + 1;
//restart_wdt();
TX9D2 = 1; //set address bit
TXREG2 = T_Buff[0]; //send address
while(!TRMT2); //wait till transmitter buffer is empty
TX9D2 = 0; //clear address bit for data
for(RecvPointer = 1; RecvPointer <= PacketSize; RecvPointer++)
{
TXREG2 = T_Buff[RecvPointer]; //move byte to transmit buffer
while(!TRMT2); //wait till transmitter buffer is empty
}
CREN2 = 1; //enable receiver
output_low(PIN_D6);
}//end of Transmit_STB
[color=green][/color]
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Sep 24, 2009 5:23 am |
|
|
Your post is large and I don't really understand your problem, but here are a few thoughts:
1) Are you sure your processor is running at 40MHz?
The code is incomplete (missing #fuses) and there is the suspicious line: Code: | //Setup_Oscillator parameter not selected from Intr Oscillator Config tab |
2) You are manually configuring the outputs using set_tris(). Be aware that by default the CCS compiler will manage the TRIS registers for you unless you define '#use fast_io'.
3) Code: | set_tris_g(0xFE); // all inputs except TX2 | TX2 is at pin G1, you have made G0 an output. (0xFE == 0b1111 1110)
Tip: use binary notation instead of hex: Code: | set_tris_g(0b11111101); // all inputs except TX2 |
4) You are configuring UART2 by manually setting all register bits. You haven't posted the register declarations so we can't check, but I'm too lazy anyway. I like the CCS configuration much better. Have you tried comparing the generated code (*.lst) with your bit settings? |
|
|
NeutronJohn Guest
|
|
Posted: Thu Sep 24, 2009 2:46 pm |
|
|
Thanks for the reply.
I tried your suggestions about #use fast_io and TRIS...but had no effect.
I found my principle ISR issue was I was counting on the 9th bit to be set on the slave response. which it never is...when I clear the ADDEN2, to not expect a 9th bit set...I start getting ISRs firing...so that's one problem down
Some terms:
master = 18F8772 code I am having trouble with receiving responses in now...
Slave: same 18F8772 processor with a "slave" programmed in that DOES use the 9-bit address detect mode...has been working for many months across several PIC processors.
NOW - here's the problem that I've had all along (which you may be on to something with) I check to see if the slave response address = the address the master calls, matches...and I am never getting a match, even though I know the slave code works....
I had this routine set up initially as "in-line" code just using the RC2IF to see when the RCREG2 had a character to grab...it grabs the 1st character, but never sees a match...so in (sort of) desperation, after trying manual baud rate set-ups...I thought I'd try an ISR...well I've basically got the same problem.
So...maybe I do have a processor speed issue or baud rate set-up issue.
Not sure how far off is since I have been seeing the delay_us and other delays I use to create pulses are "close" to correct length, just have not tried to time them exactly.
I'm gonna try to send out a toggle and see how accurate they are...I've had folks tell me NEVER count on them being accurate as they are susceptible to ISRs changing their lengths,and other pitfalls, etc. so I'm gonna just use a tight main loop and a toggle...
Any other ideas welcome...this "simple" problem has cost me some DAYS now that I don't have to lose...I have project WAY overdue because of this stupidity.
Thanks again... |
|
|
|
|
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
|