C语言 字符串解析,根据接收到的串行数据打开/关闭LED

8xiog9wr  于 2023-02-03  发布在  其他
关注(0)|答案(2)|浏览(115)

我从python的串口接收到一个字符串,格式为**(0,77,88,55)**,我将第一个数字随机化为0或1,其余的是固定的。

import random
import serial
import time

last_time = 0
test_list = [0,1]

serialSTM32 = serial.Serial('COM22',9600,writeTimeout=0)

while True:
    if (time.time() - last_time) > 2:
        random_num = random.choice(test_list)
        #string = str(random_num)
        string = "(" + str(random_num) + "," + "77" + "," + "88" + "," + "55" + ")"
        serialSTM32.write(string.encode('utf-8'))
        print(string)
        last_time = time.time()
        serialSTM32.flushInput()

STM32 MCU通过虚拟串行COM端口接收“usbd_cdc_if. c”文件中变量的数据:

uint8_t bufferVariable = 0;

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  bufferVariable = Buf[0];
  return (USBD_OK);
}

bufferVariable通过以下方式传递到“main. c”文件:

extern uint8_t bufferVariable;

“main.c”然后解析数据,拆分数据,并将第一个数字“0”或“1”放入名为“first”的变量中,将第二个数字“77”放入名为“second”的变量中,等等。我正在使用“first”变量,看看是否为“1”以打开LED,但如果是“0”则关闭LED。程序等待启动市场“(“并继续阅读,直到它到达结束标记“)",然后解析两者之间的数据。**在Arduino上运行良好,从解析教程开始,我把所有的东西都转换成在STM32 MCU上工作。

对于此STM32控制器,之前我在没有解析的情况下进行了测试,仅通过串行接收“1”或“0”以打开/关闭LED,这可以正常工作**.....但现在我使用格式(0,77,88,55),其中包括解析数据,然后获取从该格式提取的值。**此部件无法正常工作....LED无法打开或关闭。

“main. c”文件代码:

#define buffer_size 40

char input_buffer[buffer_size];
const char start_marker = '(';
const char end_marker = ')';
uint8_t bytes_received = 0;
uint8_t read_in_progress = 0;

char* grab_value(char *data, char separator, int index) {
    int found = 0;
    int string_index[] = { 0, -1 };
    int maximum_index = strlen(data) - 1;

    for (int i = 0; i <= maximum_index && found <= index; i++) {
        if (data[i] == separator || i == maximum_index) {
            found++;
            string_index[0] = string_index[1] + 1;
            string_index[1] = (i == maximum_index) ? i + 1 : i;
        }
    }

    if (found > index) {
        data[string_index[1]] = '\0';
        return &data[string_index[0]];
    } else {
        return NULL;
    }
}

int first, second, third, fourth;

extern uint8_t bufferVariable;

int main(void) {

    while (1) {

        if (bufferVariable == end_marker) {
            read_in_progress = 0;
            input_buffer[bytes_received] = '\0';
        }

        if (read_in_progress) {
            input_buffer[bytes_received++] = bufferVariable;
            if (bytes_received == buffer_size) {
                bytes_received = buffer_size - 1;
            }
        }

        if (bufferVariable == start_marker) {
            bytes_received = 0;
            read_in_progress = 1;
        }
        char *str_first = grab_value(input_buffer, ',', 0);
        char *str_second = grab_value(input_buffer, ',', 1);
        char *str_third = grab_value(input_buffer, ',', 2);
        char *str_fourth = grab_value(input_buffer, ',', 3);

        if (str_first) {
            first = atoi(str_first);
        }
        if (str_second) {
            second = atoi(str_second);
        }
        if (str_third) {
            third = atoi(str_third);
        }
        if (str_fourth) {
            fourth = atoi(str_fourth);
        }
        printf("first: %d\n", first);

        if (first == '0') {
            HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
        } else if (first == '1') {
            HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
        }

    }
    
}
xqk2d5yq

xqk2d5yq1#

first == '0'

这是完全错误的。'0'不是整数值,只有48在ASCII中表示字符'0'
不要重新发明轮子。
整个招待会结束后,简单地说:

if(sscanf(inputBuffer, "(%d,%d,%d,%d)", &first, &second, &third, &fourth) == 4)
{
    if(!first) HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
    else HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
}

STM32 uC拥有比Arduino中使用的AVR uC更多的资源,您不需要任何"技巧"。只需确保inputBuffer以空字符终止

xurqigkl

xurqigkl2#

免责声明,这是我的个人偏好:
对于嵌入式,您永远不应该使用阻塞I/O、始终缓冲的中断驱动I/O。除了阻塞I/O更简单之外,我不能说任何一句话支持它。
你说问题是,LED不切换。
让我们看看事实。
此检查控制是否切换LED:

if (first == '0') {
    HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
} else if (first == '1') {
    HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
}

我注意到你在比较一个整数和char-0和1的值,而不是整数值,你本质上是在检查first == 48/49而不是0/1(见整数值https://www.asciitable.com/
同时,您将接收到的字符串转换为整数,方法是执行
first = atoi(str_first);
first01进行比较,而不是将'0''1'(分别为48和49)进行比较。

相关问题