473,327 Members | 1,976 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,327 software developers and data experts.

GM862-GPS via MSP430

I'm using the telit GM862-GPS with a TI MSP430G2553 microcontroller. I can receive the debug echo from the serial communication but the device does not execute any of the AT-COMMANDs.

Hardware configuration
MCU---GSM
Rx ---- Tx
Tx ----- Rx
--------- RTS - GRD
--------- DTR - Pulled up

The voltage levels are within operating parameters.

I've played with the baud rate, every configuration I've tried ends with the same result.

I end all lines with '\r'. I've even tried:
\015
\0x0D
\0D
\0x0d
\0d
\r\n
\n\r
/r
/r/n
/n/r
<CR>
<cr>

And several other even more ridicules combinations, all to the same result, the echo.


What can I do to make this thing work?
Mar 13 '12 #1
11 4453
Banfa
9,065 Expert Mod 8TB
What do you mean by "I can receive the debug echo"? What do you send what do you receive back?

The first thing you should try with any modem is sending an "AT", it should reply with "OK". You should only be using the carriage return <CR> (ASCII 0x0D, C string "\r") to terminate your commands, using line feed <LF> (ASCII 0x0A, C string "\n") as well can confuse the issue as it is not part of the command set protocol.
Mar 13 '12 #2
I send "AT\r" and only get "AT\r" back.

Here is the UART:

Expand|Select|Wrap|Line Numbers
  1. #include "msp430g2553.h"
  2. #include "TrackingSystem.h"
  3. #include "stdlib.h"
  4.  
  5. char* rx_data;
  6. int rx_index;
  7.  
  8. int GSM_init()
  9. {
  10.     rx_index = 0;
  11.     // allocate space for 64 characters
  12.     rx_data = (char*)malloc(sizeof(char)*64);
  13.  
  14.     // Clears rx_data memory location
  15.     int i = 0;
  16.     for(;i<=64;i++)
  17.     {
  18.         *(rx_data+i) = 'x';
  19.     }
  20.  
  21.     P1DIR |= BIT5; // RESET
  22.     P2DIR |= BIT0; // ON/OFF
  23.  
  24.     P1SEL |= BIT1 + BIT2 ;    // P1.1 = RXD, P1.2=TXD
  25.     P1SEL2 |= BIT1 + BIT2 ;    // P1.1 = RXD, P1.2=TXD
  26.     UCA0CTL1 |= UCSSEL_2;    // SMCLK
  27.     UCA0BR0 = 104;            // 1MHz 6900
  28.     UCA0BR1 = 0;            // 1MHz 6900
  29.     UCA0MCTL = UCBRS2 + UCBRS0; // Modulation UCBRSx = 5
  30.     UCA0CTL1 &= ~UCSWRST;    // **Initialize USCI state machine**
  31.     IE2 |= UCA0RXIE;        // Enable USCI_A0 RX interrupt
  32.  
  33.     BIC_ON_OFF;
  34.  
  35.     GSM_Off();
  36.  
  37.     return 0;
  38. }
  39.  
  40. //=====================================================
  41. // Send char array to GSM unit
  42. // CHAR ARRAY MUST END WITH '\0'!
  43. int delay_count;
  44. void GSM_Send(char *tx)
  45. {
  46.         while (!(IFG2 & UCA0TXIFG));            // USCI_A0 TX buffer ready?
  47.  
  48.         while(*(tx)) // if not '\0'
  49.         {
  50.             LED1_TOGGLE;
  51.             UCA0TXBUF = *(tx++); // Send char
  52.  
  53.             wait_micro(x_delay);
  54.         }
  55. }
  56.  
  57. char* Rx_Get()
  58. {
  59.     rx_index = 0;
  60.     return rx_data;
  61. }
  62.  
  63. //=========================================================
  64. // Incoming GSM communication
  65. #pragma vector = USCIAB0RX_VECTOR
  66. __interrupt void USCIAB0RX_ISR(void)
  67. {
  68.     LED2_TOGGLE;
  69.     *(rx_data+rx_index) = UCA0RXBUF; // Get RXed character
  70.     rx_index++;
  71. }
  72.  
Heres the code in main.

As of right now, it is set up to run a test that varies the time between characters.

