uint16_t init_serial_port(char *port_name)
This function configures the specified serial port. Under Windows.uint16_t puts_serial(uint8_t *buffer, uint16_t size)
And this one writes a string of bytes to this port.gets_serial(uint8_t *buffer, uint16_t size)
This, respectively, reads a string of bytes from the serial port.init_gprs() & stop_gprs()
The GSM module is initialized and cut down accordingly.uint16_t connect_gprs(uint8_t index, uint8_t mode, char *address, char *port)
Establishes a connection to the server. It is worth noting that the module can work with TCP and UDP protocols both as a client and as a client. A maximum of 8 simultaneous connections is supported.uint16_t close_gprs(uint8_t index)
Closes the specified connection.uint16_t send_gprs(uint8_t index, uint8_t *buffer, uint16_t size)
Send a message through the specified connection.uint16_t recv_gprs(uint8_t index, uint8_t *buffer, uint16_t size)
Receive message. Non-blocking function, which means it will not wait for data to appear in the stream, but will return control if there is nothing to receive. It is worth noting that this behavior is easier to implement than blocking. uint16_t init_serial_port(char *port_name) { COMMTIMEOUTS timeouts; DCB parameters; int result; serial_port_handle = CreateFile(port_name, // "\\\\.\\COMx" GENERIC_READ | GENERIC_WRITE, 0, // NULL, OPEN_EXISTING, 0, NULL); if (serial_port_handle == INVALID_HANDLE_VALUE) { printf("Error opening a serial port!\n"); return 1; } // timeouts.ReadIntervalTimeout = 100; // timeouts.ReadTotalTimeoutMultiplier = 0; // , // timeouts.ReadTotalTimeoutConstant = 1000; // , , . timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 1000; result = SetCommTimeouts(serial_port_handle, &timeouts); if (result == 0) { printf("Error setting timeouts for serial port!\n"); close_serial_port(); return 1; } // - // , , 1 -. memset(¶meters,0,sizeof(parameters)); parameters.DCBlength = sizeof(DCB); GetCommState(serial_port_handle, ¶meters); parameters.BaudRate = (DWORD)BAUD_RATE; parameters.ByteSize = 8; parameters.Parity = NOPARITY; parameters.StopBits = ONESTOPBIT; parameters.fAbortOnError = TRUE; parameters.fDtrControl = DTR_CONTROL_DISABLE; parameters.fRtsControl = RTS_CONTROL_DISABLE; parameters.fBinary = TRUE; parameters.fParity = FALSE; parameters.fOutX = FALSE; parameters.fInX = FALSE; parameters.XonChar = (uint8_t)0x00; parameters.XoffChar = (uint8_t)0xff; parameters.fErrorChar = FALSE; parameters.fNull = FALSE; parameters.fOutxCtsFlow = FALSE; parameters.fOutxDsrFlow = FALSE; parameters.XonLim = 128; parameters.XoffLim = 128; result = SetCommState(serial_port_handle, ¶meters); if (result == 0) { printf("Error setting serial port parameters!\n"); close_serial_port(); return 1; } return 0; }
"AT\r"
, which allows the module to automatically adjust the baud rate on the serial port. The answer that can be obtained after this from the port will look like "AT\r\r\nOK\r\n"
.
"\r"
. In response, the module will transmit a string of characters consisting of two parts — a command to which the module responds with a response separated by the "\ r \ r \ n" characters, terminated by the characters "\r\n"
. To make it easier to parse the answers, I created a macro that sets a pointer to the beginning of the response in the receive buffer. If you want to output the answer to the console, you need to add a null character to the end of the received message.
void at_send(char *cmd, uint16_t size) { uint16_t result; cmd[size - 1] = '\r'; result = puts_serial(cmd, size); return; } uint16_t at_recv(uint8_t *buffer, uint16_t size) { uint16_t result; result = gets_serial(buffer, size); return result; }
"AT+CPIN=pin-code"
As it is easy to guess, this command unlocks the SIM card by entering the pin code. To check if a pin is required, you can use the command "AT+CPIN?"
."AT+CREG?"
This command returns the registration status of the module to the network. It is necessary to perform it until the module answers that it is registered on the network."AT+CGATT=1"
Forces the module to connect to GPRS. To check if it is connected, use the command "AT+CGATT?"
."AT+CIPRXGET=1"
Enables manual retrieval of data transmitted over a connection. By default, this option is disabled and data is transferred to the serial port immediately after it is received. This is not very convenient, although not critical - you can configure the module so that, along with the data, it also sends IP headers by which you can determine who the packet was from. I decided that it was easier to get data manually and I was not mistaken. As I understand it, this command is perceived only by GSM-modules SIM.COM."AT+CIPMUX=1"
By default, the module can establish only one connection. This option enables the ability to create multiple connections. Sending and receiving data will differ by only one parameter - the connection index."AT+CSTT="internet""
APN - Access Point Name, the name of the access point for GPRS. For my provider it looks that way."AT+CIICR"
Establishes a GPRS wireless connection. It may take some time, so you need to run it in a loop and check the answer."AT+CIFSR"
Returns the IP address of the module. I use it to check if the module is connected to the Internet."AT+CDNSCFG="8.8.8.8","8.8.4.4""
This command sets the DNS servers that the module will use."AT+CIPSTATUS"
In addition to connection status data, this command provides information on whether the module is ready to establish connections. So you need to check her answer."AT+CIPSTART=index,"mode","address","port""
.
index
indicates the serial number of the connection, can take values ​​from 0 to 7.mode
defines the protocol to be used by the connection. May be “TCP” or “UDP”.address
specifies the server address. If the DNS server was specified during the configuration, then you can use both the IP address and the domain name.port
specifies the server port to connect to."AT+CIPUDPMODE"
. For details, refer to the documentation.
"OK"
after a short period of time, you can get one of three answers:
"index,ALREADY CONNECT"
this means that the connection with the specified index is already established and it is worth looking for it."index,CONNECT OK"
everything is obvious here."index,CONNECT FAIL"
means that there are problems with establishing a connection."AT+CIPCLOSE=index"
. To disconnect all connections and deactivate the GPRS interface, use the "AT+CIPSHUT"
.
"AT+CIPSEND=index,length"
, where index
indicates the connection over which data is to be sent, and length
specifies the length of the data packet. By the way, you can find the MTU for each connection using the command "AT+CIPSEND=?"
.
">"
prompt, after which you need to send data to the serial port. As soon as the module receives a number of bytes equal to length
, it will say something like "index,SEND OK"
. In general, you can not use the length
parameter, however, in this case, the end of the data packet should be indicated explicitly with the 0x1A
symbol, in the terminal the combination Ctrl + Z. This option is obviously not suitable for transmitting arbitrary data.
"+CIPRXGET:1,index\r\n"
to the serial port. I honestly do not know what unit means, because this function of the module is documented rather weakly, but in my case it appears in all messages about the reception of a packet.
"\r\r\n"
, this did not bother me in any way. So the data reception function was implemented quite simply.
"AT+CIPRXGET=2,index,length"
. Two means reception mode, in this case the bytes are simply poured into the serial port. You can also set to receive data in the form of HEX-text, apparently for the sake of preventing conflicts with software flow control . I did not need this, because I do not use flow control at all. The length
parameter specifies the size of the data packet that we wish to receive at one time.
"+CIPRXGET:2,index,received,excess\r\n__DATA__\r\nOK\r\n"
. The received
field will contain the number of bytes in the __DATA__
data __DATA__
, and the excess
field will contain the number of bytes waiting for their turn in the module's buffer. So if the received
field is zero, you can declare with a clear conscience that there is nothing to receive. Actually, using this, I implemented a non-blocking function for receiving data.
Source: https://habr.com/ru/post/119030/