美文网首页
WIN 终端串口程序

WIN 终端串口程序

作者: wjundong | 来源:发表于2023-01-07 00:29 被阅读0次

serial.c

#include <stdio.h>
#include <libserialport.h>
#include <string.h>
#include <windows.h>
#include <pthread.h>

struct sp_port *port = NULL;
int connected = 0;

int serialport_connect(const char *port_name)
{
    if(port != NULL)
    {
        sp_close(port);
        sp_free_port(port);
        port = NULL;
    }

    sp_get_port_by_name(port_name, &port);

    int res = sp_open(port, SP_MODE_READ_WRITE);
    if(res != SP_OK)
    {
        sp_free_port(port);
        port = NULL;
        return -1;
    }
    
    sp_set_baudrate(port, 115200);
    sp_set_bits(port, 8);
    sp_set_parity(port, SP_PARITY_NONE);
    sp_set_stopbits(port, 1);
    sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE);

    return 0;
}

/* 连接到第一个扫描到的串口 */
const int serialport_connect_to_available(void)
{
    struct sp_port **port_list = NULL;
    enum sp_return result = sp_list_ports(&port_list);
    if (result != SP_OK) {
        return -1;
    }

    for (int i = 0; port_list[i] != NULL; i++) 
    {
        struct sp_port *port = port_list[i];
        char *port_name = sp_get_port_name(port);
        
        int r = serialport_connect(port_name);
        if(r == 0)
        {
            printf("\n连接到串口 %s\n\n", port_name);
            
            sp_free_port_list(port_list);
            return 0;
        }
    }

    sp_free_port_list(port_list);

    return -1;
}

void *serial_write_task(void * arg)
{
    char buf[8192];

    while (1)
    {
        gets(buf);
        int n = strlen(buf);
        buf[n++] = '\r';
        buf[n++] = '\n';
        if(connected)
        {
            sp_blocking_write(port, buf, n, 1000);
        }
    }
}

int main(int argc, char const *argv[])
{
    SetConsoleOutputCP(65001);
    // HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
    // SetConsoleMode(hInput, ENABLE_VIRTUAL_TERMINAL_INPUT);
    HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleMode(hOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);

    int res = serialport_connect_to_available();
    if(res != 0)
        printf("\n未找到串口, 请将设备插入USB口\n");
    else 
        connected = 1;
    
    char buf[4096];
    int buf_len = sizeof(buf);

    gets(buf);

    pthread_t t;
    pthread_create(&t, NULL, serial_write_task, NULL);

    while (1)
    {
        if(connected == 1)
        {
            int n = sp_blocking_read(port, buf, buf_len, 1);
            if(n < 0)
            {
                printf("\n串口连接断开了!\n");
                connected = 0;
                continue;
            }
            printf("%.*s", n, buf);
            fflush(stdout);
        }

        else if(serialport_connect_to_available() == 0)
        {
            connected = 1;
        }

        Sleep(10);
    }
    
    getchar();

    return 0;
}

其中

HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(hOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);

的作用是输出 ANSI 格式彩色文本

HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hInput, ENABLE_VIRTUAL_TERMINAL_INPUT);

的作用是自行处理输入,即键盘输入的每一个字符不通过缓冲区, 直接发送给程序, Ctrl+C 等组合键也会被接收, 可自行处理。但上面程序简单起见,不使用这一功能, 而是直接使用 gets 即从缓冲区接收字符串。

编译运行 (MSYS2环境)

gcc serial.c -lserialport -lpthread

相关文章

网友评论

      本文标题:WIN 终端串口程序

      本文链接:https://www.haomeiwen.com/subject/djpecdtx.html