Expand|Select|Wrap|Line Numbers
  1. void TESTING()
  2. {
  3.     GSM_init();
  4.  
  5.     GSM_On();
  6.  
  7.     _BIS_SR(GIE);
  8.  
  9.     LED1_ON;
  10.     __delay_cycles(3500);
  11.  
  12.     int flag = 1;
  13.     int count = 0;
  14.     while(flag)
  15.     {
  16.         GSM_Send("\r\0");
  17.         _delay_cycles(2000);
  18.         if(!Rx_Get())
  19.             ERROR();
  20.  
  21.         GSM_Send("\r\0");
  22.         _delay_cycles(2000);
  23.         if(!Rx_Get())
  24.             ERROR();
  25.  
  26.         GSM_Send("\r\0");
  27.         _delay_cycles(2000);
  28.         if(!Rx_Get())
  29.             ERROR();
  30.  
  31.         GSM_Send("\r\0");
  32.         _delay_cycles(2000);
  33.         if(!Rx_Get())
  34.             ERROR();
  35.  
  36.         GSM_Send("AT\r\0");
  37.         _delay_cycles(10000);
  38.  
  39.         char* rx = Rx_Get();
  40.         if(*(rx+3) != 'x')
  41.             flag = 0;
  42.  
  43.         count++;
  44.         if(count==3)
  45.         {
  46.             GSM_Off();
  47.             _delay_cycles(200);
  48.             GSM_On();
  49.             count = 0;
  50.             x_delay++;
  51.             if(x_delay == 1000)
  52.             ERROR();
  53.         }
  54.     }
  55.     return 0;
  56. }
  57.  
Mar 13 '12 #3
I just noticed an error in my error checking:

if(!Rx_Get())
ERROR();

But even with this error, the test is still valid, Rx_Get() clears rx_index so if I was to recieve anything from the GM862 I will still fall out of the while loop and return 0;

Quick notes:
The '\0' is used as an end of string and does not get sent to the GM862

rx_data is initialized to all 'x'
Mar 13 '12 #4
Banfa
9,065 Expert Mod 8TB
OK receiving AT<CR> is not unexpected. Most modems default to having command echo on so you get back the command you send followed by the reply.

The full reply to AT<CR> is AT<CR>OK<CR>

You don't have to specify your strings as "AT\r\0" the zero terminator is automatically added to strings so "AT\r" suffices.

Line 40 if(*(rx+3) != 'x'), this is a very basic test where you should really be testing of the expected reply and it may not work due to buffering and other issues.

The general approach of sends a few <CR> and then and AT and seeing if you get an OK reply and if not repeating is correct, you might not want to repeat forever in production though.

However your buffering of the input from the UART could probably be better. The function Rx_Get doesn't really do anything, you are left accessing the input buffer directly but as soon as more data arrives (and a modem can send unsolicited messages) the interrupt routine will overwrite the data the program is currently accessing.

I better method is to use a ring or circular buffer (Link to wikipedia article circular buffer) and for the program to pass the a pointer to a local buffer to the Rx_Get function, the Rx_Get function then copies data out of the circular buffer and into the buffer pointed to (or an alternative is for Rx_Get to return a single character). Additionally Rx_Get diables interrupts (or specifically the UART interrupt) while it is messing around with buffer pointers ensuring that you do not have 2 threads of execution attempting to read/write the same data at the same time. This means that while the interrupt is running Rx_Get can not be running so the interrupt can access the buffer without any need for additional code. Additionally if you use a ring buffer then the code will know if there is data waiting, rather than wait for a fixed amount of time you can wait for data to have arrived, which leads onto ...


Waiting for 10000 cycles on a 16MHz micro-controller means that you have waited for 10000/16000000 = 0.000625 seconds. At 9600 baud (a common default) in that amount of time you can receive 0.000625 / (1 / 9600) = 6 bits or about 1/2 a byte taking start and stop bits into account. You need to receive 6 bytes you will need to wait something more like 0.00625 seconds or 100000 cycles (did you perhaps read 9600 baud as bytes per second instead of bits per second?).
Mar 13 '12 #5
The Rx_Get is a work in progress. The idea is to send a copy of the buffer and clear the Rx_index. I will take a look at better solutions to the buffering as soon as I can get the comunication rolling.

The '\0' is handled in
line 48 while(*(tx)) // if not '\0'

