Transceive short message by serial port (reproduced)

xiaoxiao2021-03-06  66

Serial port connection

GSM mobile phone sends and receive short messages, how to program the implementation in the application?

Q We plan to develop a

GSM short message mode

GPS system, how to use

SMS data communication?

A First, we have to

Esti formulated

The SMS specification has aware. The specifications related to the short message transceiver we discussed have mainly include

GSM 03.38,

GSM 03.40 and

GSM 07.05. The top two focused

SMS technology implementation

(Including encoding

), The latter specified

SMS

DTE-DCE interface standard

(AT command set

).

There are three ways to send and receive

SMS information:

Block Mode, Text Mode and

PDU Mode.

Block Mode is already a former yellow flowers, and it is rarely used.

Text Mode is a plain text method that can be used in different character sets, which can also be used to send Chinese short messages, but domestic mobile phones are basically not supported, mainly for Europe and America.

PDU MODE is supported by all mobile phones, you can use any character set, which is also a default encoding method.

Text Mode is relatively simple, and we don't discuss it without custom data transmission. The content introduced below is

Implementation method for transmitting and receiving short messages under PDU MODE.

PDU string is a string

ASCII code, by '

0 '

- '

9', '

A '

- '

F 'these numbers and letters. They are

8-digit hexadecimal number, or

BCD code decimal number.

The PDU string not only contains the displayed message itself, but also contains many other information, such as

SMS service center number, target number, reply number, encoding method, and service time, etc. Send and receive

The PDU string is not exactly the same. We will use two practical examples to explain

The structure and arrangement of the PDU string.

example

1 Send:

SMSC number is

8613800250500, the other party number is

13851872468, message content is "

Hello! ". From the mobile phone

PDU string can be

08 91 68 31 08 205 05 F0 11 00 0D 91 68 31 58 81 27 64 F8 00 00 00 06 C8 32 9B FD 0E 01 control specifications, specific analysis:

Segmentation meaning

08 SMSC address information length

8-eight-bit bytes

(include

91) 91 SMSC address format

(TON / NPI) with international format numbers

(In front add)

'

68 31 08 20 05 05 F0 SMSC address

8613800250500, makeup '

F 'a number of even

11 basic parameters

(TP-MTI / VFP) Send,

TP-VP with relative format

00 message reference value

(TP-MR) 0 0D Target Address Digital Number

13 decimal numbers

