Atmel website | ARM Community | AVR freaks | Technical Support
Banner
 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 23 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: USART and CRLF
PostPosted: Wed May 30, 2012 1:58 am 
Offline

Joined: Sat Oct 30, 2010 6:04 pm
Posts: 784
The Lynch PDF does go off into some more complex areas, and is tailored to the SAM7.

Lets start with some simpler polling code that sends some characters or strings.

Code:
void Send_Char(char c)
{
  while((pUsart0->US_CSR & AT91C_US_TXRDY) == 0);
  pUsart->US_THR = c;
}

void Send_String(char *s)
{
  while(*s)
  {
    while((pUsart0->US_CSR & AT91C_US_TXRDY) == 0);
    pUsart->US_THR = *s++;
  }
}

Send_String("Hello World!\r\n");


A more complex approach would be to make some FIFO buffers, and put the output data into one, and use the interrupt routine to send the characters as the USART consumes them, and read the incoming data and write that into the other FIFO.


Top
 Profile  
 
 Post subject: A
PostPosted: Thu May 31, 2012 12:40 pm 
Offline

Joined: Sat May 05, 2012 10:47 am
Posts: 32
Hi, and thanks a lot for your answer.
I am using a function made by the provider.

Code:
unsigned char USART_WriteBuffer(
    AT91S_USART *usart,
    void *buffer,
    unsigned int size)
{
    // Check if the first PDC bank is free
    if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {

        usart->US_TPR = (unsigned int) buffer;
        usart->US_TCR = size;
        usart->US_PTCR = AT91C_PDC_TXTEN;

        return 1;
    }
    // Check if the second PDC bank is free
    else if (usart->US_TNCR == 0) {

        usart->US_TNPR = (unsigned int) buffer;
        usart->US_TNCR = size;

        return 1;
    }
    else {

        return 0;
    }
}



I am writing in this buffer in my main just to test:
USART_WriteBuffer( pUSART0, "ATI", 3);

Normally, I would obtain the reference ID of my GSM module.