This is at the microcontroller level, makes life easier though it may not be needed.

The clock was my big mistake.
I have the clock configured to 1MHz, so it wasnt an error of calculation. In another c file, I recalibrate the clock to be the slowest possible rate, which changed my old calibration.

It took you pointing out how fast you thought my clock was going (so fast it will only catch a half of a byte) for me to realize how slow my clock was really going.

With that in mind, I performed this test:
Expand|Select|Wrap|Line Numbers
  1. while(1)
  2.     {
  3.         wait_milli(1000);
  4.         LED2_TOGGLE;
  5.         _delay_cycles(1000000);
  6.         LED2_TOGGLE;
  7.     }
Both wait and delay took one second.

I'm rerunning the test with the clock corrections as I type this. Now there is a half second delay between the '\r' and a three second delay after "AT\r".
Mar 13 '12 #6
Even with the clock correction, the device is not working.
Mar 13 '12 #7
Banfa
9,065 Expert Mod 8TB
The '\0' is handled in
line 48 while(*(tx)) // if not '\0'

This is definitely a minor side issue but worth sorting out. I fully understand that this line uses and handles the '\0' at the end of a string, what I am saying is that you do not need to explicitly put the '\0' in the string because your compiler automatically puts it in because that is how C defines strings.

If you where to look at the memory containing the string "AT\r\0" would would find it was 5 bytes long containing the values (in hex)

41 54 0D 00 00

The string contains 2 terminators the one you explicitly put in and the one the compiler implicitly put in. This is unnecessary for you code to work and you could just use the string "AT\r" which would be 4 bytes of memory containing

41 54 0D 00

Apart from using a little more memory than required and making your strings look a little messy they is however no harmful effect from implicitly putting in the extra '\0' characters.

Hmmm so I am a little perplexed as to what is actually going on with your modem communications but here are some thoughts
  • In your original code you are calling GSM_off from GSM_init, this looks strange. I notice that in you main you call GSM_init and then GSM_on but if you are configuring the Telit and then powering it off and then on (if that is what GSM_off and GSM_on does) again you will have lost your configuration and returned to power on defaults.
  • Now is the time to double check all the register addresses for the Telit and make sure you are writing the correct values to the correct addresses. If you have already double checked it then triple check it.
  • A simple confirmation of the number of characters received would probably be helpful. Initialise a global int (or unsigned) to 0 and increment it in USCIAB0RX_ISR so you can tell how many times the interrupt routine has been called and therefore how much data has been received.
  • I assume the UARTs on your micro controller only have a single byte buffer? If they have more, say a 2 byte buffer you could be missing every other byte in the received data. The micro-controller data sheet will tell you this.
  • If nothing else works then check to see if there is an errata (list of errors) for either the micro-controller or Telit (less likely). I once used a different micro-controller connected to a Telit modem which didn't work at first because there was an error in the implementation of the micro-controllers UART which meant that to receive data you actually had to read from the address of the transmit buffer. These sort of errors are not unknown.
  • If you have access to a serial line analyser or an oscilloscope then attach it to the serial lines running between the micro-controller and Telit and watch the data flow (or fail to flow).
Mar 14 '12 #8
I call GSM_Off inside of init because I want the device to reset to power up defaults. This is going to be a low powered application where the the modem will only be on three times a day. Later, I wont have to have the explicit GSM_Off, because it will be assumed to be off, but as of right now for testing, I need to always turn the device off before starting. The GSM_init sets up the microcontroller side of configuration and the defaults are assumed for the modem.

I do not know how to check the Telit registers with my setup. I must look into that.

I do have a confirmation of the number of characters received. rx_index serves that purpose. Every time that the interrupt is called, rx_index is incremented and I can view it from a debug window. This was the very first step for my program. The Rx_Get() function is set up to send a copy of the buffer to the caller and clear out the buffer (reset the index).

The buffer (UCA0RXBUF) is a single byte buffer.

There are no errors and no warnings for the microcontroller.

I will have a chance later today to check the output with a logic analyzer and oscilloscope again.
Mar 14 '12 #9
Banfa
9,065 Expert Mod 8TB
I call GSM_Off inside of init because I want the device to reset to power up defaults.
Fair enough, the power on defaults of the modem should at the very least allow the AT/OK command response to happen. However until you have the communications sorted out you may want to just turn it on and leave it on to keep things simple.

