Response from at command

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Response from at command

4,135件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Mon Apr 15 10:15:07 MST 2013
Hi,
I've seen this issue before but haven't been solved yet.

When I send an AT Command to a GSM modem and waiting for a small reply (like "OK") everything is fine.
But when I expect a longer reply from the modem (like 50 characters) I cannot receive all the string.

I have tried with many types of circular buffers.
I have realised that its a matter of IRQ because its not possible to ensure the time of its arrival.

Can you propose a way to wait for the whole string to arrive and then proceed with the program flow ?

Thanks a lot.

(I use LPC1115)
0 件の賞賛
返信
19 返答(返信)

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Sun Apr 28 23:25:31 MST 2013
Hi,
Finally it worked!
Key notes:
* Big delay after the AT command.
* Enable tx irq only during expected transmision time
* and some more as shown to the code...


#define UART_BUFF_MASK  (UART_BUFF_SIZE - 1)

static uint8_t buf[128];

static volatile struct {
        uint16_t        ri, wi, ct, act;
        uint8_t         buff[UART_BUFF_SIZE];
} TxBuff, RxBuff;

#define RS485_ENABLED0
#define TX_INTERRUPT0/* 0 if TX uses polling, 1 interrupt driven. */
#define MODEM_TEST0

#define IER_RBR0x01
#define IER_THRE0x02
#define IER_RLS0x04

#define IIR_PEND0x01
#define IIR_RLS0x03
#define IIR_RDA0x02
#define IIR_CTI0x06
#define IIR_THRE0x01

#define LSR_RDR0x01
#define LSR_OE0x02
#define LSR_PE0x04
#define LSR_FE0x08
#define LSR_BI0x10
#define LSR_THRE0x20
#define LSR_TEMT0x40
#define LSR_RXFE0x80

void UART_IRQHandler (void)
{
        uint8_t iir, d;
        int i, cnt;

        for (;;) {
                iir = LPC_UART->IIR;                    /* Get interrupt ID */
                if (iir & 1) break;             /* Exit if there is no interrupt */
                switch (iir & 7) {

                case 4:                 /* Rx FIFO is filled to trigger level or timeout occured */
                        i = RxBuff.wi;
                        cnt = RxBuff.ct;
                       while (LPC_UART->LSR & 0x01) {          /* Get all data in the Rx FIFO | (LPC_UART->LSR & 0x02))*/
                        d = LPC_UART->RBR;
if (cnt < UART_BUFF_SIZE) {     /* Store data if Rx buffer is not full */
RxBuff.buff = d;
i++;
i &= UART_BUFF_MASK;
cnt++;
}

                        }
                        RxBuff.wi = i;
                        RxBuff.ct = cnt;
                        break;
                case 2:                 /* Tx FIFO gets empty */
                        cnt = TxBuff.ct;
                        if (cnt) {              /* There is one or more byte to send */
                                i = TxBuff.ri;
                                for (d = 16; d && cnt; d--, cnt--) {    /* Fill Tx FIFO */
                                        LPC_UART->THR = TxBuff.buff[i++];
                                        i &= UART_BUFF_MASK;
                                }
                                TxBuff.ri = i;
                                TxBuff.ct = cnt;
                        } else {
                                TxBuff.act = 0; /* When no data to send, next putc() must trigger Tx sequense */
                        }
                        //__disable_irq();
                        LPC_UART->IER = 0x5 ;
                        break;

                default:                /* Data error or break detected */
                        LPC_UART->LSR;
                        LPC_UART->RBR;
                        break;
                }
        }
}

