LPC2148 UART1 using interrupt stop sending data after amount of data
Started by 5 years ago●5 replies●latest reply 5 years ago●171 viewsHello everyone,
I have configured the UART1 of my LPC2148 with
speed(9600 / 8bits / N parity /1bit stop) with interruption.
The UART1 connects to an ESP-01 I can send and receive
information perfectly. The problem I present is when receiving
a certain amount of data from the ESP-01, the microcontroller
for some reason stops transmitting information and I do not understand what
the reason is. below I leave the configuration and the information that I am
receiving from the ESP when receiving 6 times this frame the microcontroller
stops.
Data frame:
//----------------------------------------Data frame received---------------------
+IPD,4,346:HTTP/1.1 200 OK
Date: Sat, 04 Jan 2020 13:12:46 GMT
Server: xxxxx/x.x.xx (xxxxxx)
Vary: Accept-Encoding
Content-Length: 155
Connection: close
Content-Type: text/html; charset=UTF-8
[{"count":"6","image":"0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,"}]
OK
//-------------------------------------------------------------------------------------------
Code:
//----------------------------Structure for Data recieved------------------------------------------
typedef struct {
int in;
int out;
char buffer[400];
}p;
p *ptr2,datos_serial2;
//---------------------------Init UART1---------------------------------------------
void uart1_init(void)//9600 BAUD pclock 48MHZ
{
PCONP |= 0x00000010;/* PCRTC = 1 */
PINSEL0 |= 0x00050000; /* Enable RxD1 and TxD1*/
U1LCR=0X83; //8-data bits, 1 Stop bit, Disable Parity and Enable DLAB
U1DLL=0x38;// MULVAL = 0x5 and DIVADDVAL = 14
U1DLM=1;
U1LCR=0X03; //cleared DLAB
U1IER= 0x00000001;//Enable Interrupt
}
//---------------------------------Send Char----------------
void SendCharUART1 (char str){
U1THR = str;
while( (U1LSR & 0x40) == 0 ); /* Wait till THRE bit becomes 1 which tells that transmission is completed */
}
//--------------------------------Interrupt enable------------------------------------------------------
void UART1_Interrupt_EN(void)
{
// VICIntSelect = 0x00000000;
VICVectAddr7 = (unsigned) UART1Handler;//Vector 7
VICVectCntl7 = 0x00000020 | 7; //select UART1 interrupt as IRQ i.e vector 7
VICIntEnable |=(1UL<<7);//interrupt ena.
}
//------------------------------------------Interrupt IRQ--------------------------------------------
void UART1Handler (void) __irq
{
// /* Serial Receive Interrupt. */
char recieved;
if ((U1IIR & 0x0E) == 0x04) {
recieved=U1RBR;
ptr2 = &datos_serial2;
if(ptr2->in>=399)
ptr2->in=0;
ptr2->buffer[ptr2->in++]=recieved;
}
VICVectAddr = 0x00;
}
//-----------------------------------------Main-------------------
int main()
{
uart1_init();
UART1_Interrupt_EN();
while(1){
sendata_esp01(); //Process to send data to ESP01
delay()
//----------------- Algorithm to process the received data------------------//
Process_Datareceived();
//--------------------------------------------------------------------------------------//
}
}
A possible issue is that in your ISR you have the following:
ISR() { if ( ( IRQ_source_reg & 0x0e ) == 0x04 ) { process_receive_char; } clear_the_VIC;
}
The problem is, when you enable the RX IRQ, you also enable the the RX timeout IRQ (see the description of the RBR bit for the U1IER reg in the User manual) which has the code of 0x0c. So if that IRQ ever comes in, you will never clear it and thus will just spin in the ISR - as soon as you clear the IRQ on the VIC, you get an other one, as the UART will still assert its request line.
I'm not saying that that is the problem, but it can be if you ever miss a character. Your ISR clears only one char from the FIFO, which should be OK as long as you never disable the IRQ for more than 1 character, but if you do, then you might have that problem, so it probably is worth to take a look. Maybe something like this:
ISR() { int temp; temp = IRQ_source_reg & 0x0e; if ( temp == 0x04 || temp == 0x0c ) { while ( line_status_reg & 0x01 ) { store_receive_char_in_buffer; } } clear_the_VIC; }
In fact, since you don't enable any other interrupt, you don't even need to check what the IIR contains, it's enough if you read it, then you move to the line status reg loop:
ISR() { (void) IQR_source_reg; while ( line_status_reg & 0x01 ) { ...
What you raise is correct, I made the changes you recommended but the
problem continues. I must emphasize that upon receiving 6 continuous
data frames, the microcontroller specifically stops 6.
void UART1Handler (void) __irq{ int temp; char recieved; temp = U1IIR & 0x0e; if ( temp == 0x04 || temp == 0x0c ) { while ( U1LSR & 0x01 ) { recieved=U1RBR; ptr2 = &datos_serial2; if(ptr2->in>=399) ptr2->in=0; ptr2->buffer[ptr2->in++]=recieved; } } VICVectAddr = 0x00; }
void SendCharUART1 (char str){ U1THR = str; while( (U1LSR & 0x40) == 0 ); /* Wait till THRE bit becomes 1 which tells that transmission is completed */ }
Regards,
Do you have one or more spare port pin(s) to which you can put a scope?
You could toggle them every time you enter and leave the ISR and also every time you enter an leave the send routine. Like, setting them to 1 on entry and clear to 0 on leave. Then when your code stops, you can see whether it's stuck in one those routines.
It might be possible that your UART handler has no problems, but the rest of the code, which processes the requests and creates the response gets stuck somewhere after 6 frames received.
This port-pin toggling business is painful, but I found that it can help to solve very ugly software bugs when you have no other means of debug. Plus it needs no extra RAM, has minimal effect on timing and in general, it's the least intrusive debug tool you can have.
Thank you very much, you were correct the problem was not in the UART functions of sending or receiving. I was in a function that was overflowing an array.
A good way to find issues like this is write the simplest program you can have that (in this case) will just read the values and print them out. Basically, isolate the input and make sure it works.
A core concept is simplify, simplify, simplify. Get to the minimum program you can.