For the reception, I have based the code on the one for the GPS module.
Code:
void Usart0IrqHandler (void)
{
  volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure
  // determine which interrupt has occurred
  // assume half-duplex operation here, only one interrupt type at a time
  if ((pUsart0->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY)
  {
    char ch;

  // we have a receive interrupt,
  // remove it from Receiver Holding Register and place into buffer[]

    ch = pUsart0->US_RHR;

    if (ch == 'A') // Resync line
      nChars = 0;

    Buffer[nChars++] = ch; // Store char and advance

    if (nChars >= sizeof(Buffer)) // Enough to hold the biggest NMEA sentence, YMMV
      nChars = 0; // Wrap

   
   
    if (ch == 0x0D) // CR, we ignore LF
    {
      Buffer[nChars - 1] = 0; // Place a NUL so C string functions actually work

      // Should check for the right AT sentence here, and perhaps parse it properly       
      if ( (Buffer[0] == 'A') && (Buffer[1] == 'T'))
      { 
        for(int i = 0 ; i <= 100 ; i++){
          gsm_data[i]= Buffer[i];
        }
          flag_gsm = 1;
      }
     
      nChars = 0; // reset
    }
  }
}


The problem is that I cannot find the end of transmit character for the received data.
Otherwise, when I am debugging (I have commented most of the handler code, I just keep the " Buffer[nChars++] = ch;" and the condition to enter in the loop ) my buffer of reception conatins "ATI" and not the identification number...
I have tried with AT+ATI, AT+ATI;. I do not really understand the syntax written in the AT commands pdf. I have also had a look on http://olimex.wordpress.com/tag/gsm/
and apparently it is quite easy, but unfortunately, I always receive the data I have sent.


Top
 Profile  
 
 Post subject: Re: USART and CRLF
PostPosted: Thu May 31, 2012 3:24 pm 
Offline

Joined: Sat May 05, 2012 10:47 am
Posts: 32
Ok, it is better now, I can send commands.
The gsm mod did not understand because the message must end by CRLF.
So I have created a function :
Code:
void send_gsm_command(const char *command)
{
        int i = 0;
        int lg = strlen(command);
        char buf[10];
        for (i =0 ; i< lg;i++){
      buf[i] = command[i];
   }
   buf[i]='\r';
   buf[i+1] ='\n';
        USART_WriteBuffer( AT91C_BASE_US0, buf,(i+1) );
}


I am now able to send commands, and the GSM returns me data.
I now have to do the reception handler. It will be more complicated than before because the frames are all different. I have to find something they have in commun.


Top
 Profile  
 
 Post subject: Re: USART and CRLF
PostPosted: Thu May 31, 2012 3:47 pm 
Offline

Joined: Sat Oct 30, 2010 6:04 pm
Posts: 784
You need to think about the receive interrupt some more. AT commands are not required to echo, and the responses typically won't start with anything you can sync on. You need to store the data into a buffer, and then parse it. ie break it down, and identify responses like "OK", "ERROR", "NO CARRIER", etc. Don't try to decode it under the interrupt routine.

Why would you not use something like
USART_WriteBuffer( pUSART0, "ATI\r\n", 5); or frankly something that computes strlen() automatically.


Top
 Profile  
 
 Post subject: Re: USART and CRLF
PostPosted: Thu May 31, 2012 6:06 pm 
Offline

Joined: Sat May 05, 2012 10:47 am
Posts: 32
Ok I see. I fill in my buffer but how do I know that I have to stop and parse?


Top
 Profile  
 
 Post subject: Re: USART and CRLF
PostPosted: Fri Jun 01, 2012 9:39 pm 
Offline

Joined: Sat May 05, 2012 10:47 am
Posts: 32
Hi,
to make my gsm mod work, I used the usart used by my gps mode. It worked very well. But now I would like to use both of them. So I have connected my gsm mod on the USART2 (UEXT connector) and I have adapted from the Usart0 Init program to init the Usart2. Unfortunately, the gsm mod does not work at all and does not enter in the interruption.

Here is my Usart 0 code:
Code:
#include <board.h>
#include "irq/irq.h"
#ifndef AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
// Interrupt is internal and uses a logical 1 level.
#define AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE
#endif

void Usart0IrqHandler(void);


// *******************************************************
// External Globals
// *******************************************************
extern char Buffer_gps[]; // holds received characters
extern unsigned long nChars_gps; // counts number of received chars
extern char *pBuffer_gps; // pointer into Buffer
// *******************************************************
// Function Prototypes
// *******************************************************

void InitUSART0(void) {
// enable the usart0 peripheral clock
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
pPMC->PMC_PCER = (1<<AT91C_ID_US0); // enable usart0 peripheral clock
// set up PIO to enable USART0 peripheral control of pins
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOB; // pointer to PIO data structure
pPIO->PIO_PDR = AT91C_PB5_RXD0 | AT91C_PB4_TXD0;
pPIO->PIO_BSR = AT91C_PIO_PB5 | AT91C_PIO_PB4;
pPIO->PIO_ASR = 0; // peripheral A function set to "no effect"
// set up the USART0 registers
volatile AT91PS_USART pUSART0 = AT91C_BASE_US0; // create a pointer to USART0 structure

pUSART0->US_CR = AT91C_US_RSTRX | // reset receiver
AT91C_US_RSTTX | // reset transmitter
AT91C_US_RXDIS | // disable receiver
AT91C_US_TXDIS; // disable transmitter

pUSART0->US_MR = AT91C_US_PAR_NONE | // no parity
0x3 << 6 |// 8-bit characters
AT91C_US_NBSTOP_1_BIT;  // 1 stop bit

pUSART0->US_IER = 0x00; // no usart0 interrupts enabled (no effect)
pUSART0->US_IDR = 0xFFFF; // disable all USART0 interrupts
pUSART0->US_BRGR = 0x143; //FOR GPS // 19200 = 0x143; // CD = 0x139 = 9600 (313 from above calculation) FP=0 (not used)
//pUSART0->US_BRGR = 0x35;//115200 FOR GSM
pUSART0->US_RTOR = 0; // receiver time-out (disabled)
pUSART0->US_TTGR = 0; // transmitter timeguard (disabled)
pUSART0->US_FIDI = 0; // FI over DI Ratio Value (disabled)
pUSART0->US_IF = 0; // IrDA Filter value (disabled)

// Set up the Advanced Interrupt Controller (AIC) registers for USART0
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // pointer to AIC data structure
pAIC->AIC_IDCR = (1<<AT91C_ID_US0); // Disable USART0 interrupt in AIC
pAIC->AIC_SVR[AT91C_ID_US0] = (unsigned int)Usart0IrqHandler;// Set the USART0 IRQ handler address in AIC Source
 // Vector Register[6]
pAIC->AIC_SMR[AT91C_ID_US0] =(AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x4 ); // Set the interrupt source type(level-sensitive) and
 // priority (4) in AIC Source Mode Register[6]
pAIC->AIC_IECR = (1<<AT91C_ID_US0); // Enable the USART0 interrupt in AIC
// enable the USART0 receiver and transmitter
pUSART0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
// enable the USART0 receive interrupt
pUSART0->US_IER = AT91C_US_RXRDY; // enable RXRDY usart0 receive interrupt
pUSART0->US_IDR = ~AT91C_US_RXRDY; // disable all interrupts except RXRDY
// set up buffer pointer and character counter
pBuffer_gps = &Buffer_gps[0];
nChars_gps = 0;
// enable IRQ interrupts
IRQ_EnableIT(AT91C_ID_US0);//enableIRQ();
// at this point, only the USART0 receive interrupt is armed!
}




and here is the Usart 2 code:
Code:
#include <board.h>
#include "irq/irq.h"
#ifndef AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
// Interrupt is internal and uses a logical 1 level.
#define AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE
#endif

void Usart2IrqHandler(void);


// *******************************************************
// External Globals
// *******************************************************
extern char Buffer_gsm[]; // holds received characters
extern unsigned long nChars_gsm; // counts number of received chars
extern char *pBuffer_gsm; // pointer into Buffer
// *******************************************************
// Function Prototypes
// *******************************************************

void InitUSART2(void){
// enable the usart2 peripheral clock
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
pPMC->PMC_PCER = (1<<AT91C_ID_US2); // enable usart2 peripheral clock
// set up PIO to enable USART2 peripheral control of pins
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOB; // pointer to PIO data structure
pPIO->PIO_PDR = AT91C_PB9_RXD2 | AT91C_PB8_TXD2;
pPIO->PIO_BSR = AT91C_PIO_PB9 | AT91C_PIO_PB8;
pPIO->PIO_ASR = 0; // peripheral A function set to "no effect"
// set up the USART2 registers
volatile AT91PS_USART pUSART2 = AT91C_BASE_US2; // create a pointer to USART0 structure

pUSART2->US_CR = AT91C_US_RSTRX | // reset receiver
AT91C_US_RSTTX | // reset transmitter
AT91C_US_RXDIS | // disable receiver
AT91C_US_TXDIS; // disable transmitter

pUSART2->US_MR = AT91C_US_PAR_NONE | // no parity
0x3 << 6 |// 8-bit characters
AT91C_US_NBSTOP_1_BIT;  // 1 stop bit

pUSART2->US_IER = 0x00; // no usart2 interrupts enabled (no effect)
pUSART2->US_IDR = 0xFFFF; // disable all USART2 interrupts
//pUSART0->US_BRGR = 0x143; //FOR GPS // 19200 = 0x143; // CD = 0x139 = 9600 (313 from above calculation) FP=0 (not used)
pUSART2->US_BRGR = 0x35;//115200 FOR GSM
pUSART2->US_RTOR = 0; // receiver time-out (disabled)
pUSART2->US_TTGR = 0; // transmitter timeguard (disabled)
pUSART2->US_FIDI = 0; // FI over DI Ratio Value (disabled)
pUSART2->US_IF = 0; // IrDA Filter value (disabled)

// Set up the Advanced Interrupt Controller (AIC) registers for USART2
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // pointer to AIC data structure
pAIC->AIC_IDCR = (1<<AT91C_ID_US2); // Disable USART2 interrupt in AIC
pAIC->AIC_SVR[AT91C_ID_US2] = (unsigned int)Usart2IrqHandler;// Set the USART0 IRQ handler address in AIC Source
 // Vector Register[6]
pAIC->AIC_SMR[AT91C_ID_US2] =(AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x4 ); // Set the interrupt source type(level-sensitive) and
 // priority (4) in AIC Source Mode Register[6]
pAIC->AIC_IECR = (1<<AT91C_ID_US2); // Enable the USART2 interrupt in AIC
// enable the USART2 receiver and transmitter
pUSART2->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
// enable the USART2 receive interrupt
pUSART2->US_IER = AT91C_US_RXRDY; // enable RXRDY usart2 receive interrupt
pUSART2->US_IDR = ~AT91C_US_RXRDY; // disable all interrupts except RXRDY
// set up buffer pointer and character counter
pBuffer_gsm = &Buffer_gsm[0];
nChars_gsm = 0;
// enable IRQ interrupts
IRQ_EnableIT(AT91C_ID_US2);//enableIRQ();
// at this point, only the USART2 receive interrupt is armed!
}


//------------------------------------------------------------------------------
/// Sends the contents of a data buffer through the specified USART peripheral.
/// This function returns immediately (1 if the buffer has been queued, 0
/// otherwise); poll the ENDTX and TXBUFE bits of the USART status register
/// to check for the transfer completion.
/// \param usart  Pointer to an USART peripheral.
/// \param buffer  Pointer to the data buffer to send.
/// \param size  Size of the data buffer (in bytes).
//------------------------------------------------------------------------------
unsigned char USART_WriteBuffer(
    AT91S_USART *usart,
    void *buffer,
    unsigned int size)
{
    // Check if the first PDC bank is free
    if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {

        usart->US_TPR = (unsigned int) buffer;
        usart->US_TCR = size;
        usart->US_PTCR = AT91C_PDC_TXTEN;

        return 1;
    }
    // Check if the second PDC bank is free
    else if (usart->US_TNCR == 0) {

        usart->US_TNPR = (unsigned int) buffer;
        usart->US_TNCR = size;

        return 1;
    }
    else {

        return 0;
    }
}


void send_gsm_command(const char *command)
{
        char buf[20];
        int i = 0;
        for (i =0 ; i< strlen(command);i++){
      buf[i] = command[i];
   }
   buf[i]='\r';
   buf[i+1] ='\n';
        USART_WriteBuffer( AT91C_BASE_US2, buf,(i+1) );
}



The interrupt handler for the gsm mod is like that:
Code:
void Usart2IrqHandler (void)
{
  volatile AT91PS_USART pUsart2 = AT91C_BASE_US2; // create a pointer to USART0 structure
  // determine which interrupt has occurred
  // assume half-duplex operation here, only one interrupt type at a time
  if ((pUsart2->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY)
  { ... ...

But I never enter into it.
I am quite stuck with this problem. Do you have any idea?
Thanks a lot in advance.

Arnaud


Top
 Profile  
 
 Post subject: Re: USART and CRLF
PostPosted: Fri Jun 01, 2012 10:28 pm 
Offline

Joined: Sat Oct 30, 2010 6:04 pm
Posts: 784
Well send_gsm_command is broken. You can't dispatch a local buffer on the stack to a DMA transfer and then leave the subroutine. You don't check if the send succeeds, and you don't send the right number of characters.

This might work better :

Code:
void send_gsm_command(const char *command)
{
    while(USART_WriteBuffer( AT91C_BASE_US2, command, strlen(command) ) == 0);
    while(USART_WriteBuffer( AT91C_BASE_US2, "\r\n", 2 ) == 0);
}


I'm really not looking to code a solution.


Top
 Profile  
 
 Post subject: Re: USART and CRLF
PostPosted: Fri Jun 01, 2012 10:43 pm 
Offline

Joined: Sat May 05, 2012 10:47 am
Posts: 32
Thank you for your answer. In USART_WriteBuffer, it is not a constant so I just wrote
void send_gsm_command( char *command) ...

Unfortunately, it does not change anything.
I think there is a more important problem. When I connect the gsm mod to the board, it is in failure mode.
There is a red led flashing slowly when it is connected to the GSM network. And it works, but once I connect it on the board and run the code, this red led is flashing twice and faster.
It worked when I used the other USART port but not any more on the USART2 port.
I do not understand because the itinialization is the same, and the pins are correct...


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page Previous  1, 2

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


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 post attachments in this forum

Search for:
Jump to: