Как создать AT Commands Parser в C, чтобы получить входящую строку из USART1?

Вопрос:

Я хочу получить строку из USART1 из STM32VLDiscovery (STM32F100X4) и написать AT Parser из строки, полученной из USART1.

Ниже приведена концепция, которую я разработал, но я не уверен, правильна она или нет.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "dosomethinga.h"

void dosomethingB();
void GET_AT_COMMAND(char*);
void takecommand(char *, char *);
int quit;


int main()
{   char buff[15];
char command = '\0';
quit = 0;

while(!quit)
{
printf("Enter your command: ");
scanf("%s", &buff);

if (buff[0] == 'A' && buff[1] == 'T' && buff[2] == '+')
{
GET_AT_COMMAND(buff);
}

}
}

void dosomethingB()
{
printf("dosomethingB called \n");
}

void GET_AT_COMMAND(char *text)
{
int command;
char temp[10] = "";

/*if(text[3] == 'A')
command = 1;

else if(text[3] == 'B')
command = 2;

else if(text[3] == 'Z')
command = 3;
*/

takecommand(text,temp);

if (strcmp(temp, "CALLA") == 0)
command = 1;

if (strcmp(temp, "CALLB") == 0)
command = 2;

if (strcmp(temp, "Z") == 0)
command = 3;

switch(command)
{
case 1:
dosomethingA();
break;

case 2:
printf("herehere.... \n");
dosomethingB();
break;

case 3:
printf("Exiting program.... \n");
quit = 1;
break;


default:
printf("Nothing to do here \n");
}
}

void takecommand(char *mycmd, char *hold)
{
int i;
for(i = 0; i < 10 ; i++)
{
hold[i] = mycmd[i+3];
}
}

Может ли кто-нибудь объяснить шаги, которые я должен сделать? Благодарю.

Лучший ответ:

В основном вы должны ждать внимания “AT” от входа и игнорировать что-либо перед ним. Например, входы “XYZATZ\r” и “AaatZ\r” должны обрабатываться как команда “ATZ”. Также может быть короткая пауза между “A” и “T” (и всеми остальными символами команд), потому что человек может набирать эти команды.

По умолчанию все команды заканчиваются символом “\ r”.

Подробнее о командах AT из документации ITU-T. Например, из стандарта V.250.

Вероятно, есть много альтернативных способов реализации этого. Лучшая альтернатива зависит от ваших потребностей. Если вы собираетесь внедрять все AT-команды мобильного терминала, вам следует потратить больше времени на парсер. Если вы хотите сделать несколько тестовых приложений для нескольких команд, ваша реализация может быть простой, как и ваша.

Ответ №1

Я разработал этот синтаксический анализатор AT, это можно использовать для справки.

Когда вы получаете данные из UART1, просто вызовите этот метод at_wait_msg() чтобы проанализировать сообщение AT

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

static const char *AT_HEADER = "AT";
static const char *AT_DEVICE_PROFILE = "DR";
static const char *AT_SET_DEVICE = "SD";

static const char AT_EOF = '\r';

typedef enum {
DeviceProfile,
SetDevice,
Error
} AT_Msg_Type;

typedef struct {
char header[3];
char command[3];
char data[128];
} AT_Msg_Data;

static void at_wait_msg(char text);
static void at_wait_msg_complete(char *text);
static void at_parse_msg(AT_Msg_Data *data);
static AT_Msg_Type at_check_format(AT_Msg_Data *data);

static char _rx_data[512];
static uint16_t _rx_index = 0;

int main()
{
//example data getting from UART1
char text[] = "ATDR\rATSD123456abchelloworld\r1123ATssa\r";

for (int i = 0; i < strlen(text) + 1; i++) {
//to simulate getting data from UART1 byte per byte
at_wait_msg(text[i]);
}

return 0;
}

static void at_wait_msg(char text)
{
_rx_data[_rx_index++] = text;

if (text == AT_EOF) {
at_wait_msg_complete(_rx_data);

_rx_index = 0;
}
}

static void at_wait_msg_complete(char *text)
{
AT_Msg_Data data;

int result = sscanf_s(_rx_data, "%2s%2s%s\r",
data.header, sizeof(data.header),
data.command, sizeof(data.command),
data.data, sizeof(data.data));

if (result >= 2) {
at_parse_msg(&data);
}
}

static void at_parse_msg(AT_Msg_Data *data)
{
AT_Msg_Type type = at_check_format(data);

switch (type) {
case DeviceProfile:
printf("device profile\r\n");
break;
case SetDevice:
printf("settings %s\r\n", data->data);
break;
case Error:
default:
printf("Error\r\n");
break;
}
}

static AT_Msg_Type at_check_format(AT_Msg_Data *data)
{
if (strcmp(data->header, AT_HEADER) != 0) {
return Error;
}

if (strcmp(data->command, AT_DEVICE_PROFILE) == 0) {
return DeviceProfile;
}

if (strcmp(data->command, AT_SET_DEVICE) == 0) {
return SetDevice;
}

return Error;
}

Оцените статью
TechArks.Ru
Добавить комментарий