|
|
View previous topic :: View next topic |
Author |
Message |
erhane
Joined: 01 Jul 2014 Posts: 41
|
Clearing UART Buffer [SOLVED] |
Posted: Wed Jul 09, 2014 5:14 am |
|
|
Hello,
I am using dspic30f6015 in my project.
My code is mainly doing:
1_When data come to UART (RS485 half dublex) enter interrupt.
2_After interrupt occur, disabling interrupt and wait for next 7 byte.
3_After obtaining of total 8 byte data, code doing some duty.
4_When duty has finished clearing interrupt flag and enable interupt again.
Problem:
When code is doing its duty, if there is an data flow over UART even if interrupt disabled when interrupt enabled it enters interrupt.
What i want:
I just want to ignore whole data flow while UART interrupt disabled.
What i tried:
Clear_interrupt before enabling it(NOT WORKED).
Read data in UART buffer 3 times with "int a = getc();"(NOT WORKED)
What i think:
I think problem is because of even interrupt disabled buffer keeps getting data from serial line. i can not disable uart in a function. If i disable uart while code working there are problems occur enabling uart or maybe i set wrong register values in order to disable uart. Can i disable or enable uart in a while loop in main function by setting register values?
My code:
Code: |
#USE RS232(stream=RS485,UART1,baud=38400,ENABLE=PIN_G3,parity=N,bits=8,stop=1) // Set UART1 as RS485 stream
#USE RS232(stream=RS232,UART2,baud=38400,parity=N,bits=8,stop=1) // Set UART2 as RS232 stream
//
// RS485 receive byte interrupt
#INT_RDA
void isr_rs485_message()
{
// Receive the RS485 message
reg_rs485_message = 1;
}
// Main method
void main()
{
// Set I/O states of the ports
// FEDCBA9876543210
set_tris_b(0b1111111011111111);
set_tris_c(0b1111111111111111);
set_tris_d(0b1111101100111111);
set_tris_e(0b1111111110000000);
set_tris_f(0b1111111111111100);
set_tris_g(0b1111111100110011);
// Turn on debug led
output_high(LED);
output_low(RX_Disable);
output_low(LASER_FLAG);
// Enable RS485 receive byte interrupt
enable_interrupts(INT_RDA);
if(debug_mode==1)
{
output_high(RX_Disable); //Receive disabled
fprintf(RS485,"\n\n\rMODESIS DUZLEMSEL KONUMLAMA SISTEMI\n\r");
fprintf(RS485,"Konumlama Islemi Icin [0] ---- Yazma Islemi Icin[1]\n\r");
output_low(RX_Disable); //Receive enabled
}
while(true)
{
if(reg_rs485_message==1)
{
disable_interrupts(INT_RDA);
reg_rs485_message=0;
get_data();
// Enable RS232 receive byte interrupt
clear_interrupt(INT_RDA);
enable_interrupts(INT_RDA);
if(debug_mode==1)
{
output_high(RX_Disable); //Receive disabled
fprintf(RS485,"\n________________________________________________________________________\n\r");
fprintf(RS485,"\nMODESIS DUZLEMSEL KONUMLAMA SISTEMI\n\r");
fprintf(RS485,"Konumlama Islemi Icin [0] ---- Yazma Islemi Icin[1]\n\r");
output_low(RX_Disable); //Receive enabled
}
}
}
}
|
Last edited by erhane on Wed Jul 09, 2014 6:38 am; edited 1 time in total |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Jul 09, 2014 6:18 am |
|
|
A serial receive interrupt, RDA, means one, or possibly more (but only if the interrupt has been disabled for a relatively long time), characters have been received. It does not mean a message has been received, nor that the start of a message has been received.
Its best not to mess about with RDA enables. Just leave them on and deal with characters one by one in the ISR. A serial receive ISR should read the character that's just been received, store it in some buffer - circular, linear, packet based, whatever - and raise some flag if it means something special, like end of line/message/packet, which all mean something worth processing is in the buffer.
Mainline code should simply look for the flag and read from the buffer to get its data.
Too often people think the start of a line/message/packet is the important bit. No, generally its not, its the end when things have to happen. Having an ISR look for the start of a message and then read the whole message in one simply jams up the processor for the whole sending time of the message. And what happens if something goes wrong and too few characters get sent for some reason? The ISR jams up waiting, and the code effectively dies, that's what.
Instead, an ISR should always be ready to receive and deal with a character. That may be as simple as stuffing it into a buffer, or it may be as complex (relatively speaking) as running it through a packet receiving state machine which detects that framing of the data, checks for errors, including checking the CRC and so on and buffers only the actual payload of the packet.
The general rule for ISRs is: Get in quick, do the minimum necessary and get out fast. Don't hang around, don't use delays, don't wait for anything and don't print or otherwise output anything and don't fiddle around with interrupt enables unless you absolutely have to, which in almost all serial receive ISRs is never. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Jul 09, 2014 6:29 am |
|
|
let me add one comment to RF_D's EXCELLENT exposition.
The cleanest way to handle clearing the ISR buffer to simply
set the next_char_OUT pointer to the same value as
the next_char_IN pointer VAR. Never mess with the int enables!
as long as the buffer uses unsigned INT8 pointer vars, this approach can't fail. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Wed Jul 09, 2014 6:31 am |
|
|
RF_D is 100% correct AND CCS supplies a working example of how to do it !
Called ex_sisr.c, located in the examples folder.
I know it works ! Slightly modified,I have an 18F46K22 using BOTH UARTs at 115k200 for the past couple of years. No need to 'reinvent the wheel' as CCS has done it for you !!
jay |
|
|
erhane
Joined: 01 Jul 2014 Posts: 41
|
|
Posted: Wed Jul 09, 2014 6:38 am |
|
|
Thank you all. I will work on it. Your answers enlightened me. |
|
|
erhane
Joined: 01 Jul 2014 Posts: 41
|
|
Posted: Wed Jul 09, 2014 10:48 am |
|
|
i want to add something.
i am disabling interrupts because i am driving stepper motors and i have to generate steps like;
while(steps<10000)
{
output_high(pin);
delay_us(10);
output_low(pin);
steps--;
}
If i dont disable interrupts don't this step routine disturb?
What can you suggest about interrupts in pulse generate applications? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Wed Jul 09, 2014 11:29 am |
|
|
The stepper should be being driven from an interrupt.....
I've replied in your other thread about this. |
|
|
|
|
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
|