rx_index does not count the number of characters received because you keep zeroing it, you need to know if the interrupt routine is firing and if so how many times. If it isn't being called then you have a problem with your UART or Telit configuration, or possibly your hardware (tx/rx lines not correctly connected). If it is firing but you aren't receiving the expected data then you have a problem with your software buffering or possibly once again your UART configuration.

It boils down to this, it isn't working and currently there is no single reason why it isn't working there are multiple possibilities. You need to find a way of diagnosing what the exact cause is and knowing whether the interrupt routine is firing the excepted number of times or not is 1 thing that may help work out what the actual problem is.
Mar 14 '12 #10
The device is sending back exactly the same number of characters that the microcontroller sends to it. The posted code was test code after that point was considered. Here is the test code for checking the number of recieved bytes:

Expand|Select|Wrap|Line Numbers
  1.         GSM_Send("\r");
  2.         wait_milli(500);
  3.         if(!Rx_Get())
  4.             return 1;
  5.  
  6.         GSM_Send("AT\r");
  7.  
  8.         wait_milli(10000);
  9.  
  10.         while(1);
With a stop on the while(1) we can see the following:
rx_data unsigned char* 0x0202 "AT\015"
rx_index int 3

0x0202 is the location of the buffer
"AT\015" are the three chars in that location
\015 = \0x0D = '\r'

For the baud rate test:
I sent out this bit pattern: 0011 1001
which are chars '\n' and '\t'

here is the test code for baud rate:
Expand|Select|Wrap|Line Numbers
  1.     while(1)
  2.     {
  3.         GSM_Send("\n\t");
  4.         Rx_Get();
  5.     }
With this, I was able check the baud rate with a logic analyzer.
The baud rate was correct: 9600

I'm going to start from scracth again. There may be a bug deep in the system that I cant find.
Mar 14 '12 #11
Banfa
9,065 Expert Mod 8TB
Sorry I haven't been more help, I can think of some hardware issues that would cause this problem, faulty modem, tx line of the UART mistakenly connected to the RX line.

I personally would be looking for some way to verify the modem hardware independently, by connecting direct to a PC or similar, but you would need to have an RS232 line level driver chip to do that and obviously the circuitry as well.
Mar 15 '12 #12

Sign in to post your reply or Sign up for a free account.

Similar topics

14
by: Evil Bastard | last post by:
Hi all, I'm currently tackling the problem of implementing a python to assembler compiler for PIC 18Fxxx microcontrollers, and thought I'd open it up publicly for suggestions before I embed too...
13
by: john.constantine | last post by:
Hi I have this code: template<typename ClassType> struct S { template<typename FunctionType> void member() {}; };
9
by: Ralf Hildebrandt | last post by:
Hi all! First of all: I am a C-newbie. I have noticed a "strange" behavior with the standart integer multiplication. The code is: void main(void)
3
by: Ramon | last post by:
Hi all, I want to write some data on the EEPROM of a PIC 16F877 microcontroller via serial port rs232. What library can I use with a gcc compiler to perform this ? Thank you very much ! ...
5
by: aekalman | last post by:
Hi all. I'm revising part of a large body of code that runs on a variety of very different targets, and one of the things I'd like to do is move away from certain "#define'd types" in favor of...
12
by: Michael | last post by:
In the below example, I beleive that the char array buffer should only occupy 40 bytes of the stack within the inner braces. However the compiler seems to use 40 bytes of the stack througout the...
0
by: Chris Stephens | last post by:
Low Cost C Compilers ------------------------------------ HI-TECH Software's C compilers are now available to support the ARM, dsPIC, msp430, 8051, PIC 10 to 17, PIC 18 as well as many other...
40
by: Dave Hansen | last post by:
Please note crosspost. Often when writing code requiring function pointers, it is necessary to write functions that ignore their formal parameters. For example, a state machine function might...
6
by: Simon Walsh | last post by:
I'm an Electronics student in college and I'm currently working on a project. I was given a circuit diagram for my project, from which I had to design a printed circuit board to be sent off and...
0
by: Blubaugh, David A. | last post by:
To All, I was wondering if anyone has ever worked on developing a project for Python, where the Python and Numpy script code could then be generated into either C or assembly source for the...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.