(Excluding

91 and '

F '

91 Target Address Format

(TON / NPI) with international format numbers

(In front add)

'

68 31 58 81 27 64 F8 target address

(TP-DA) 8613851872468, supplement

F 'a number of even

00 protocol identification

(TP-PID) is ordinary

GSM type, point-to-point mode

00 user information encoding method

(TP-DCS) 7-bit encoding

00 validity period

(TP-VP) 5 minutes

06 user information length

(TP-UDL) actual length

6 bytes

C8 32 9B FD 0E 01 User Information

(TP-UD) "

Hello! "

example

2 Receive:

SMSC number is

8613800250500, the other party number is

13851872468, message content is "Hello

! ".

PDU string can be

08 91 68 31 08 205 05 F0 84 0D 91 68 31 58 81 27 64 F8 00 08 30 30 21 80 63 54 80 06 4F 60 59 7D 00 21 Control Specifications, Specific Analysis: Segment Meaning Description

08 address information length eight-bit bytes

(include

91) 91 SMSC address format

(TON / NPI) with international format numbers

(In front add)

'

68 31 08 20 05 05 F0 SMSC address

8613800250500, makeup '

F 'a number of even

84 basic parameters

(TP-MTI / MMS / RP) Receive, no more news, there is a reply address

0D replies address number

13 decimal numbers

(Excluding

91 and '

F '

91 Reply Address format

(TON / NPI) with international format numbers

(In front add)

'

68 31 58 81 27 64 F8 Reply Address

(TP-RA) 8613851872468, supplement

F 'a number of even

00 protocol identification

(TP-PID) is ordinary

GSM type, point-to-point mode

08 User Information Coding Method

(TP-DCS) UCS2 encoding

30 30 21 80 63 54 80 Time Stamp

(TP-SCTS) 2003-3-12 08:36:45 8 Time Zone

06 user information length

(TP-UDL) actual length

6 bytes

4F 60 59 7D 00 21 User Information

(TP-UD) "Hello

! "

If the basic parameters are the highest

(TP-RP) is

0, there is no three segments of the address. From

Short messages issued on the Internet are often this situation.

Note that the number and time representation is not in normal order, and

F 'Reduces odd numbers.

Q The above two have appeared

7-bit and

UCS2 encoding, please tell us about these coding methods.

A

In the PDU Mode, three coding methods can be used to encode the seminated content, they are

7-bit,

8-bit and

UCS2 encoding.

7-bit encoding is used to send ordinary

ASCII characters, it will

7-bit character

(The highest bit is

0) encoded

8-bit data, each

8 characters can be "compressed"

7;

8-bit encoding is usually used to send data messages, such as pictures and ringtones, etc.

UCS2 encoding for sending

Unicode characters.

User information of PDU string

(TP-UD) section maximum capacity is

140 bytes, so in these three coding mode, the maximum number of characters that can be sent is

160,

140 and

70. Here, all English letters, one Chinese character and a data byte are viewed as a character.

have to be aware of is,

PDU string user information length

(TP-UDL), which is different in various coding methods.

7-bit encoding, refers to the number of characters of the original short message, not the number of bytes encoded.

8-bit encoding is the number of bytes.

When UCS2 encodes, it is also the number of bytes, equal to twice the number of characters of the original short message. If user information

(TP-UD) There is a head

(Basic parameters

TP-UDHI is

1) In all encoding mode, user information length

(TP-UDL) is equivalent to the sum of the number of the number and the number of bytes of encoding. If used

Compression algorithm recommended by GSM 03.42

(TP-DCS high)

3-bit

001), then the length is also the sum of the byte or head length and the compression encoding after compression encoding.

The following is a specific example

7-bit encoding process. Our English SMS "

Hello! "Code:

Source string each

8 characters are divided into groups

(This example is dissatisfied

8

) Code, compressed between the characters in the group, but there is no connection between each group. use

C realization

7-bit encoding and decoding algorithms are as follows:

// 7-bit encoding

// psrc: Source string pointer

// PDST: Target Code String Pointer

// nsrclength: Source string length

// Return

: Target Code String Length

INT GSMENCODE7bit (const char * psrc, unsigned char * pdst, int nsrclength) {INT nsrc; // source string count value

INT NDST; / / Target Code String Counting Value

INT nchar; // The serial number of the character byte that is currently being processed, the range is

0-7 unsigned char nLEFT; / / Previous byte residual data

/ / Count value initialization

Nsrc = 0; ndst = 0; // Put the source string

8 bytes are divided into groups, compressed into

7 bytes

// Cycle this processing process until the source string is processed

/ / If the packet is not

8 bytes, can also handle properly

While (nsrc

3-bit

nchar = nsrc & 7; // Treat a source string for each byte

IF (nchar == 0) {// The first byte in the group, just saved, use the next byte to use

NLEFT = * psrc;} else {// group other bytes, add the right part to the residual data to get a target coded byte

* PDST = (* psrc << (8-nchar)) | NLEFT; // Save the left part of the byte, saved as residual data

NLEFT = * psrc >> nchar; // Modify the pointer and count value of the target string

PDST ; NDST ;} // Modify the pointer and count value of the source string

PSRC ; NSRC ;} // Return to the target string length

Return ndst;} // 7-bit decoding

// psrc: source code string pointer

// PDST: Target string pointer

// nsrclength: Source Code String Length

// Return

: Target string length

INT GSMDECode7bit (const unsigned char * psrc, char * pdst, int nsrclength) {int NSRC; // Source string count value

INT NDST; / / Target decoding string count value

INT NBYTE; / / The number of bytes currently being processed, the range is

0-6 unsigned char nLEFT; / / The last byte residual data

/ / Count value initialization

NSRC = 0; NDST = 0; // Group byte serial number and residual data initialization

nbyte = 0; NLEFT = 0; // Put the source data per

7 bytes are divided into groups, unzipped into

8 bytes

// Cycle the process, until the source data is processed

/ / If the packet is not

7 bytes, can also be handled correctly

While (nsrc

NLEFT = * psrc >> (7-nbyte); / / Modify the pointer and count value of the target string

PDST ; NDST ; // Modify byte count value

NBYTE ; // to a group of last bytes

IF (nbyte == 7) {// extra target decoded byte

* PDST = NLEFT; / / Modify the pointer and count value of the target string

PDST ; NDST ; // Group byte serial number and residual data initialization

NBYTE = 0; NLEFT = 0;} // Modify the pointer and count value of the source string

PSRC ; NSRC ;} * pdst = 0; // Return to the target string length

Return ndst;} It should be pointed out that

7-bit character set

The ANSI standard character set is incomplete,

0x20 The following also arranged some printable characters, but both English letters, Arabic numbers, and common symbols are the same. Use the algorithm described above to send and receive pure English short messages, the general situation should be enough. If it is French, German, Spanish, etc.

"," É "characters, then press the output of the above-mentioned output to check the table, see

The provisions of GSM 03.38.

8-bit encoding actually does not specify what specific algorithm does not need to be introduced.

UCS2 encoding is to put each character

(1-2 bytes

)according to

The provisions of ISO / IEC10646, transition to

16-bit

Unicode wide character. in

In the Windows system, especially

In 2000 / XP, you can simply call

The API function implements encoding and decoding. If there is no system support, for example, the mobile module is controlled by the microcontroller to send and receive short messages.

In the Windows environment, use

C realization

The algorithm for UCS2 encoding and decoding is as follows:

// UCS2 encoding

// psrc: Source string pointer

// PDST: Target Code String Pointer

// nsrclength: Source string length

// Return

: Target Code String Length

INT GSMENCODEUCS2 (const char * psrc, unsigned char * pdst, int nsrclength) {int NDSTLENGTH; // Unicode wide character number

Wchar wchar [128]; // unicode buffer

// String

-> Unicode string

ndstlength = :: MultibyTetowideChar (CP_ACP, 0, PSRC, NSRCLENGTH, WCHAR, 128); // High and low byte calls, output

For (int i = 0; i

* PDST = Wchar [i] >> 8; // Output low byte

* PDST = wchar [i] & 0xff;} // Return to the target coding string length return ndstlength * 2;} // uCS2 decoding

// psrc: source code string pointer

// PDST: Target string pointer

// nsrclength: Source Code String Length

// Return

: Target string length

INT GSMDECodeucs2 (const unsigned char * psrc, char * pdst, int nsrclength) {int NDSTLENGTH; // Unicode wide character number

Wchar wchar [128]; // unicode buffer

// High and low byte calls,

Unicode for (INT i = 0; I

Wchar [i] = * psrc << 8; // Lower Laying byte

Wchar [i] | = * psrc ;} // unicode string

-> String

ndstlength = :: widechartomultibyte (CP_ACP, 0, Wchar, NSRCLENGTH / 2, PDST, 160, NULL, NULL); // Output string adds an end conference

PDST [NDSTLENGTH] = '/ 0'; // Returns the length of the target string

Return NDSTLENGTH;

PDU strings need to be formatted, no direct

The user information in the PDU string decodes as a short message string because it is still a link to each other between the printable string and byte data. Circular call

SSCANF and

The Sprintf function implements this transformation. The following is provided with algorithms that do not have these functions, and they also apply to microcontrollers.

DSP programming environment.

// Printing string to convert to byte data

// Such as:

"C8329BFD0E01" -> {0xc8, 0x32, 0x9b, 0xfd, 0x0e, 0x01} // psrc: Source string pointer

// PDST: Target Data Pointer

// nsrclength: Source string length

// Return

: Target data length

INT GSMString2bytes (const char * psrc, unsigned char * pdst, int nsrclength) {for (int i = 0; i

4 bit

IF (* psrc> = '0' && * psrc <= '9') {* PDST = (* psrc - '0') << 4;} else {* pdst = (* psrc - 'a' 10) << 4;} psrc ; // low output

4 bit

IF (* psrc> = '0' && * psrc <= '9') {* pdst | = * psrc - '0';} else {* pdst | = * psrc - 'a' 10;} PSRC ; PDST ;} // Return to the target data length ReturnNSRCLENGTH / 2;} // byte data Conversion to the printable string

// Such as:

{0xC8, 0x32, 0x9b, 0xfd, 0x0e, 0x01} -> "c8329bfd0e01" // psrc: source data pointer

// PDST: Target string pointer

// nsrclength: source data length

// Return

: Target string length

INT GSMBYTES2STRING (Const unsigned char * psrc, char * pdst, int nsrclength) {const char Tab [] = "0123456789abcdef"; // 0x0-0xf character lookup table

For (int i = 0; i

4 bit

* PDST = Tab [* psrc >> 4]; // output high

4 bit

* PDST = Tab [* psrc & 0x0f]; PSRC ;} // Output string adds a end value

* PDST = '/ 0'; // Return to the target string length

Return nsrclength * 2;

The compression algorithm in GSM 03.42 has not found it so far, and we will not discuss this. If you are interested, you can study it in depth.

[related resources

] ◆

ETSI official website:

http://www.etsi.org ◆

BHW98 column:

http://www.9cbs.net/develop/author/netauthor/bhw98/------------------------------ ------------------------------------------------Initial Release :

2003-03-14 Last revision:

2003-03-26 Title

Transceive short messages through serial port

(under

BHW98 (original)

Keyword

short message

Serial port

, The core coding method of SMS, PDU, EMS Q PDU has been clear, how to implement

The AT command transmits and receives short messages?

A in the upper part, we have discussed

7-bit, 8bit and

Several UCS2

The encoding mode of the PDU user information is given. Now, key description

PDU stronger coding and decoding process, and

GSM 07.05

AT command implementation method. These are the core code of the underlying, in order to ensure the transplantability of the code, we don't have to use it as much as possible

MFC class, if necessary

ANSI C Standard Library Function.

First, define the following constants and structures:

// User information encoding method

#define GSM_7bit 0 # Define GSM_8bit 4 # define GSM_UCS2 8 // Short message parameter structure, encoding / decoding shared

// where the string is

0 end

Typedef struct {char SCA [16]; // Short Message Service Center Number

(SMSC address

CHAR TPA [16]; // Target number or reply number

(TP-DA or

TP-RA) CHAR TP_PID; // User Information Protocol Identification

(TP-PID) CHAR TP_DCS; // User Information Coding Method

(TP-DCS) Char TP_SCTS [16]; // Service Timestamp String

(TP_SCTS), used in reception

CHAR TP_UD [161]; // Original user information

(After encoding or decoding

TP-UD) CHAR INDEX; // Short message number, used in reading

} SM_PARAM; everyone has noticed

The numbers and time in the PDU string are both two-two strings. Using the following two functions can be positive and reverse transform:

/ / The normal sequence string is converted to two or two strings, if the length is odd, supplemented

'F' makes an even number

// Such as:

"8613851872468" -> "683158812764f8" // psrc: Source string pointer

// PDST: Target string pointer

// nsrclength: Source string length

// Return

: Target string length

INT GSMINVERTNUMBERS (const char * psrc, char * pdst, int nsrclength) {int ndstlength; // target string length

Char ch; // Used to save a character

// Copy string length

ndstlength = nsrclength; // Two two times

For (int i = 0; i

* PDST = * psrc ; // The character appeared after copying

* PDST = ch; // Copy the character appeared first

} // Source string length is odd?

IF (nsrclength & 1) {* (PDST-2) = 'f'; //

'F' NDSTLENGTH ; // Target string length plus

1} // Output string adds an end conference

* PDST = '/ 0'; // Return to the target string length

Return NDSTLENGTH;} // Two-two-reversed strings converted to normal sequence

// Such as:

"683158812764F8" -> "8613851872468" // psrc: Source string pointer

// PDST: Target string pointer

// nsrclength: Source string length

// Return

: Target string length

INT GSMSERIALIZENUMBERS (const char * psrc, char * pdst, int nsrclength) {int ndstlength; // target string length

Char ch; // Used to save a character

// Copy string length

NdstLength; // two two muttonback FOR (int i = 0; I

* PDST = * psrc ; // The character appeared after copying

* PDST = ch; // Copy the character appeared first

} // The last character is

Is 'f'?

IF (* (PDST-1) == 'f') {pdst-; ndstlength-; // Target string length reduction

1} // Output string adds an end conference

* PDST = '/ 0'; // Return to the target string length

Return ndstlength;} The following is

PDU stronger codec module. To simplify programming, some fields use a fixed value.

// PDU encoding, used to prepare, send short messages

// psrc: source

PDU parameter pointer

// PDST: Target

PDU string pointer

// Return

: aims

PDU string length

INT GSMENCODEPDU (const SM_PARAM * PSRC, CHAR * PDST) {INT NLENGTH; / / String length

Int ndstlength; // target

PDU string length

Unsigned char buf [256]; // internal buffer

// SMSC address information

NLENGTH = Strlen (PSRC-> SCA); // SMSC address string length

BUF [0] = (char) (NLENGTH & 1) == 0? Nlength: NLENGTH 1) / 2 1; // SMSC address information length

BUF [1] = 0x91; // fixed

: Use international format numbers

Ndstlength = GSMBYTES2STRING (BUF, PDST, 2); // Conversion

2 bytes to goals

PDU string

NDSTLENGTH = GSMINVERTNUMBERS (PSRC-> SCA, & PDST [NDSTLENGTH], NLENGTH); // Conversion

SMSC to goals

PDU string

// TPDU segment basic parameters, target address, etc.

NLENGTH = STRLEN (PSRC-> TPA); // TP-DA address string length

BUF [0] = 0x11; // is sending a text message

(TP-MTI = 01),

TP-VP with relative format

(TP-VPF = 10) BUF [1] = 0; // TP-MR = 0 BUF [2] = (char) NLENGTH; // Target Address Digital Number

(TP-DA address string real length

BUF [3] = 0x91; // fixed

: Use international format numbers

NDSTLENGTH = GSMBYTES2STRING (BUF, & PDSTLENGTH], 4); // Conversion

4 bytes to goals

PDU string

NDSTLENGTH = GSMINVERTNUMBERS (PSRC-> TPA, & PDST [NDSTLENGTH], NLENGTH); // Conversion

TP-DA to the target

PDU string

// TPDU segment protocol identification, encoding method, user information, etc. NLENGTH = Strlen (PSRC-> tp_UD); // User information string length

BUF [0] = PSRC-> TP_PID; // Protocol Identification

(TP-PID) BUF [1] = psrc-> tp_dcs; // User information encoding method

(TP-DCS) BUF [2] = 0; // Validity

(TP-VP)

5 minutes

IF (PSRC-> TP_DCS == GSM_7bit) {// 7-bit encoding method

BUF [3] = NLENGTH; / / The length of the coding

NLENGTH = GSMENCODE7BIT (PSRC-> TP_UD, & BUF [4], NLENGTH 1) 4; // Conversion

TP-DA to the target

PDU string

} Else if (psrc-> tp_dcs == gsm_ucs2) {// ucs2 encoding method

BUF [3] = GSMENCODEUCS2 (PSRC-> TP_UD, & BUF [4], NLENGTH); // Conversion

TP-DA to the target

PDU string

NLENGTH = BUF [3] 4; // Nlength is equal to this segment data length

} Else {// 8-bit encoding method

BUF [3] = gsmencode8bit (psrc-> tp_ud, & buf [4], nlength); // conversion

TP-DA to the target

PDU string

NLENGTH = BUF [3] 4; // Nlength is equal to this segment data length

} Ndstlength = gsmbytes2string (buf, & pdst [ndstlength], nlength); // Convert this data to the target

PDU string

/ / Return to the target string length

Return ndstlength;} // PDU decoding for receiving, reading short messages

// psrc: source

PDU string pointer

// PDST: Target

PDU parameter pointer

// Return

: User information string length

INT GSMDECodEpdu (const char * psrc, sm_param * pdst) {int NDstlength; // Target

PDU string length

Unsigned char TMP; // Interim byte variable

Unsigned char buf [256]; // internal buffer

// SMSC address information

GSMString2bytes (PSRC, & TMP, 2); // Take the length

TMP = (TMP - 1) * 2; // SMSC number string length

PSRC = 4; // Remove the pointer

GSMSerializenumBers (PSRC, PDST-> SCA, TMP); // Conversion

SMSC number to the target

PDU string

PSRC = TMP; / / Movement

// TPDU segment basic parameters, reply address, etc.

GSMSTRING2BYTES (PSRC, & TMP, 2); // Take basic parameters

PSRC = 2; // Remove the pointer

IF (TMP & 0x80) {// contains a reply address, retrieved the address information

GSMString2bytes (PSRC, & TMP, 2); // Take the length

IF (TMP & 1) TMP = 1; // Adjust parity PSRC = 4; // Move after the pointer

GSMSerializenumBers (PSRC, PDST-> TPA, TMP); // Take

TP-RA number

PSRC = TMP; / / Movement

} // TPDU segment protocol identification, encoding method, user information, etc.

GSMSTRING2BYTES (PSRC, (unsigned char *) & pdst-> tp_pid, 2); // Take the protocol identification

(TP-PID) PSRC = 2; // Remove the pointer

GSMSTRING2BYTES (PSRC, (unsigned char *) & pdst-> tp_dcs, 2); // Take the encoding method

(TP-DCS) PSRC = 2; // Remove the pointer

GSMSerializenumBers (PSRC, PDST-> TP_SCTS, 14); // Service Timestamp String

(TP_SCTS) PSRC = 14; // Remove the pointer

GSMSTRING2BYTES (PSRC, & TMP, 2); // User Information Length

(TP-UDL) PSRC = 2; // Remove the pointer

IF (PDST-> TP_DCS == GSM_7bit) {// 7-bit decoding

NDSTLENGTH = GSMSTRING2BYTES (PSRC, BUF, TMP & 7? (int) TMP * 7/4 2: (int) TMP * 7/4); // Format Conversion

GSmdecode7bit (buf, pdst-> tp_ud, ndstlength); // Convert to

TP-du ndstlength = TMP;} else if (pdst-> tp_dcs == GSM_UCS2) {// ucs2 decoding

ndstlength = GSMString2bytes (PSRC, BUF, TMP * 2); // Format Conversion

ndstlength = GSMDecodeucs2 (BUF, PDST-> TP_UD, NDSTLENGTH); // Convert to

TP-DU} else {// 8-bit decoding

ndstlength = GSMString2bytes (PSRC, BUF, TMP * 2); // Format Conversion

ndstlength = GSmDecode8bit (buf, pdst-> tp_ud, ndstlength); // Convert to

TP-DU} // Returns the length of the target string

Return ndstlength;}

GSM 07.05, send short messages

AT cmgs command, read short message

AT cmgr command, list short messages

AT cmgl command, delete short messages

AT cmgd command. but

The AT cmgl command can read all short messages, so we use it to read short message function, but useless

AT CMGR. Here is the implementation code for sending, reading, and deleting short messages:

// Send a short message

// psrc: source

PDU parameter pointer

Bool GsmsendMessage (const sm_param * psrc) {int npduLength; // PDU string length Unsigned char nsmsclength; // SMSC string length

INT NLENGTH; / / The data length received by the serial port

Char cmd [16]; // Command string

CHAR PDU [512]; // PDU string

CHAR ANS [128]; // Answering

NpduLength = Gsmencodepdu (PSRC, PDU); //

PDU parameters, encoding

PDU string

STRCAT (PDU, "/ X01A"); //

Ctrl-z end

GSMSTRING2BYTES (PDU, & nsmsclength, 2); // Take

PDU string

SMSC information length

NSMSCLENGTH ; // plus the length byte itself

// The length in the command does not include

SMSC information length, data byte count

Sprintf (CMD, "AT CMGS =% D / R", NPDulength / 2 - nsmsClength; // Generate Commands

WriteComm (CMD, Strlen (CMD)); // Pre-output command string

NLENGTH = Readcomm (ANS, 128); // Read answering data

/ / If you can find it

"/ r / n>" decided to success or not

IF (NLENGTH == 4 && Strncmp (ANS, "/ R / N>", 4) == 0) {WriteComm (PDU, Strlen (PDU)); // Get affirmative answer, continue to output

PDU string

NLENGTH = Readcomm (ANS, 128); // Read answering data

/ / If you can find it

" CMS Error" decided to success or not

IF (NLENGTH> 0 && Strncmp (ANS, " CMS Error", 10)! = 0) {Return True;}} Return False;} // Read short messages

// use

Cmgl instead

CMGR, read all short messages in one time

// PMSG: Short message buffer must be large enough

// Return

: Short message

INT GSMREADMESSAGE (SM_PARAM * PMSG) {INT NLENGTH; / / The data length received in serial port

INT NMSG; // short message count value

CHAR * PTR; / / internal data pointer

Char cmd [16]; // Command string

CHAR ANS [1024]; // Answering

NMSG = 0; PTR = ANS; Sprintf (cmd, "at cmgl / r"); // Generate Commands

WriteComm (CMD, Strlen (CMD)); // Output Command String

NLENGTH = Readcomm (ANS, 1024); // Read answer data

/ / If you can find it

" CMS Error" decided to success or not

IF (NLENGTH> 0 && Strncmp (ANS, " CMS ERROR", 10)! = 0) {// Loop reads each short message,

" Cmgl:"

While (ptr = strstr (PTR, " cmgl:"))! = null) {PTR = 6; // Skip

" Cmgl:" SSCANF (PTR, "% D", & PMSG-> index); // Read the serial number

Trace ("index =% d / n", pmsg-> index); PTR = strstr (PTR, "/ r / n"); // Look for a row

PTR = 2; // Skip

"/ r / n" gsmdecodepdu (PTR, PMSG); // PDU string

PMSG ; // Prepare to read a short message

NMSG ; // short message count

1}} return nmsg;} // Delete short message

// Index: short message number, from

1 start

Bool gsmdeleteMessage (const INDEX) {INT NLENGTH; / / Serial port received

Char cmd [16]; // Command string

CHAR ANS [128]; // Answering

Sprintf (CMD, "AT CMGD =% D / R", INDEX); // Generate Commands

/ / Output command string

WriteComm (cmd, strlen (cmd)); // read answering data

NLENGTH = Readcomm (ANS, 128); // According to whether it can find

" CMS Error" decided to success or not

IF (NLENGTH> 0 && Strncmp (ANS, " CMS ERROR", 10)! = 0) {Return True;} Return False;}

The AT command is used during the process.

WriteComm and

The READCOMM function, which is used to read and write serial ports, depending on the specific operating system. in

In addition to using the Windows environment

Mscomm control, as well as some ready-made serial communication classes, you can also simply call some

Windows API is implemented. The following is the use

The main code implemented by the API, pay attention to the synchronization of timeout control

(block

)mode.

// Serial port equipment handle

Handle hcomm; // Open the serial port

// pport: serial port name or device path, available

"COM1" or

"//./Com1" two ways, it is recommended to use the latter

// nbaudrate: baud rate

// nparity: parity

// NBYTESIZE: Data byte width

// nstopbits: Stop bit

Bool OpenComm (Const Char * Pport, Int NbaudRate, Int nstopbits) {DCB DCB; / / Serial Pit Control Block

CommTIMEOUTS TIMEOUTS = {// Serial port timeout control parameter 100, // read character interval timeout time

: 100 ms 1, // read the time of each character

: 1 ms (n characters

N ms) 500, // Basic

(additional

Read time

: 500 ms 1, // Time for each character during writing

: 1 ms (n characters

N ms) 100}; // Basic

(additional

Wait timeout

: 100 ms hcomm = createfile (pport, // serial port name or device path

Generic_read | generic_write, // Read and write

0, // Sharing method: exclusive

NULL, / / ​​Default security descriptor

Open_existing, // creation method

0, // Do not set file properties

NULL); // Do not need to refer to the template file

IF (hcomm == invalid_handle_value) return false; // Open serial port failed

Getcommstate (hcomm, & dcb); //

DCB dcb.baudrate = nbaudrate; dcb.bytesize = nbytesize; dcb.parity = nParity; dcb.stopbits = nstopbits; setcommstate (hcomm, & dcb); // Setting

DCB SetupComm (HCOMM, 4096, 1024); // Setting the input and output buffer size

Setcommtimeouts (hcomm, & timeouts); // Set timeout

Return True;} // Close the serial port

Bool Closecomm () {Return CloseHandle (HCOMM);} // Write serial port

// PDATA: Data buffer pointer to be written

// Nlength: The data length to be written

Void WriteComm (void * pdata, int NLENGTH) {DWORD DWNUMWRITE; / / The data length issued by the serial port

Writefile (HCOMM, PDATA, (DWORD) NLENGTH, & DWNUMWRITE, NULL);} // Read Serial Port

// PDATA: The data buffer pointer to be read

// Nlength: The maximum data length to be read

// Return

: Data length read in

INT Readcomm (void * pdata, int nlength) {dWord dwnumread; // Series received data length

Readfile (HCOMM, PDATA, (DWORD) NLENGTH, & DWNUMREAD, NULL; RETURN (Int) dwnumread;} ​​q

What questions do you need to pay attention to when communicating with your mobile phone?

Annection

The AT command is sent to the phone, it may return success or fail. For example, use

When the at cmgs command sends a short message, if it is just that the phone is ringing or talking, it will return one.

" CMS Error". Therefore, after sending the command, the response of the phone should be detected, and then reissue after failure. Moreover, since only one communication port, transmission and reception cannot be performed simultaneously.

If the serial port communication timeout control synchronization (blocking

) Mode, general practice is specially sent

/ Receive processing package in a work subline. Because there are more code, it will not be detailed here. Attached

In Demo, a complete sub-thread and send

/ Receive the source code of the application interface.

Q

Is the AT command not to support all manufacturers?

A ETSI GSM 07.05 specification until

1998 is finally formed

RELEASE version

(Ver 7.0.1), before and after, it does not rule out the manufacturers

DTE-DCE short message

The AT command has different possibilities. Several we use

PDU mode

The AT command is the basic command, from the principle, the mobile phone and

The GSM module should be supported, but there may be fine differences.

Q user information

(TP-UD) In ​​addition to short messages in the general sense, it can also be pictures and sound data. What are the norms about the phone ringtones and pictures formats?

A is a unified ringtone, picture format,

Motorola and

Ericsson, Siemens, Alcatel, etc.

EMS (Enhanced Messaging Service) standard, and

year 2002

Announced in February. These manufacturers have the same format. But another mobile phone giant

NOKIA did not participate in standard development, ringtones, and picture formats. So there is no unified specification.

EMS is actually do not transcend

GSM 07.05, just

The TP-UD data section contains a certain format. The phone ringtones, picture format of each manufacturer can check the relevant website.

Q user information

(TP-UD) Can actually be any custom data, is it?

A Yes, although there will be garbled on the phone. In this case, there is no meaning of the encoding method. But pay attention to still have to comply with the specification. For example, if specified

7-bit encoding method,

TP-UDL should be equal to the actual data length

8/7 (with the letter, not the four

). Use

SMS can transmit a variety of custom data in the application of point or multi-point to a point or more, such as

GPS information, environmental monitoring information, encrypted personal information, etc.

If you want to send a normal short message while transmitting custom data, the easiest way is to add an identification sign in front of the data, such as

"Ffff" to distinguish custom data and normal short messages.

The core coding method of Q PDU has been clear. How do I implement short messages with the AT command? A In the above, we have discussed the encoding mode of the 7-bit, 8bit, and ucs2, and give the code. Now, focus on the PDU stroner coding and decoding process, and the AT command implementation method for GSM 07.05. These are the core code of the underlying, in order to ensure the portability of the code, we don't have to use the MFC class as much as possible, use ANSI C standard library functions. First, define the following constants and structures: // User information encoding method

#define GSM_7bit 0

#define GSM_8bit 4

#define GSM_UCS2 8

// Short message parameter structure, encoding / decoding shared

// where the string ends in 0

Typedef struct {

Char SCA [16]; // Short Message Service Center Number (SMSC Address)

CHAR TPA [16]; // Target number or reply number (TP-DA or TP-RA)

Char TP_PID; // User Information Protocol Identifier (TP-PID)

CHAR TP_DCS; // User Information Coding Method (TP-DCS)

Char tp_scts [16]; // Service time stamp string (TP_SCTS), used in reception

CHAR TP_UD [161]; / / Original user information (TP-UD before code or decoding)

CHAR INDEX; // Short message number, used in reading

} SM_PARAM;

Everyone has noticed the number and time in the PDU string, both two-two strings. The following two functions can be positive and reverse transform: // The normal sequence string is converted to two two-reversed strings. If the length is odd, then add 'F' to even

// such as "8613851872468" -> "683158812764f8"

// psrc: Source string pointer

// PDST: Target string pointer

// nsrclength: Source string length

// Return: Target String Length

INT GSMINVERTNUMBERS (Const Char * PSRC, Char * PDST, INT NSRCLENGTH)

{

INT NDSTLENGTH; / / Target String Length

Char ch; // Used to save a character

// Copy string length

Ndstlength = nsrclength;

// Two two times

For (int i = 0; i

{

CH = * psrc ; // Save the first character appearing first

* PDST = * psrc ; // The character appeared after copying

* PDST = ch; // Copy the character appeared first

}

// Source string length is odd?

IF (Nsrclength & 1)

{

* (PDST-2) = 'f'; // 补 'f'

NDSTLENGTH ; // Target string length plus 1

}

// Output string adds an end conference

* PDST = '/ 0';

/ / Return to the target string length

Return ndstlength;

}

// Two-two strings are converted to a normal sequential string

// 如: "683158812764f8" -> "8613851872468"

// psrc: Source string pointer

// PDST: Target string pointer

// nsrclength: Source string length

// Return: Target String Length

INT GSMSERIALIZENUMBERS (Const Char * PSRC, Char * PDST, INT NSRCLENGTH)

{

INT NDSTLENGTH; / / Target String Length

Char ch; // Used to save a character

// Copy string length

Ndstlength = nsrclength;

// Two two times

For (int i = 0; i

{

CH = * psrc ; // Save the first character appearing first

* PDST = * psrc ; // The character appeared after copying

* PDST = ch; // Copy the character appeared first

}

// The last character is 'f'?

IF (* (PDST-1) == 'f')

{

PDST -;

ndstlength -; // Target string length minus 1

}

// Output string adds an end conference

* PDST = '/ 0';

/ / Return to the target string length

Return ndstlength;}

The following is a full string of PDUs. To simplify programming, some fields use a fixed value. // PDU encoding, used to prepare, send short messages

// psrc: Source PDU parameter pointer

// PDST: Target PDU string pointer

// Return: Target PDU Strings Length

INT GSMENCODEPDU (Const Sm_Param * Psrc, Char * PDST)

{

INT NLENGTH; / / String length

INT NDSTLENGTH; / / Target PDU String Length

Unsigned char buf [256]; // internal buffer

// SMSC address information

NLENGTH = Strlen (PSRC-> SCA); // SMSC address string length

BUF [0] = (char) (NLENGTH & 1) == 0? Nlength: NLENGTH 1) / 2 1; // SMSC address information length

BUF [1] = 0x91; // Fixed: with international format numbers

NdstLength = GSMBytes2String (buf, pdst, 2); // Convert 2 bytes to the target PDU string

NDSTLENGTH = GSMINVERTNUMBERS (PSRC-> SCA, & PDST [NDSTLENGTH], NLENGTH); // Convert SMSC to Target PDU Strings

// TPDU segment basic parameters, target address, etc.

NLENGTH = STRLEN (PSRC-> TPA); // TP-DA address string length

BUF [0] = 0x11; // Yes Send SMS (TP-MTI = 01), TP-VP with relative format (TP-VPF = 10)

BUF [1] = 0; // TP-MR = 0

BUF [2] = (char) NLENGTH; / / Target Address Digital Number (TP-DA Address String Real length)

BUF [3] = 0x91; // Fixed: with international format numbers

NDSTLENGTH = GSMBYTES2STRING (BUF, & PDSTLENGTH], 4); // Convert 4 bytes to the target PDU string

NDSTLENGTH = GSMINVERTNUMBERS (PSRC-> TPA, & PDST [NDSTLENGTH], NLENGTH); // Convert TP-DA to the target PDU string

// TPDU segment protocol identification, encoding method, user information, etc.

NLENGTH = Strlen (PSRC-> TP_UD); // The length of the user information string

BUF [0] = PSRC-> TP_PID; // Protocol Identification (TP-PID)

BUF [1] = PSRC-> TP_DCS; // User Information Coding Method (TP-DCS)

BUF [2] = 0; // Validity (TP-VP) is 5 minutes

IF (psrc-> tp_dcs == GSM_7bit)

{

// 7-bit encoding method

BUF [3] = NLENGTH; / / The length of the coding

NLENGTH = GSMENCODE7BIT (PSRC-> TP_UD, & BUF [4], NLENGTH 1) 4; // Convert TP-DA to Target PDU Strings

}

ELSE IF (psrc-> tp_dcs == GSM_UCS2)

{

// UCS2 encoding method

BUF [3] = GSMENCODEUCS2 (PSRC-> TP_UD, & BUF [4], NLENGTH); // Convert TP-DA to Target PDU Strings NLENGTH = BUF [3] 4; // Nlength is equal to this segment data length

}

Else

{

// 8-bit encoding method

BUF [3] = Gsmencode8bit (PSRC-> TP_UD, & BUF [4], NLENGTH); // Convert TP-DA to the target PDU string

NLENGTH = BUF [3] 4; // Nlength is equal to this segment data length

}

NDSTLENGTH = GSMBYTES2STRING (BUF, & PDSTLENGTH], NLENGTH); // Convert this section data to the target PDU string

/ / Return to the target string length

Return ndstlength;

}

// PDU decoding for receiving, reading short messages

// psrc: Source PDU string pointer

// PDST: Target PDU parameter pointer

// Return: User Information String Length

INT gsmdecodepdu (const char * psrc, sm_param * pdst)

{

INT NDSTLENGTH; / / Target PDU String Length

Unsigned char TMP; // Interim byte variable

Unsigned char buf [256]; // internal buffer

// SMSC address information

GSMString2bytes (PSRC, & TMP, 2); // Take the length

TMP = (TMP - 1) * 2; // SMSC number string length

PSRC = 4; // Remove the pointer

GSMSerializenumBers (PSRC, PDST-> SCA, TMP); // Convert SMSC number to target PDU string

PSRC = TMP; / / Movement

// TPDU segment basic parameters, reply address, etc.

GSMSTRING2BYTES (PSRC, & TMP, 2); // Take basic parameters

PSRC = 2; // Remove the pointer

IF (TMP & 0x80)

{

/ / Contain the reply address, retrieve the address information

GSMString2bytes (PSRC, & TMP, 2); // Take the length

IF (TMP & 1) TMP = 1; // Adjust parity

PSRC = 4; // Remove the pointer

GSMSERIALIZENUMBERS (PSRC, PDST-> TPA, TMP); // Take the TP-RA number

PSRC = TMP; / / Movement

}

// TPDU segment protocol identification, encoding method, user information, etc.

GSMString2bytes (psrc, (unsigned char *) & pdst-> tp_pid, 2); // Take the protocol identifier (TP-PID)

PSRC = 2; // Remove the pointer

GSMString2bytes (PSRC, (unsigned char *) & pdst-> tp_dcs, 2); // Take the encoding method (TP-DCS)

PSRC = 2; // Remove the pointer

GSMSerializenumBers (PSRC, PDST-> TP_SCTS, 14); // Service Timestamp String (TP_SCTS)

PSRC = 14; // Remove the pointer

GSMSTRING2BYTES (PSRC, & TMP, 2); // User Information Length (TP-UDL) PSRC = 2; // Remove

IF (PDST-> TP_DCS == GSM_7bit)

{

// 7-bit decoding

NDSTLENGTH = GSMSTRING2BYTES (PSRC, BUF, TMP & 7? (int) TMP * 7/4 2: (int) TMP * 7/4); // Format Conversion

GSMDecode7bit (buf, pdst-> tp_ud, ndstlength); // Convert to TP-DU

NDSTLENGTH = TMP;

}

Else IF (pdst-> tp_dcs == GSM_UCS2)

{

// UCS2 decoding

ndstlength = GSMString2bytes (PSRC, BUF, TMP * 2); // Format Conversion

NDSTLENGTH = GSMDECodeucs2 (BUF, PDST-> TP_UD, NDSTLENGTH); // Convert to TP-DU

}

Else

{

// 8-bit decoding

ndstlength = GSMString2bytes (PSRC, BUF, TMP * 2); // Format Conversion

NDSTLENGTH = GSMDECode8bit (buf, pdst-> tp_ud, ndstlength); // Convert to TP-DU

}

/ / Return to the target string length

Return ndstlength;

}

According to GSM 07.05, send a short message to use the AT CMGS command, read the short message with the at cmgr command, list short messages with the at cmgl command, delete the short message with the AT CMGD command. However, the AT cmgl command can read all short messages, so we use it to read the short message function without using AT CMGR. Here is the implementation code for sending, reading, and deleting short messages: // Send a short message

// psrc: Source PDU parameter pointer

Bool GsmsendMessage (const sm_param * psrc)

{

Int npduLength; // PDU string length

Unsigned char nsmsclength; // SMSC string length

INT NLENGTH; / / The data length received by the serial port

Char cmd [16]; // Command string

CHAR PDU [512]; // PDU string

CHAR ANS [128]; // Answering

npduLength = Gsmencodepdu (PSRC, PDU); // According to PDU parameters, encoded PDU strings

STRCAT (PDU, "/ x01a"); // Ended Ctrl-Z

GSMString2bytes (PDU, & nsmsclength, 2); // Take the SMSC information length in the PDU string

NSMSCLENGTH ; // plus the length byte itself

// The length in the command does not include the length of the SMSC information, with a data byte count

Sprintf (CMD, "AT CMGS =% D / R", NPDulength / 2 - nsmsClength; // Generate Commands

WriteComm (CMD, Strlen (CMD)); // Pre-output command string

NLENGTH = Readcomm (ANS, 128); // Read answering data

/ / According to the "/ R / N>" determined to be successful or not (NLENGTH == 4 && Strncmp (ANS, "/ R / N>", 4) == 0)

{

WriteComm (PDU, Strlen (PDU)); // Get affirmative answers, continue to output a PDU string

NLENGTH = Readcomm (ANS, 128); // Read answering data

/ / Determine the success of " CMS ERROR" according to Can I find it?

IF (NLENGTH> 0 && Strncmp (ANS, " CMS Error", 10)! = 0)

{

Return True;

}

}

Return False;

}

// Read short messages

// Use cmgl instead of cmgr, you can read all short messages in one time

// PMSG: Short message buffer must be large enough

// Return: Short message

INT GSMReadMessage (SM_PARAM * PMSG)

{

INT NLENGTH; / / The data length received by the serial port

INT NMSG; // short message count value

CHAR * PTR; / / internal data pointer

Char cmd [16]; // Command string

CHAR ANS [1024]; // Answering

NMSG = 0;

PTR = ANS;

Sprintf (CMD, "AT CMGL / R"); // Generate Commands

WriteComm (CMD, Strlen (CMD)); // Output Command Strings

NLENGTH = Readcomm (ANS, 1024); // Read answer data

/ / Determine the success of " CMS ERROR" according to Can I find it?

IF (NLENGTH> 0 && Strncmp (ANS, " CMS Error", 10)! = 0)

{

// Recycled each short message to " cmgl:"

While (PTR = strstr (PTR, " CMGL:"))! = null)

{

PTR = 6; // Skip " CMGL:"

SSCANF (PTR, "% D", & PMSG-> index); // Read the serial number

Trace ("INDEX =% D / N", PMSG-> index);

PTR = strstr (PTR, "/ r / n"); // Look for a row

PTR = 2; // Skip "/ R / N"

GSmDecodePdu (PTR, PMSG); // PDU string

PMSG ; // Prepare to read a short message

NMSG ; // short message count plus 1

}

}

Return NMSG;

}

// Delete short messages

// Index: Short message number, starting from 1

Bool GsmdeeeteMessage (Const Int Index)

{

INT NLENGTH; / / The data length received by the serial port

Char cmd [16]; // Command string

CHAR ANS [128]; // Answering

Sprintf (CMD, "AT CMGD =% D / R", INDEX); // Generate Commands

/ / Output command string

WriteComm (cmd, strlen (cmd)); // read answering data

NLENGTH = Readcomm (ANS, 128);

/ / Determine the success of " CMS ERROR" according to Can I find it?

IF (NLENGTH> 0 && Strncmp (ANS, " CMS Error", 10)! = 0)

{

Return True;

}

Return False;

}

The WriteComm and READCOMM functions are used above the AT command, which is used to read and write the serial port, depending on the specific operating system. In the Windows environment, in addition to the MSCOMM control, and some ready-made serial communication classes, some Windows APIs can be simply invoked. The following is the main code implemented using the API, pay attention to the synchronization (blocking) mode of the timeout control. // Serial port equipment handle

Handle HCOMM;

// Open the serial port

// pport: serial port name or device path, available "COM1" or "//./com1", recommended the latter

// nbaudrate: baud rate

// nparity: parity

// NBYTESIZE: Data byte width

// nstopbits: Stop bit

Bool OpenComm (Const Char * Pport, Int Nbaudrate, Int NPARITY, INT NBYTESIZE, INT NSTOPBITS)

{

DCB DCB; // Serial Pull

CommTIMEOUTS TIMEOUTS = {// Serial port timeout control parameters

100, // Read characters interval timeout: 100 ms

1, // read the time of each character: 1 ms (n characters for N ms)

500, // Basic (extra) Read time: 500 ms

1, // Write the time of each character: 1 ms (n characters for N ms)

100}; // Basic (additional) Writing timeout: 100 ms

hcomm = cretefile (pport, // serial port name or device path

Generic_read | generic_write, // Read and write

0, // Sharing method: exclusive

NULL, / / ​​Default security descriptor

Open_existing, // creation method

0, // Do not set file properties

NULL); // Do not need to refer to the template file

IF (hcomm == invalid_handle_value) return false; // Open serial port failed

Getcommstate (hcomm, & dcb); // Take DCB

Dcb.baudrate = NBAUDRATE

DCB.BYTESIZE = NBYTESIZE;

DCB.PARITY = NPARITY;

DCB.Stopbits = NStopbits;

Setcommstate (HCOMM, & DCB); // Set DCB

SetupComm (hcomm, 4096, 1024); // Setting the input and output buffer size

Setcommtimeouts (hcomm, & timeouts); // Set timeout

Return True;

}

// Turn off the serial port

Bool closecomm ()

{

Return CloseHandle (HCOMM);

}

// write serial port

// PDATA: Data buffer pointer to be written

// Nlength: The data length of the data to be written void writecomm (void * pdata, int NLENGTH)

{

DWORD DWNUMWRITE; / / The data length issued by the serial port

Writefile (HCOMM, PDATA, (DWORD) NLENGTH, & DWNUMWRITE, NULL

}

// Read the serial port

// PDATA: The data buffer pointer to be read

// Nlength: The maximum data length to be read

// Return: Data length actually read

Int Readcomm (void * pdata, int NLENGTH)

{

DWORD DWNUMREAD; / / The data received by the serial port

Readfile (HCOMM, PDATA, (DWORD) NLENGTH, & DWNUMREAD, NULL

Return (int) DWNumRead;

}

Q What questions need to pay attention to when using the AT command to communicate with a mobile phone? A No AT command is sent to the phone, it may return success or fail. For example, when sending a short message with the AT CMGS command, if it is just that the phone is ringing or talking, it will return a " cms error". Therefore, after sending the command, the response of the phone should be detected, and then reissue after failure. Moreover, since only one communication port, transmission and reception cannot be performed simultaneously. If the serial pass-through credit timeout control synchronization (blocking) mode, the general practice is to package the send / receive processing in a work subline. Because there are more code, it will not be detailed here. In the attached DEMO, the complete sub-thread and the source code of the application interface are included. Q Is the AT command, is it supported by all manufacturers? A ETSI GSM 07.05 specification until 1998 to form the final Release version (Ver 7.0.1), before and later, it does not rule out the possibility of different manufacturers in DTE-DCE's short message AT commands. The AT commands in several PDU patterns we use are basic commands. From the principle, each manufacturer's mobile phone and the GSM module should be supported, but there may be fine differences. Q User Information (TP-UD) In ​​addition to short messages in the general sense, it can also be pictures and sound data. What are the norms about the phone ringtones and pictures formats? A is a unified ringtone, picture format, Motorola and Ericsson, Siemens, Alcatel, and the like, and announced in February 2002. These manufacturers have the same format. But another mobile phone giant Nokia did not participate in standard development, ringtone, picture formats different from them. So there is no unified specification. EMS did not exceed GSM 07.05, just the TP-UD data section contains a certain format. The phone ringtones, picture format of each manufacturer can check the relevant website. Q User Information (TP-UD) can actually be any custom data, is it? A Yes, although there will be garbled on the phone. In this case, there is no meaning of the encoding method. But pay attention to still have to comply with the specification. For example, if the 7-bit encoding method is specified, the TP-UDL should be equal to 8/7 of the actual data length (in the one, not a round). In applications with SMS, point-to-point or multi-point to a point of data communication, various custom data, such as GPS information, environmental monitoring information, encrypted personal information, and so on. If you want to send a normal short message while transmitting custom data, the easiest way is to add an identification flag in front of the data, such as "ffff" to distinguish custom data and normal short messages.

转载请注明原文地址:https://www.9cbs.com/read-110916.html

New Post(0)