精华内容
下载资源
问答
  • 串口协议解析方法

    2021-06-04 23:29:33
    这个逻辑就比较yani
    展开全文
  • #include#include#include#include#include#include#include#include#include#include#include#includetypedefenum{SERIAL_8N1=0,SERIAL_7E1=1,SERIAL_7O1=2,SERIAL_7S1=3}serial_format;constchar*serial_port[]={...

    #include#include#include#include#include#include#include#include#include#include#include#includetypedefenum{

    SERIAL_8N1=0,

    SERIAL_7E1=1,

    SERIAL_7O1=2,

    SERIAL_7S1=3}serial_format;constchar*serial_port[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4"};intserial_open(intport)

    {intfd=open(serial_port[port], O_RDWR|O_NONBLOCK);if(-1==fd)

    {

    perror("Can't Open Serial Port");

    exit (-1);

    }else{

    fcntl(fd, F_SETFL,0);

    }returnfd;

    }voidserial_format_set(intfd,serial_format format)

    {intstatus=0;structtermios options;if( tcgetattr( fd,&options)!=0)

    {

    perror("serial fomat abnormal");

    exit (-1);

    }

    options.c_cflag&=~CSIZE;switch(format)

    {caseSERIAL_8N1:

    options.c_cflag&=~PARENB;

    options.c_cflag&=~CSTOPB;

    options.c_cflag&=~CSIZE;

    options.c_cflag|=CS8;

    options.c_iflag&=~(INPCK|ISTRIP);break;caseSERIAL_7E1:

    options.c_cflag|=PARENB;

    options.c_cflag&=~PARODD;

    options.c_cflag&=~CSTOPB;

    options.c_cflag&=~CSIZE;

    options.c_cflag|=CS7;

    options.c_iflag|=(INPCK|ISTRIP);break;caseSERIAL_7O1:

    options.c_cflag|=PARENB;

    options.c_cflag|=PARODD;

    options.c_cflag&=~CSTOPB;

    options.c_cflag&=~CSIZE;

    options.c_cflag|=CS7;

    options.c_iflag|=(INPCK|ISTRIP);break;caseSERIAL_7S1:

    options.c_cflag&=~PARENB;

    options.c_cflag&=~CSTOPB;

    options.c_cflag&=~CSIZE;

    options.c_cflag|=CS8;

    options.c_iflag&=~INPCK;

    options.c_iflag|=ISTRIP;break;default:

    perror("serial format abnormal");

    exit (-1);

    }

    tcflush(fd,TCIOFLUSH);

    status=tcsetattr(fd, TCSANOW,&options);if(status!=0)

    {

    perror("tcsetattr format abnormal");

    exit(-1);

    }

    }voidserial_speed_set(intfd,intbaudrate)

    {intstatus;structtermios options;/** Get the current options for the port

    1421aedabd7ca918716a95773be91a18.gif*/tcgetattr(fd,&options);/** Set the baud rates to 19200

    1421aedabd7ca918716a95773be91a18.gif*/cfsetispeed(&options, baudrate);

    cfsetospeed(&options, baudrate);/** Enable the receiver and set local mode

    1421aedabd7ca918716a95773be91a18.gif*/options.c_cflag|=(CLOCAL|CREAD);/** Set the new options for the port

    1421aedabd7ca918716a95773be91a18.gif*/tcflush(fd,TCIOFLUSH); 

    status=tcsetattr(fd, TCSANOW,&options);if(status!=0)

    {

    perror("tcsetattr speed abnormal");

    exit(-1);

    }

    }voidserial_etc_config(intfd)

    {intstatus=0;structtermios options;if( tcgetattr( fd,&options)!=0)

    {

    perror("serial etc abnormal");

    exit (-1);

    }//no hardware flow controloptions.c_cflag&=~CRTSCTS;//no soft controloptions.c_iflag&=~(IXON|IXOFF|IXANY);//raw set_inputoptions.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);//no output process , raw set_inputoptions.c_oflag&=~OPOST;//min characteroptions.c_cc[VMIN]=1;//time to wait for dataoptions.c_cc[VTIME]=15;

    tcflush(fd,TCIOFLUSH);

    status=tcsetattr(fd, TCSANOW,&options);if(status!=0)

    {

    perror("tcsetattr etc abnormal");

    exit(-1);

    }

    }voidserial_config(intfd,intbaudrate,serial_format format)

    {

    serial_speed_set(fd,baudrate);

    serial_format_set(fd,format);

    serial_etc_config(fd);

    }intmain(intargc,char**argv)

    {

    fd_set  set_input;intfd;charbuff[50]={'\0',};structtimeval timeout;intret_select=0;intbytes=0;intwrite_num=0;intread_num=0;intwait=0;

    fd=serial_open(0);

    serial_config(fd,B9600,SERIAL_8N1);

    FD_ZERO(&set_input);

    FD_SET(fd,&set_input);intloop_test=5;while(loop_test)

    {

    printf("Loop %d\n",loop_test);

    loop_test--;//tcflush(fd,TCIOFLUSH);if(loop_test%2)

    {

    write_num=write(fd,"hello \nlinux world !\n",strlen("hello \nlinux world !\n"));

    }else{

    write_num=write(fd,"hello \nserial port !\n",strlen("hello \nserial port !\n"));

    }

    printf("now %d bytes has been written to the serial port\n",write_num);

    timeout.tv_sec=1;

    timeout.tv_usec=0;

    ret_select=select(fd+1,&set_input, NULL,NULL,&timeout);/*See if there was an error*/if(ret_select<0)

    perror("select failed");elseif(ret_select==0)

    printf("timeout\n");else{/*We have set_input*/if(FD_ISSET(fd,&set_input))

    {

    bytes=0;

    wait=0;do{

    ioctl(fd, FIONREAD,&bytes);

    }while( wait++,bytes!=write_num);

    printf("now %d bytes is availble to read\n",bytes);

    printf("delay %d times for read\n",wait);

    read_num=read(fd, buff, bytes);

    printf("now %d bytes has been read from serial\n",read_num);

    buff[bytes]='\0';

    printf("%s", buff);

    }

    }

    printf("************\n");

    }

    close(fd);

    exit (0);

    }

    展开全文
  • 注意:下面的示例代码是从原子提供的例程中摘录,因此可能与最新的RT-Thread源码有出入(因为RT-Thread源码在不断的开发维护中) 下面摘录的例程中,关键位置我给出了注释 下面开始正文: RT-Thread的Finsh串口控制台...

    硬件测试平台:正点原子潘多拉STM32L4开发板
    OS内核版本:4.0.0

    注意:下面的示例代码是从原子提供的例程中摘录,因此可能与最新的RT-Thread源码有出入(因为RT-Thread源码在不断的开发维护中)
    下面摘录的例程中,关键位置我给出了注释

    下面开始正文:

    RT-Thread的Finsh串口控制台有个标志性的开头打印信息如下:

     \ | /
    - RT -     Thread Operating System
     / | \     4.0.0 build Dec 18 2018
     2006 - 2018 Copyright by rt-thread team
    

    在components.c中找到rtthread_startup()函数

    int rtthread_startup(void)
    {
        rt_hw_interrupt_disable();
    
        /* board level initialization
         * NOTE: please initialize heap inside board initialization.
         */
        rt_hw_board_init();
    
        /* show RT-Thread version */
        rt_show_version();
    

    rt_show_version();就是打印这段开头信息的。

    /**
     * This function will show the version of rt-thread rtos
     */
    void rt_show_version(void)
    {
        rt_kprintf("\n \\ | /\n");
        rt_kprintf("- RT -     Thread Operating System\n");
        rt_kprintf(" / | \\     %d.%d.%d build %s\n",
                   RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
        rt_kprintf(" 2006 - 2018 Copyright by rt-thread team\n");
    }
    RTM_EXPORT(rt_show_version);
    

    显然,既然能串口打印了,那么必然在这之前已经初始化了该串口,那么rt_show_version()之前的rt_hw_board_init()函数里一定初始化了串口。

    void rt_hw_board_init()
    {
    //...略
    
        /* Second initialize the serial port, so we can use rt_kprintf right away */
    #ifdef RT_USING_SERIAL
        stm32_hw_usart_init();
    #endif
    
    #ifdef RT_USING_CONSOLE
        rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
    #endif
    //...略
    }
    
    int stm32_hw_usart_init(void)
    {
        struct stm32_uart* uarts[] =
        {
    #ifdef BSP_USING_UART1
            &uart1,
    #endif
    
    #ifdef BSP_USING_UART2
            &uart2,
    #endif
    
    #ifdef BSP_USING_UART3
            &uart3,
    #endif
    
    #ifdef BSP_USING_LPUART1
            &lpuart1,
    #endif
        };
        int i;
    
        for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++)
        {
            struct stm32_uart *uart = uarts[i];
            rt_err_t result;
    
            /* register UART device */
            result = rt_hw_serial_register(&uart->serial,
                                  uart->uart_name,
    #ifdef BSP_UART_USING_DMA_RX
                                  RT_DEVICE_FLAG_DMA_RX |
    #endif
                                  RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                                  uart);
            RT_ASSERT(result == RT_EOK);
            (void)result;
        }
    
        return 0;
    }
    

    stm32_hw_usart_init()这个函数注册了使用到的串口设备到设备框架层,注册完就可以直接使用内核通用接口函数操作设备了,比如开启设备,读设备,写设备,通过BSP_USING_UART1这类宏控来控制将要使用哪几个串口。注意,这里只是注册,并没完成真正的底层硬件初始化。真正的完成底层硬件初始化在rt_console_set_device(RT_CONSOLE_DEVICE_NAME);这里面。即调用了打开设备才是完成了串口硬件初始化串口才能正常使用。

    
    /* UART1 device driver structure */
    static struct stm32_uart uart1 =
    {
        {USART1},               // UART_HandleTypeDef UartHandle;
        USART1_IRQn,            // IRQn_Type irq;
    
    #ifdef BSP_UART_USING_DMA_RX
        USART1_RX_DMA_IRQN,     // IRQn_Type dma_irq;
        0,                      // rt_size_t last_index;
        // DMA_HandleTypeDef hdma_rx;
        {USART1_RX_DMA_CHANNEL, {USART1_RX_DMA_REUQEST}},
    #endif
    
        "uart1",                // char * uart_name;
        // struct rt_serial_device serial;
        {{0}, &stm32_uart_ops, RT_SERIAL_CONFIG_DEFAULT}
    };
    

    stm32_uart类型如下:

    /* STM32 uart driver */
    struct stm32_uart
    {
        UART_HandleTypeDef UartHandle;
        IRQn_Type irq;
    
    #ifdef BSP_UART_USING_DMA_RX
        IRQn_Type dma_irq;
        rt_size_t last_index;
        DMA_HandleTypeDef hdma_rx;
    #endif
    
        char * uart_name;
        struct rt_serial_device serial;
    };
    

    struct rt_serial_device 类型如下:

    struct rt_serial_device
    {
        struct rt_device          parent;
    
        const struct rt_uart_ops *ops;
        struct serial_configure   config;
    
        void *serial_rx;
        void *serial_tx;
    };
    typedef struct rt_serial_device rt_serial_t;
    

    &stm32_uart_ops 对应 const struct rt_uart_ops *ops;
    RT_SERIAL_CONFIG_DEFAULT 对应 struct serial_configure config;

    stm32_uart_ops这个结构体实现接口层和底层的连接。
    RT_SERIAL_CONFIG_DEFAULT 这个是串口默认配置。

    /* Default config for serial_configure structure */
    #define RT_SERIAL_CONFIG_DEFAULT           \
    {                                          \
        BAUD_RATE_115200, /* 115200 bits/s */  \
        DATA_BITS_8,      /* 8 databits */     \
        STOP_BITS_1,      /* 1 stopbit */      \
        PARITY_NONE,      /* No parity  */     \
        BIT_ORDER_LSB,    /* LSB first sent */ \
        NRZ_NORMAL,       /* Normal mode */    \
        RT_SERIAL_RB_BUFSZ, /* Buffer size */  \
        0                                      \
    }
    //一一对应关系如下
    struct serial_configure
    {
        rt_uint32_t baud_rate;            /* 波特率 */
        rt_uint32_t data_bits    :4;      /* 数据位 */
        rt_uint32_t stop_bits    :2;      /* 停止位 */
        rt_uint32_t parity       :2;      /* 奇偶校验位 */
        rt_uint32_t bit_order    :1;      /* 高位在前或者低位在前 */
        rt_uint32_t invert       :1;      /* 模式 */
        rt_uint32_t bufsz        :16;     /* 接收数据缓冲区大小 */
        rt_uint32_t reserved     :6;      /* 保留位 */
    };
    

    再看stm32_uart_ops

    static const struct rt_uart_ops stm32_uart_ops =
    {
        stm32_configure,
        stm32_control,
        stm32_putc,
        stm32_getc,
    };
    

    这里的stm32_configure函数就实现了STM32串口的底层初始化流程,包含HAL_UART_Init函数调用。
    stm32_control函数是开启和清楚接收中断的,以及串口DMA配置。
    限于篇幅这几个函数不放在这里了。

    void USART1_IRQHandler(void)
    {
        /* enter interrupt */
        rt_interrupt_enter();
    
        uart_isr(&uart1.serial);
    
        /* leave interrupt */
        rt_interrupt_leave();
    }
    
    void USART1_RX_DMA_IRQHandler(void)
    {
        /* enter interrupt */
        rt_interrupt_enter();
    
        HAL_DMA_IRQHandler(uart1.UartHandle.hdmarx);
    
        /* leave interrupt */
        rt_interrupt_leave();
    }
    

    串口中断和串口接收DMA中断也在drv_usart.c文件里
    uart_isr(&uart1.serial);主要是清除中断标志位

    用过HAL库的都知道,外设的GPIO初始化,外设时钟使能,NVIC配置 都在HAL_UART_MspInit函数中完成,HAL_UART_MspInit函数也在drv_usart.c文件里

    void HAL_UART_MspInit(UART_HandleTypeDef *huart)
    

    同时将由于不同的GPIO可能导致的不同的端口配置和复用通道,DMA通道都用宏封装

    #ifdef BSP_USING_UART1
        #define USART1_RX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
        #define USART1_TX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
    
        /* Definition for USART1 Pins */
        #define USART1_TX_PIN                    GPIO_PIN_9
        #define USART1_TX_GPIO_PORT              GPIOA
        #define USART1_TX_AF                     GPIO_AF7_USART1
        #define USART1_RX_PIN                    GPIO_PIN_10
        #define USART1_RX_GPIO_PORT              GPIOA
        #define USART1_RX_AF                     GPIO_AF7_USART1
    
        #define USART1_RX_DMA_CHANNEL            DMA1_Channel5
        #define USART1_RX_DMA_REUQEST            DMA_REQUEST_2
        #define USART1_RX_DMA_IRQN               DMA1_Channel5_IRQn
        #define USART1_RX_DMA_IRQHandler         DMA1_Channel5_IRQHandler
    #endif
    

    上面的串口1使用的是默认配置RT_SERIAL_CONFIG_DEFAULT,
    如果要开其他串口或是要改配置比如改波特率,可以仿照RT_SERIAL_CONFIG_DEFAULT这个宏再封装一个出来改对应的项,赋值到对应串口的设备结构体中去,如static struct stm32_uart uart1

    上面提到,实际打开串口完成硬件初始化配置是在rt_console_set_device函数中

    #ifdef RT_USING_CONSOLE
        rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
    #endif
    
    rt_device_t rt_console_set_device(const char *name)
    {
        rt_device_t new, old;
    
        /* save old device */
        old = _console_device;
    
        /* find new console device */
        new = rt_device_find(name);
        if (new != RT_NULL)
        {
            if (_console_device != RT_NULL)
            {
                /* close old console device */
                rt_device_close(_console_device);
            }
    
            /* set new console device */
            rt_device_open(new, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
            _console_device = new;
        }
    
        return old;
    }
    

    #define RT_CONSOLE_DEVICE_NAME “uart1”
    这个宏定义在rtconfig.h中,定义了使用哪个串口作为控制台的端口。这里使用的是串口1,可以根据需要进行修改

    在rt_console_set_device函数中,完成了打开串口设备的动作 rt_device_open(new, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
    rt_device_open函数中调用了device_init和device_open,
    #define device_init (dev->init)
    #define device_open (dev->open)
    实际上是 (dev->init)和(dev->open)

    在rt_hw_serial_register函数中device->init = rt_serial_init;
    在rt_serial_init函数中看到了serial->ops->configure(serial, &serial->config); 前面说了,configure这个函数指针指向了stm32_configure,这个里面调用了HAL_UART_Init函数完成串口初始化配置。

    rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
                                   const char              *name,
                                   rt_uint32_t              flag,
                                   void                    *data)
    {
        rt_err_t ret;
        struct rt_device *device;
        RT_ASSERT(serial != RT_NULL);
    
        device = &(serial->parent);
    
        device->type        = RT_Device_Class_Char;
        device->rx_indicate = RT_NULL;
        device->tx_complete = RT_NULL;
    
    #ifdef RT_USING_DEVICE_OPS
        device->ops         = &serial_ops;
    #else
        device->init        = rt_serial_init;
        device->open        = rt_serial_open;
        device->close       = rt_serial_close;
        device->read        = rt_serial_read;
        device->write       = rt_serial_write;
        device->control     = rt_serial_control;
    #endif
        device->user_data   = data;
    
        /* register a character device */
        ret = rt_device_register(device, name, flag);
    
    #if defined(RT_USING_POSIX)
        /* set fops */
        device->fops        = &_serial_fops;
    #endif
    
        return ret;
    }
    
    static rt_err_t rt_serial_init(struct rt_device *dev)
    {
        rt_err_t result = RT_EOK;
        struct rt_serial_device *serial;
    
        RT_ASSERT(dev != RT_NULL);
        serial = (struct rt_serial_device *)dev;
    
        /* initialize rx/tx */
        serial->serial_rx = RT_NULL;
        serial->serial_tx = RT_NULL;
    
        /* apply configuration */
        if (serial->ops->configure)
            result = serial->ops->configure(serial, &serial->config);
    
        return result;
    }
    

    本文通篇讲了用于控制台的串口1如何注册到系统中并完成了初始化,其余串口也是同理。
    主要关注两个问题,1是如何修改某个串口的波特率,2是如果增加串口。
    如果底层驱动做好的情况下,实际上直接改宏控就能完成增加串口,env工具可以快速完成配置,也可以手动改rtconfig.h文件。

    也可以先全部默认的参数,然后在任务中重新配置,比如:
    如下步骤可以实现对应的配置,比如波特率115200改成9600

    #define SAMPLE_UART_NAME       "uart2"    /* 串口设备名称 */
    static rt_device_t serial;                /* 串口设备句柄 */
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  /* 初始化配置参数 */
    
    /* step1:查找串口设备 */
    serial = rt_device_find(SAMPLE_UART_NAME);
    
    /* step2:修改串口配置参数 */
    config.baud_rate = BAUD_RATE_9600;        //修改波特率为 9600
    config.data_bits = DATA_BITS_8;           //数据位 8
    config.stop_bits = STOP_BITS_1;           //停止位 1
    config.bufsz     = 128;                   //修改缓冲区 buff size 为 128
    config.parity    = PARITY_NONE;           //无奇偶校验位
    
    /* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */
    rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
    
    /* step4:打开串口设备。以中断接收及轮询发送模式打开串口设备 */
    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
    

    RT-Thread 官方串口配置文档

    展开全文
  • 经常需求使用 GPS 串口 NMEA 解析的功能,写了一段代码来完成引功能。分享一下,大家一起学习。头文件:#ifndef_GPS_MONITER_HH_#define_GPS_MONITER_HH_BOOLInitSerailPort(CStringcsSerialPort,LPVOIDpParent=NULL...

    经常需求使用 GPS 串口 NMEA 解析的功能,写了一段代码来完成引功能。

    分享一下,大家一起学习。

    头文件:#ifndef _GPS_MONITER_HH_

    #define _GPS_MONITER_HH_

    BOOL InitSerailPort(CString csSerialPort,LPVOID pParent = NULL);

    DWORD WINAPI ReadNMEAThread(LPVOID lpParameter);

    void SetSystemTimeFormUTC(CString csDate,CString csUTCTime);

    void DeinitSerialPort(void);

    #endif

    源文件:#include "stdafx.h"

    #include "GPSMoniter.h"

    #define SATTATOLNUMBER32

    // 用于在 GPS 监控界面显示 NMEA 信息

    char gcBuff[4096];

    CString gcsTime;

    CString gcsDate;

    int gdSignalNumber[SATTATOLNUMBER];

    CString csLat;

    CString csLatdir;

    CString csLon;

    CString csLondir;

    CString csAltitude;

    CString csSpeed;

    CString csOrientation;

    int nNumDisplayed;

    int giGSVSatNumber;

    HANDLE ghCommHandle;

    HANDLE nmeathread_hand;// Global handle to the NMEA reading thread

    CString gcsGPSState;//定位: A; 导航: V

    CString gcsTimeOp;

    CString gcsLatField;

    CString gcsLonField;

    int giResult;

    int giSalNumber;

    int giGSVCurrentPackage;

    int giHourDiff;

    BOOL InitSerailPort(CString csSerialPort,LPVOID pParent)

    {

    DCB commDCB;

    COMMTIMEOUTS timeouts;

    ghCommHandle = CreateFile(csSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,

    OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);

    if(INVALID_HANDLE_VALUE == ghCommHandle)

    {

    RETAILMSG(1, (TEXT("Opening GPS %s failed: %d!rn"),csSerialPort,(int)GetLastError()));

    return FALSE;

    }

    commDCB.DCBlength = sizeof (DCB);

    if(!GetCommState(ghCommHandle,&commDCB))

    {

    CloseHandle(ghCommHandle);

    ghCommHandle = INVALID_HANDLE_VALUE;

    RETAILMSG(1,(L"Failed in getting GPS %s DCB settings: %d!rn",csSerialPort,(int)GetLastError()));

    return FALSE;

    }

    commDCB.DCBlength = sizeof(DCB);

    commDCB.BaudRate = 9600;             // Current baud

    commDCB.ByteSize = 8;                 // Number of bits/bytes, 4-8

    commDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space

    commDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2

    // Setting serial port to Centrality speicifcations

    if(!SetCommState(ghCommHandle,&commDCB))

    {

    CloseHandle(ghCommHandle);

    ghCommHandle = INVALID_HANDLE_VALUE;

    RETAILMSG(1,(L"Error in trying to set GPS %s DCB settings: %d!rn",csSerialPort,(int)GetLastError()));

    return FALSE;

    }

    // Get the default timeout settings for port

    if(!GetCommTimeouts(ghCommHandle, &timeouts))

    {

    CloseHandle(ghCommHandle);

    ghCommHandle = INVALID_HANDLE_VALUE;

    RETAILMSG(1,(L"Failed in getting GPS %s timeout settings: %d!rn",csSerialPort,(int)GetLastError()));

    return FALSE;

    }

    // RETAILMSG(1,(L"%s DCB set successfully!rn",csSerialPort));

    // Change the timeouts structure settings to Centrality settings

    timeouts.ReadIntervalTimeout = 500;

    timeouts.ReadTotalTimeoutMultiplier = 0;

    timeouts.ReadTotalTimeoutConstant = 0;

    // Set the time-out parameters for all read and write operations on the port.

    if(!SetCommTimeouts(ghCommHandle,&timeouts))

    {

    CloseHandle(ghCommHandle);

    ghCommHandle = INVALID_HANDLE_VALUE;

    RETAILMSG(1,(L"Error in trying to set GPS %s timeout settings: %d!rn",csSerialPort,(int)GetLastError()));

    return FALSE;

    }

    if(0 != SetCommMask(ghCommHandle,EV_RXCHAR))

    {

    RETAILMSG(1,(L"==Set %s mask OK!rn",csSerialPort));

    }

    else

    {

    RETAILMSG(1,(TEXT("==Set %s mask failure:%d!rn"),csSerialPort,GetLastError()));

    }

    nmeathread_hand = CreateThread(NULL,0,ReadNMEAThread,pParent,0,NULL);

    //nmeathread_hand = CreateThread(NULL, 0, ReadNMEAThread, this, CREATE_SUSPENDED, NULL);

    if(!nmeathread_hand)

    {

    RETAILMSG(1, (L"Could not create NMEA read thread.rn"));

    return FALSE;

    }

    else

    {

    //SetThreadPriority(nmeathread_hand, THREAD_PRIORITY_BELOW_NORMAL);

    //ResumeThread(nmeathread_hand);

    }

    SYSTEMTIME stUTC;

    SYSTEMTIME stLocal;

    GetLocalTime(&stLocal);

    GetSystemTime(&stUTC);

    giHourDiff = stLocal.wHour - stUTC.wHour;

    return TRUE;

    }

    // nmeathread_hand = CreateThread(NULL, 0, ReadNMEAThread, this, 0, NULL);

    DWORD WINAPI ReadNMEAThread(LPVOID lpParameter)

    {

    //DECLARE_USER_MESSAGE(UWM_NEW_NMEA);

    int start, endline, onestart, oneend, linelen, degdig, iPos;

    ULONG bytesRead;

    DWORD EventMask = EV_RXCHAR;

    CString field;

    TCHAR *stopstring;

    static int iCount = 0;

    CWnd *mpNmea;

    mpNmea = (CWnd*)lpParameter;

    // Wait on the event

    while(WaitCommEvent(ghCommHandle, &EventMask, NULL))

    {

    // RETAILMSG(1,(TEXT("---------------------------------------------ReadNMEAThread:%d,Tick: %drn"),iCount++,GetTickCount()));

    // Clear the buffer before you start reading

    memset(gcBuff, 0, 4096);

    // Read from serial port (4b)

    if (ReadFile(ghCommHandle, gcBuff, 4096, &bytesRead, NULL))

    {

    if(bytesRead == 0)

    continue;

    CString dacstr(gcBuff);/*Leo:从串口读GPS卫星数据*/

    start = 0;

    endline = 0;

    // Parse/Process the output (4c)

    while(1)

    {

    int i = 0;

    start = dacstr.Find(L"$G", start);

    if(start 

    break;

    endline = dacstr.Find(L"rn", start);

    if(endline 

    break;

    linelen = endline - start;

    //DebugOutput(MSG_DEBUG, "GPSViewer msg: start = %d endline = %d length = %d", start, endline, linelen);

    // Extract one line

    CString oneline;

    oneline = dacstr.Mid(start, linelen);

    #if _DEBUG

    // RETAILMSG(1,(TEXT("*******************************GPSViewer msg: Oneline = %srn"),oneline));

    #endif

    onestart = 0;

    oneend = 0;

    i = 0;

    //

    //$GPRMC,075017.31,V,2232.6057,N,11356.3074,E,,,190708,,W,N*15

    //$GPRMC,080525.82,A,2232.5196,N,11356.3719,E,,,190708,,W,A*08

    if(oneline.Left(6) == L"$GPRMC")

    {

    while((iPos = oneline.Find(L",")) >= 0)

    {

    field = oneline.Left(iPos);

    i ++;

    oneline = oneline.Mid(iPos + 1);

    if(3 == i)

    {

    gcsGPSState = field;

    }

    else if(10 == i)//当前UTC日期ddmmyy 格式 - 例如: 030222

    {

    gcsDate = field;

    }

    }

    }

    //

    //$GPGGA,080514.82,2232.5203,N,11356.3719,E,1,6,1.327,239.386,M,,M,,*4D

    else if(oneline.Left(6) == L"$GPGGA")

    {

    while((iPos = oneline.Find(L",")) >= 0)

    {

    static int iOrientation = 0;

    field = oneline.Left(iPos);

    i ++;

    oneline = oneline.Mid(iPos + 1);

    if (i == 2)

    {

    //

    if(iOrientation != giResult)

    {

    RETAILMSG(1,(L"[GPS]Status of GPS is changed: %d(Old: %d)rn",giResult,iOrientation));

    iOrientation = giResult;

    }

    //

    gcsTimeOp = field;

    // 将格式从: --:--:--.-- 修改为: --:--:-- ,即不显示秒后的数据 ---Leo 2009-03-26

    CString csTmp = gcsTimeOp.Right(5);

    CString csHour = gcsTimeOp.Left(2);

    int iHour = _wtoi(csHour);

    if(iHour + giHourDiff 

    {

    csHour.Format(L"%d",iHour + giHourDiff);

    }

    else

    {

    csHour.Format(L"%d",((iHour + giHourDiff) - 24));

    }

    // gcsTime = csHour + L":" + time.Mid(2,2) + L":" + csTmp.Left(2);

    gcsTime = csHour + gcsTimeOp.Mid(2,2) + csTmp.Left(2);

    }

    else if (i == 3)

    {//Get Latitude from GGA - Value may not be valid.  Check flag to be sure.

    gcsLatField = field;

    degdig = gcsLatField.GetLength() - 2;

    csLat = gcsLatField.Left(2) + CString(" ") + gcsLatField.Right(degdig);

    }

    else if (i == 4)

    {//Get Latitude Direction (N,S) from GGA - Value may not be valid.  Check flag to be sure.

    csLatdir = field;

    }

    else if (i == 5)

    {//Get Longitude from GGA - Value may not be valid.  Check flag to be sure.

    gcsLonField = field;

    degdig = gcsLonField.GetLength() - 3;

    csLon = gcsLonField.Left(3) + CString(" ") + gcsLonField.Right(degdig);

    }

    else if (i == 6)

    {//Get Longitude Direction (E,W) from GGA - Value may not be valid.  Check flag to be sure.

    csLondir = field;

    }

    else if (i == 7)//GPS状态批示0-未定位 1-无差分定位信息 2-带差分定位信息

    {//Get Flag from GGA indicating position fix.  Position output from GGA is valid.

    giResult = atoi((const char*)((LPCTSTR)field));

    if(0 == giResult)

    {

    // RETAILMSG(1,(TEXT("===No orientationrn")));

    }

    else if(1 == giResult)

    {

    // RETAILMSG(1,(TEXT("===Orientation with no differencern")));

    }

    else if(2 == giResult)

    {

    // RETAILMSG(1,(TEXT("===Orientation with differencern")));

    }

    }

    else if (i == 10)

    {

    csAltitude = field;

    }

    }

    }

    //$GPGSV,3,3,11,29,21,93,36,30,33,40,36,31,49,324,*46

    else if (oneline.Left(6) == L"$GPGSV")

    {

    while((iPos = oneline.Find(L",")) >= 0)

    {

    field = oneline.Left(iPos);

    i ++;

    oneline = oneline.Mid(iPos + 1);

    if(3 == i)

    {

    if(_ttoi(field) > 0)

    {

    giGSVCurrentPackage = _ttoi(field);

    if (giGSVCurrentPackage == 1) // new GSV sentence

    {

    nNumDisplayed = 0;

    for(int j = 0;j 

    {

    gdSignalNumber[j] = -1;

    }

    }

    }

    }

    else if(4 == i)

    {

    if(_tcstod(field, &stopstring) > 0)

    {

    giGSVSatNumber = (int)_tcstod(field, &stopstring);

    }

    }

    else if(0 == (i - 5) % 4) //卫星的PRV号星号

    {

    if (_ttoi(field) > 0)

    {

    giSalNumber = _ttoi(field);

    }

    }

    else if(3 == (i - 5) % 4) // SNR

    {

    if (_ttoi(field) > 0)

    {

    gdSignalNumber[giSalNumber-1] = _ttoi(field);

    nNumDisplayed++;

    }

    }

    }

    if ((iPos = oneline.Find(L"*")) >= 0) // last sat

    {

    field = oneline.Left(iPos);

    i ++;

    if(3 == (i - 5) % 4) // SNR

    {

    if (_ttoi(field) > 0)

    {

    gdSignalNumber[giSalNumber-1] = _ttoi(field);

    nNumDisplayed++;

    }

    }

    }

    }

    //$GPVTG,,T,,M,,N,,K,*hh

    //对地航向(单位:度)

    //磁偏角(单位:度)

    //对地航速(单位:哩/小时)

    //地面速率(0000.0~1851.8公里/小时,前面的0也将被传输)

    //如: $GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04

    else if(oneline.Left(6) == L"$GPVTG")

    {

    while((iPos = oneline.Find(L",")) >= 0)

    {

    field = oneline.Left(iPos);

    i ++;

    oneline = oneline.Mid(iPos + 1);

    if(2 == i)

    {

    csOrientation = field;

    }

    else if(8 == i)

    {

    csSpeed = field;

    }

    }

    }

    start = endline + 2;

    } // end of buffer processing

    }

    //Sleep(1000);// end of ReadFile

    } // end of WaitCommEvent

    {

    // RETAILMSG(1,(TEXT("Exit GPS thread:%d"),GetLastError()));

    }

    return 0;

    }// end of ReadNMEAThread

    //csDate: 01-01-03

    //csUTCTime: 04:07:44.08

    void SetSystemTimeFormUTC(CString csDate,CString csUTCTime)

    {

    SYSTEMTIME st;

    int iHour = 0;

    int iMinute = 0;

    int iSecond = 0;

    int iYear = 0;

    int iMonth = 0;

    int iDay = 0;

    CString csSubString;

    TCHAR *stopstring;

    // RETAILMSG(1,(TEXT("====Set system time from UTC.Date: %s, Time: %s"),csDate,csUTCTime));

    GetSystemTime(&st);

    csSubString = csDate.Left(2);

    iDay = (int)_tcstod(csSubString, &stopstring);

    csSubString = csDate.Mid(3,2);

    iMonth = (int)_tcstod(csSubString, &stopstring);

    csSubString = csDate.Right(2);

    iYear = 2000 + (int)_tcstod(csSubString, &stopstring);

    st.wYear = iYear;

    st.wMonth = iMonth;

    st.wDay = iDay;

    csSubString = csUTCTime.Left(2);

    iHour = (int)_tcstod(csSubString, &stopstring);

    csSubString = csUTCTime.Mid(3,2);

    iMinute = (int)_tcstod(csSubString, &stopstring);

    csSubString = csUTCTime.Mid(6,2);

    iSecond = (int)_tcstod(csSubString, &stopstring);

    st.wHour = iHour;

    st.wMinute = iMinute;

    st.wSecond = iSecond;

    SetSystemTime(&st);

    }

    void DeinitSerialPort(void)

    {

    SetCommMask(ghCommHandle,0);

    if(nmeathread_hand)

    {

    TerminateThread(nmeathread_hand,1);

    CloseHandle(nmeathread_hand);

    }

    if(INVALID_HANDLE_VALUE != ghCommHandle)

    {

    EscapeCommFunction(ghCommHandle,CLRDTR);

    EscapeCommFunction(ghCommHandle,CLRRTS);

    //清除驱动程序内部的发送和接收队列

    PurgeComm(ghCommHandle,PURGE_TXCLEAR|PURGE_RXCLEAR);

    CloseHandle(ghCommHandle);

    ghCommHandle = INVALID_HANDLE_VALUE;

    }

    }

    展开全文
  • stm32串口解析

    2021-08-20 23:06:57
    1:什么是串口 UART : Universal Asynchronous Receiver/Transmitter 通用异步收发器 USART : Universal Synchronous Asynchronous Receiver/Transmitter 通用同步/异步收发器 串口简单来说就是一种简单的数据传输...
  • 串口解析与打包代码框架

    千次阅读 2021-12-15 17:23:54
    1、 数据格式 格式0x55+len(1)+cmd(1)+…+crc(1) 2、解析函数与处理函数 3、接收函数填充 ...6、在调用uart_rx_fun_heart_beat函数进行处理,通过cmd找到对应的函数来打包数据,最后通过串口发送出去。 ...
  • 串口编程 - 通信协议解析 规定了串口通信协议之后,接下来就是如何解析通信协议
  • TI IWR1642 雷达串口数据解析(C++代码)本文为研究生三年的一点小成果,供相同研究方向的同学借鉴编程语言 C++,编程工具QT 本文为研究生三年的一点小成果,供相同研究方向的同学借鉴 前言:研究算法是研究生三年的...
  • } void ser()interrupt 4//串口中断、初次分离'特殊符号无法显示'开头的字符串,并写入接收数组 { uchar ok=1; RI=0; temp=SBUF; table0[i++]=temp; SBUF=temp; while(!TI);TI=0; if(table0[0] == '特殊符号无法...
  • 串口通信协议源代码篇一:串口通信源代码#include#define uchar unsigned charuchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar a,b,flag;.//定义...
  • modbus_rtu 代码示例 1.目前编写modbus_rtu控制钧舵的产品,控制夹爪的开关,modbus_rtu...串口打开代码: xxx.cpp #include "stdafx.h" #include "Serial.h" #include "afxmt.h" #include <time.h> #include &l
  • linux下串口通信代码

    2021-05-14 15:40:55
    1.Stty.h#ifndef __STTY_H__#define __STTY_H__//包含头文件#include#include#include#include#include#include#include#include#include// 串口设备信息结构typedef struct tty_info_t{int fd; // 串口设备...
  • Python 串口数据打包与解析介绍从字符串到字节流对字节流的解析 介绍 通常用python写好上位机要与板子通过串口通信的时候(比如命令,参数等),对于这之间的数据格式转换是有特定要求的,比如上位机到板子之间是以...
  • STM32串口解析json命令(使用HAL库)串口接收中断处理(0x0D 0x0A作为结尾)测试结果具体代码 串口接收中断处理(0x0D 0x0A作为结尾) 串口接收没有采用环形缓冲区,使用0x0D 0x0A作为结尾(即回车换行符)。 uint8_t rx...
  • UART串口通讯协议解析

    万次阅读 2021-02-26 11:44:04
    UART串口通讯协议解析概述接口通信协议 概述 通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。它将要传输的资料在串行通信与并行通信之间加以转换。作为把并行输入信号转成串行...
  • (转自...首先需要下到串口驱动。javacomm20-win32.zip去sun的主页应该有下的。在这个驱动中有comm.jar,javax.comm.properties,win32com.dll这么3个重要的文件。1、首先...
  • 合宙air800与STM32进行串口数据交互(通过JSON)前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 十大 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术...
  • STM32 UART串口读取解析总结 参考这三篇博文 https://blog.csdn.net/sinat_16643223/article/details/119226462 https://blog.csdn.net/sinat_16643223/article/details/118830297 ...大部分是中断,用中...
  • ROS实现串口GPS数据的解析与通信 何伯特 2018-12-22 23:37:55 7123 收藏 86 分类专栏: ROS 文章标签: 串口 通信 ROS GPS 版权 1. 配置串口 配置串口时,利用ROS自带的serial功能包进行串口数据的读取,具体...
  • 串口命令解析

    2020-12-20 02:21:35
    第一篇文章我相信很多人不看都能做的出来,但是,用过微软SerialPort类的人,都遇到过这个尴尬,关闭串口的时候会让软件死锁。天哪,我可不是武断,算了。不要太绝对了。99.9%的人吧,都遇到过这个问题。我想只有...
  • 经典的应用比如知名的grbl固件的G代码解析固件https://github.com/grbl/grbl 以及GPS报文解析库tinygpshttps://github.com/mikalhart/TinyGPSPlus 以上两个都是解析串口发来的字符串,然后把相应的值提取 ..
  • 串口通信分为串行通信和并行通信,这里主要将串行通信,因为要用到。 串行通信主要分为同步通信和异步通信。 串行通信 同步通信 带时钟同步信号的数据传输 如 I2C、SPI 异步通信 不带时钟同步...
  • 下面先自定义将串口协议定出来,按照这个协议发送的数据格式进行解析,因为串口数据快,多帧的数据就混到一起,我们要把多帧的数据按照协议提出解析出来,因此就有这篇文章进行数据解析,我的注释写的很详细,串口的接收是...
  • 串口通信实验 Printf支持 ...//加入以下代码,支持printf函数,而不需要选择use MicroLIB #if 1 #pragma import(__use_no_semihosting) //解决HAL库使用时,某些情况可能报错的bug int _ttywrch(int ch
  • GPS模块需要到室外才能定位。没定位收到: $GNGGA,,,,,,0,00,25.5,,,,,,*64 $GNGLL,,,,,,V,M*79 $GPGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5*02 $BDGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5*13 $GPGSV,1,1,00*79 ...
  • 最近在从串口读取报文并判断报文内容是否有效,本来用C++写了一个小程序。奈何板卡的sftp服务老是连不上,于是考虑用shell脚本实现这个功能。用shell脚本实现这些功能面临以下几个问题: 1.命令行如何设置和读取串口...
  • 原文:... 用倍福的从站配置工具得到的源代码有以下 2014/12/26 11:24 1,021 1.TXT 2014/12/26 11:24 0 2.txt 2012/04/11 20:43 22,131 aoeappl.c 2012/04/11 20:43 1,578 aoeappl.h...
  • 品牌型号串口码飞利普DB9:RD:2TD:3GND:51241PXG20波特率:9600开机:POWR(3个空格)1(回车)关机:POWR(3个空格)0(回车)视频:IVED(3个空格)1(回车)VGA1:IRGB(3个空格)1(回车)VGA2:IRGB(3个空格)2(回车)NECDIN-8...
  • 基于Zigbee的SHT10温湿度数据采集系统+python串口读取——Zigbee终端节点主要代码解析 1)温湿度传感器用采用的是SHT10,之前用的是DHT11采集温湿度数据,结果精度不行,所以换成SHT10传感器。 2)我组的是星状网络...
  • TI AWR1642 学习笔记4之串口数据流解析 ​ 背景:在不使用采集板的情况下,怎么去解析AWR1642 data port打印的数据流,我使用到的工具有串口助手(用于串口数据的打印与查看)、mmw Demo Data Structure v0.1.pdf(这...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 48,646
精华内容 19,458
关键字:

串口解析代码