void uart_init (uint32_t baudrate)
{

  uint32_t Fdiv;
  uint32_t regVal;
  NVIC_DisableIRQ(UART_IRQn);
  LPC_IOCON->PIO1_6 &= ~0x07;    /*  UART I/O config */
  LPC_IOCON->PIO1_6 |= 0x01;     /* UART RXD */
  LPC_IOCON->PIO1_7 &= ~0x07;
  LPC_IOCON->PIO1_7 |= 0x01;     /* UART TXD */

  /* Enable UART clock */
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
  LPC_SYSCON->UARTCLKDIV = 0x1;     /* divided by 1 */
  LPC_UART->LCR = 0x83;             /* 8 bits, no Parity, 1 Stop bit */
  regVal = LPC_SYSCON->UARTCLKDIV;
  Fdiv = (((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate ;/*baud rate */
  LPC_UART->DLM = Fdiv / 256;
  LPC_UART->DLL = Fdiv % 256;
  LPC_UART->LCR = 0x03;/* DLAB = 0 */
  LPC_UART->FCR = 0x07;/* Enable and reset TX and RX FIFO. */
  /* Read to clear the line status. */
  regVal = LPC_UART->LSR;

  /* Clear Tx/Rx buffers */
  TxBuff.ri = 0; TxBuff.wi = 0; TxBuff.ct = 0; TxBuff.act = 0;
  RxBuff.ri = 0; RxBuff.wi = 0; RxBuff.ct = 0;
 
  /* Ensure a clean start, no data in either TX or RX FIFO. */
// CodeRed - added parentheses around comparison in operand of &
  while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
  while ( LPC_UART->LSR & LSR_RDR )
  {
regVal = LPC_UART->RBR;/* Dump data from RX FIFO */
  }

  /* Enable Tx/Rx/Error interrupts */
  NVIC_EnableIRQ(UART_IRQn);

  LPC_UART->IER = IER_RBR | IER_RLS;/* Enable UART interrupt */
  return;
}

void setspeed (baudrate)
{
/* Enable UART clock */
  uint32_t Fdiv;
  uint32_t regVal;
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
LPC_SYSCON->UARTCLKDIV = 0x1;     /* divided by 1 */
regVal = LPC_SYSCON->UARTCLKDIV;
Fdiv = (((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate ;/*baud rate */
LPC_UART->FDR = 0;
LPC_UART->LCR = 0x83;             /* 8 bits, no Parity, 1 Stop bit */
  LPC_UART->DLL = Fdiv;                           // Baud Rate depending on PCLK
  LPC_UART->DLM = (Fdiv >> 8);                    // High divisor latch
}

uint32_t  uart_test (void)
{
        return RxBuff.ct;
}

uint8_t uart_getc (void)
{
        uint8_t data;
        int i;

        /* Wait while Rx buffer is empty */
        while (!RxBuff.ct);

        i = RxBuff.ri;                  /* Get a byte from Rx buffer */
        data = RxBuff.buff[i++];
        RxBuff.ri = i & UART_BUFF_MASK;
        RxBuff.ct--;
     
        return data;
}



void uart_putc (uint8_t d)       /* Data byte to be sent */
{
        int i;

        /* Wait for Tx buffer ready */
        while (TxBuff.ct >= UART_BUFF_SIZE) ;

        if (TxBuff.act) {
                i = TxBuff.wi;          /* Put a byte into Tx buffer */
                TxBuff.buff[i++] = d;
                TxBuff.wi = i & UART_BUFF_MASK;
                TxBuff.ct++;
        } else {
                TxBuff.act = 1;         /* Trigger Tx sequense */
                LPC_UART->THR = d;
        }
   
        LPC_UART->IER = 0x7 ;
}

void uart_puts(char *s)// Put String to UART, Require uart_putc()
{
while(*s!='\0'){uart_putc(*s);s++;}
}

void uart_gets(uint8_t *buf) {
int i,j;
i= uart_test();
for (j = 0; j < i; j++) {
buf[j] = uart_getc();
}
}

void wait(uint32_t time){
        while(time--){
        __NOP();
        }
}

void clr_buf (void){
int i;
for (i = 0; i <= 128; i++) {
buf='\0';
}
}



int start (void)
{
uart_init(UART_BAUD);
wait(1000000);

uart_puts ("AT+IFC=0,0\r\n");
wait(1000000);
uart_gets (buf);
clr_buf();

.................................
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Tue Apr 23 08:04:10 MST 2013
I suggest you read how UART drivers work. Obviously a driver will NEVER know how much data is being sent. To a well written UART driver, the amount of data is irrelevant; it just takes the data from the controller and places it into a buffer/queue/some other internal structure, and your application will then read it from there. You need to make sure your separate the UART driver from your application code.

A simple primer can be found here:
http://babbage.cs.qc.edu/courses/cs343/UART/
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Tue Apr 23 06:36:32 MST 2013
Hi,
Come on guys,

I reduce uart speed, reduce the irq handler function ... and still the same.
Has any of you tried AT commands with IRQ?

Should I use DMA ?
Or even polling but Ι don't know the length of the response characters. It varies.

Best
Theo
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Mon Apr 22 11:22:13 MST 2013
Hi,
An important think I need to say:
I put one flag for each error in the LSR. I get OE (overun errors).
Which means the the buffer is full and I loose the next character.
To mention that I write to the circular buffer inside the IRQ_Handler.

Hope that helps

Theanks again
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Mon Apr 22 10:52:56 MST 2013
Hi again,
I have spent so much time on this and still no good result.

I have realized that the continious maximum characters that I can receive is limited to 14chars.
I use FCR=0x7.
Both with and without flow control. (although only Auto RTS worked)

These are results from AT commands with long response. (ie AT+COPS? or AT+CGSN ...)
The modem I use is an Ericsson terminal GM29.

Please help

Thanks,
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Thu Apr 18 14:35:05 MST 2013
Hi,
I tried with RTS-CTS with all combinations of modem handling handshake but still no luck.

The code I'm using is the basic one.

Any more suggestions? I start running out of alternatives.

Thanks
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu Apr 18 04:29:29 MST 2013

Quote: tbelo
Hi,
I have tried to increase the FCR but with no luck. Instead it was only increasing the CTI calls at the IRQ handler.
I use 3 wires.(rx,tx,gnd)

Zero response at a similar thread didn't help me much.

Thanks,


Probably because you experts don't post your actual code.
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Thu Apr 18 04:25:30 MST 2013
Hi,
I have tried to increase the FCR but with no luck. Instead it was only increasing the CTI calls at the IRQ handler.
I use 3 wires.(rx,tx,gnd)

Zero response at a similar thread didn't help me much.

Thanks,
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by daniel.widyanto on Wed Apr 17 20:31:27 MST 2013

Quote:
The communication between the MCU and the MODEM is 2 wires only.


Few years ago, I met this person who complain that NXP MCU UART sucks. It turned out that he connects 2 wires only as well (the UART TXD and RXD), but not the GND. But I don't think that's your case here ;)

It seems like your main program is too busy to respond to UART's IRQ. Just increase the trigger level (in FCR) to 14 chars (The UART hardware has 16x8-bits FIFO). Also, move the copying part (from UART FIFO to your circular buffer) to the IRQ handler.

Just follow what Zero said in http://knowledgebase.nxp.com/showthread.php?t=3301
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Wed Apr 17 12:49:42 MST 2013
Hi again,
Actually it seems logical what happens.
The RX FIFO is 2 bytes thats why it receives ~16 characters. The rest of the characters are lost because you cannot have a pending IRQ.
The communication between the MCU and the MODEM is 2 wires only. I don't follow an async communication protocol with DSR,DTR etc.
So the modem (DCE) sends a bunch a strings and does not worry. The MCU (DTE) cannot control the modem to send 8 bytes at a time.So the rest are lost.

Is that correct you think ?

thanks
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Wed Apr 17 11:44:17 MST 2013
I send the command: "AT+CMGR=1\r"
the expected answer is: +CMGR: "REC READ","+6591xxxxx","","12/06/06,16:10:45+32"
but instead I receive: +CMGR: "REC RE

the same with similar command like "AT+COPS?\r" where I only receive the 1st 14 chars:
+COPS: 0,0,"GR

Sending these commands to the modem by hyperterminal I receive the complete string.

The IRQ Handler is fired up to 14 times even if more data have been send from the DCE. So I only receive the 1st 14 characters.

[U][B]Exactly the same issue was at: http://knowledgebase.nxp.com/showthread.php?t=3301[/B][/U]
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by micrio on Wed Apr 17 09:58:18 MST 2013
I sometimes get into the mindset of "I know that other part works so I won't
look there".   After checking the obvious problems it sounds like it is time
to check the unexpected ones.   That gets me out of trouble when it happens!
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Wed Apr 17 07:20:05 MST 2013
I know the number of characters to expect.
Its a standard reply from the AT compatible GSM modem.

Thanks
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by micrio on Wed Apr 17 07:15:32 MST 2013
You need some method to determine the actual number of characters sent
by your device.   A PC ASYNC port that sniffs the line would help, an ASYNC
data scope or a logic analyzer would do it too.

Alternatively you could write a debug routine that disabled interrupts and
polled the ASYNC port and counted the characters.

It sounds like you don't know for sure if the characters are being sent.
Until you answer that question you are shooting in the dark.

Pete.
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Wed Apr 17 06:06:03 MST 2013
Hi,
I go through debugging and the RDA handler is always fetched 15 times only! The rest of the data I expect (from the AT command response) are lost.

Thanks a lot
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by daniel.widyanto on Tue Apr 16 20:29:27 MST 2013
There's hardware FIFO in the UART. Set the FCR to trigger interrupt if that FIFO already full or reaching certain size limit.

If FIFO is full, the UART will trigger RDA interrupt (See UxIIR register). If FIFO is not empty, but not reaching the trigger level, the UART will trigger CTI interrupt (if the data already inside the FIFO for certain time).

Most people implement RDA handler, but not CTI. Hence, the data that's left in FIFO (less than FIFO trigger level) not fetched.

Basically, just read the RBR during the CTI / RDA interrupt, and put it to your circular buffer
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Tue Apr 16 07:24:57 MST 2013
Hi
Look. The problem is exactly like these ones:
http://knowledgebase.nxp.com/showthread.php?t=3301
http://knowledgebase.nxp.com/showthread.php?t=2842
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by micrio on Tue Apr 16 05:22:47 MST 2013
Do you know if the modem is sending the data?   Are you using handshaking?   Are the hardware handshake lines connected?   You could wire in an ASYNC port on a PC to snoop the data being transfered both ways.   Can you see the data using a scope?    There are lots of things that can go wrong, you have to eliminate them one by one.

Pete.
0 件の賞賛
返信

4,067件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tbelo on Mon Apr 15 23:09:17 MST 2013
Should I experiment to the UART_IRQ_Handler or to the main function ?
0 件の賞賛
返信