精华内容
下载资源
问答
  • ht46ru232 串口接收、发送程序 C语言 ht46ru232 串口接收、发送程序 C语言
  • VS2017平台下最简洁的基于C语言开发的串口发送程序测试代码,修改简单灵活,方便用于各种串口调试。VS2017平台下最简洁的基于C语言开发的串口发送程序测试代码,修改简单灵活,方便用于各种串口调试。
  • 前言2.windows  串口通信API3.C/C++封装  动态运行库4.JAVA-JNI  java程序调用C++程序一、前言&ensp ;写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51单片机传送来的一些数据。...

    目录

    1.前言

    2.windows  串口通信API

    3.C/C++封装  动态运行库

    4.JAVA-JNI  java程序调用C++程序

    一、前言

    &ensp ;写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51单片机传送来的一些数据。单片机的数据由USB转串口发送至上位机,要处理这些数据,就会用到windows提供一些API(Application Programming Interface,应用程序接口)。java在安装了相关的包后,比如JNative.jar,可以直接用该包提供的接口来进行调用windowsAPI。但是我才接触java。而且整个作业,我仅仅只要一部分来处理这个数据。安装一个java包,实在是大可不必,所以就用C/C++来写一个的终端,封装一下放在java程序里面。

    二、windows串口通信API

    2.1   工具:VC++6.0

    2.2   概述:windows操作系统的设备无关性将所有的外设都当做文件来操作,那么我们写串口通信就直接将串口当做文件来读写。那么我们打开串口后一定要记得关闭,这个很重要

    2.3   串口通信程序概述

    2.3.1 打开/关闭串口

    HANDLE WINAPI CreateFileW(

    LPCWSTR lpFileName,

    DWORD dwDesiredAccess,

    DWORD dwShareMode, //共享模式

    LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性

    DWORD dwCreationDisposition, //指定文件的动作

    DWORD dwFlagsAndAttributes, //文件属性---不指定就默认为同步IO

    HANDLE hTemplateFile //模板文件

    );

    BOOL WINAPI CloseHandle(

    HANDLE hObject

    );

    返回值:一个串口的句柄。

    参数解释:

    lpFileName——串口名字。 当为COM1~COM9的时候可以直接写入但是大于10会有另外的写法。以COM10为例:\.\COM10。

    lpFileName——打开方式。 简单来说这个就是打开文件是读还是写。GENERIC_READ(读)|GENERIC_WRITE(写)。还有其它的两个值,详细请在编辑器中直接按下F12看看他们的定义。

    如果我们要定义一个同步IO的话,我们的打开方式必须要有读动作。

    dwShareMode指定该端口的共享属性。 对于不能共享的串口,它必须设置为0。这就是文件与通信设备之间的主要差异之一。如果在当前的应用程序调用CreateFile()时,另一个应用程序已经打开了串口,该函数就会返回错误代码,原因是两个应用程序不能共享一个端口。然而,同一个应用程序的多个线程可以共享由CreateFile()返回的端口句柄,并且根据安全性属性设置,该句柄可以被打开端口的应用程序的子程序所继承。

    dwCreationDisposition指定文件的动作。 指定如果CreateFile()正在被已有的文件调用时应采取的动作。因为串口总是存在,fdwCreate必须设置成OPEN_EXISTING。该标志告诉Windows不用企图创建新端口,而是打开已经存在的端口。

    调用该函数后,如果没有穿件成功将会返回INVALID_HANDLE_VALUE。

    2.3.2 配置串口通信

    (1) 当我们设置同步IO通信的时候,需要设置一下通信超时。一般情况下,我们用GetCommTimeouts来获得COMMTIMEOUTS结构体,再利用SetCommTimeouts来写入。

    BOOL WINAPI GetCommTimeouts(

    HANDLE hFile,

    LPCOMMTIMEOUTS lpCommTimeouts

    );

    BOOL WINAPI SetCommTimeouts(

    HANDLE hFile,

    LPCOMMTIMEOUTS lpCommTimeouts

    );

    COMMTIMEOUTS:

    typedef struct _COMMTIMEOUTS {

    DWORD ReadIntervalTimeout; /* 设置两个字符之前的最大读取时间 */

    DWORD ReadTotalTimeoutMultiplier; /* 设置每个字符的读取时间 */

    DWORD ReadTotalTimeoutConstant; /* 设置所有字符读取的最大时间 */

    DWORD WriteTotalTimeoutMultiplier; /* 设置每个字符的写入时间 */

    DWORD WriteTotalTimeoutConstant; /* 设置所有字符的写入时间 */

    } COMMTIMEOUTS,*LPCOMMTIMEOUTS;

    (2) 设置波特率等相关参数

    仍然先用GetCommState得到DCB结构,修改其中的某些参数后再用SetCommState写入DCB结构。

    BOOL WINAPI GetCommState(

    HANDLE hFile,

    LPDCB lpDCB

    );

    BOOL WINAPI SetCommState(

    HANDLE hFile,

    LPDCB lpDCB

    );

    DCB数据结构我们初级学者需要关注:波特率、校验位、停止位、发送数据位数。

    (3) 设置缓冲区大小,根据程序要接收/发送的数据大小来决定。

    BOOL WINAPI SetupComm(

    HANDLE hFile,

    DWORD dwInQueue,

    DWORD dwOutQueue

    );

    (4) 读取/写入数据

    BOOL WINAPI ReadFile(

    HANDLE hFile,

    LPVOID lpBuffer, //存放数据的缓冲区

    DWORD nNumberOfBytesToRead, //一次想要读入的数据长度

    LPDWORD lpNumberOfBytesRead, //实际读入的数据长度

    LPOVERLAPPED lpOverlapped

    );

    BOOL WINAPI WriteFile(

    HANDLE hFile,

    LPCVOID lpBuffer,

    DWORD nNumberOfBytesToWrite,

    LPDWORD lpNumberOfBytesWritten,

    LPOVERLAPPED lpOverlapped

    );

    2.3.3 配置串口通信

    展开全文
  • 关于串口发送C语言程序,上层直接将数据装入缓冲区,若手工发送标记(auto_uart0_tx_flg )为1,则置位串口中断标志TI0,启动发送,直至缓冲区为空(读写指针相等,此时将auto_uart0_tx_flg置0),否则,说明此时...
  • keil 51 单片机C语言串口发送和接收程序 STC-ISP// 9600 N 8 1 keil 51 单片机C语言串口发送和接收程序 STC-ISP// 9600 N 8 1
  •  printf("串口发送数据成功!\n");  printf("发送的数据为:\n");  for(i=0; i; i++)  {  printf("%02X ", sendData[i]);  }  printf("\n");  /***********关闭串口***********/  CloseHandle...

    #include "pch.h"

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <windows.h>
    #include <string.h>
    #include <conio.h>
    #include "tchar.h"

    #include <iostream>

     


    int main()
    {
        /*****************************打开串口*************************************/
        HANDLE hCom;//全局变量,串口句柄
        hCom = CreateFile(_T("COM3"),//COM3口
            GENERIC_READ | GENERIC_WRITE,//允许读和写
            0,//独占方式
            NULL,
            OPEN_EXISTING,//打开而不是创建
            0,//同步方式
            //FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERAPPLE,//重叠方式
            NULL);
        if(hCom == (HANDLE)-1)
        {
            printf("打开COM失败!");
            return 0;
        }
        /****************配置串口***************/
        SetupComm(hCom, 20480, 20480);//输入缓冲区和输出缓冲区的大小都是20480
        
        COMMTIMEOUTS TimeOuts;    
        TimeOuts.ReadIntervalTimeout = 1000;//设定读超时
        TimeOuts.ReadTotalTimeoutMultiplier = 500;
        TimeOuts.ReadTotalTimeoutConstant = 5000;    
        TimeOuts.WriteTotalTimeoutMultiplier = 500;//设定写超时
        TimeOuts.WriteTotalTimeoutConstant = 2000;
        SetCommTimeouts(hCom, &TimeOuts);//设置超时
        
        DCB dcb;
        GetCommState(hCom, &dcb);
        dcb.BaudRate = 115200;//波特率为115200
        dcb.ByteSize = 8;//每个字节有8位
        dcb.Parity = NOPARITY;//无奇偶校验位
        dcb.StopBits = TWOSTOPBITS;//两个停止位
        dcb.fParity = FALSE;
        dcb.fNull = FALSE;
        SetCommState(hCom, &dcb);
        PurgeComm(hCom, PURGE_TXCLEAR|PURGE_RXCLEAR);//在读写串口之前清空缓冲区
        
                                                     
        /********同步写串口********/
        int i;
        unsigned char sendData[256] = {0};//写入串口缓存区的数组
        for(i=0; i<16; i++)
        {
            sendData[i] = i;
        }

        DWORD dwWriteLen = 0;
        if(!WriteFile(hCom, sendData, 16, &dwWriteLen, NULL))
        {
            printf("串口发送数据失败!\n");
        }
        printf("串口发送数据成功!\n");
        printf("发送的数据为:\n");
        for(i=0; i<16; i++)
        {
            printf("%02X ", sendData[i]);
        }
        printf("\n");

        /***********关闭串口***********/
        CloseHandle(hCom);

        std::cout << "Hello World!\n"; 

        return 0;
    }

    运行效果:

    配套VS2017工程下载地址:https://download.csdn.net/download/qinrenzhi/10774388

    展开全文
  • C语言串口程序

    2014-08-28 16:38:40
    基于C,语言的串口程序,包括串口接收,串口发送程序
  • 前言2.windows  串口通信API3.JAVA-JNI  java程序调用C++程序4.C/C++封装  动态运行库一、前言写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51单片机传送来的一些数据。单片机的数据由...

    目录

    1.前言

    2.windows  串口通信API

    3.JAVA-JNI  java程序调用C++程序

    4.C/C++封装  动态运行库

    一、前言

    写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51单片机传送来的一些数据。单片机的数据由USB转串口发送至上位机,要处理这些数据,就会用到windows提供一些API(Application Programming Interface,应用程序接口)。java在安装了相关的包后,比如JNative.jar,可以直接用该包提供的接口来进行调用windowsAPI。但是我才接触java。而且整个作业,我仅仅只要一部分来处理这个数据。安装一个java包,实在是大可不必,所以就用C/C++来写一个的终端,封装一下放在java程序里面。

    二、windows串口通信API

    2.1   工具:VC++6.0

    2.2   概述:windows操作系统的设备无关性将所有的外设都当做文件来操作,那么我们写串口通信就直接将串口当做文件来读写。那么我们打开串口后一定要记得关闭,这个很重要

    2.3   串口通信程序概述

    2.3.1 打开/关闭串口

    HANDLE WINAPI CreateFileW(

    LPCWSTR lpFileName,

    DWORD dwDesiredAccess,

    DWORD dwShareMode, //共享模式

    LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性

    DWORD dwCreationDisposition, //指定文件的动作

    DWORD dwFlagsAndAttributes, //文件属性---不指定就默认为同步IO

    HANDLE hTemplateFile //模板文件

    );

    BOOL WINAPI CloseHandle(

    HANDLE hObject

    );

    返回值:一个串口的句柄。

    参数解释:

    lpFileName——串口名字。 当为COM1~COM9的时候可以直接写入但是大于10会有另外的写法。以COM10为例:\.\COM10。

    lpFileName——打开方式。 简单来说这个就是打开文件是读还是写。GENERIC_READ(读)|GENERIC_WRITE(写)。还有其它的两个值,详细请在编辑器中直接按下F12看看他们的定义。

    如果我们要定义一个同步IO的话,我们的打开方式必须要有读动作。

    dwShareMode指定该端口的共享属性。 对于不能共享的串口,它必须设置为0。这就是文件与通信设备之间的主要差异之一。如果在当前的应用程序调用CreateFile()时,另一个应用程序已经打开了串口,该函数就会返回错误代码,原因是两个应用程序不能共享一个端口。然而,同一个应用程序的多个线程可以共享由CreateFile()返回的端口句柄,并且根据安全性属性设置,该句柄可以被打开端口的应用程序的子程序所继承。

    dwCreationDisposition指定文件的动作。 指定如果CreateFile()正在被已有的文件调用时应采取的动作。因为串口总是存在,fdwCreate必须设置成OPEN_EXISTING。该标志告诉Windows不用企图创建新端口,而是打开已经存在的端口。

    调用该函数后,如果没有穿件成功将会返回INVALID_HANDLE_VALUE。

    2.3.2 配置串口通信

    (1) 当我们设置同步IO通信的时候,需要设置一下通信超时。一般情况下,我们用GetCommTimeouts来获得COMMTIMEOUTS结构体,再利用SetCommTimeouts来写入。

    BOOL WINAPI GetCommTimeouts(

    HANDLE hFile,

    LPCOMMTIMEOUTS lpCommTimeouts

    );

    BOOL WINAPI SetCommTimeouts(

    HANDLE hFile,

    LPCOMMTIMEOUTS lpCommTimeouts

    );

    COMMTIMEOUTS:

    typedef struct _COMMTIMEOUTS {

    DWORD ReadIntervalTimeout; /* 设置两个字符之前的最大读取时间 */

    DWORD ReadTotalTimeoutMultiplier; /* 设置每个字符的读取时间 */

    DWORD ReadTotalTimeoutConstant; /* 设置所有字符读取的最大时间 */

    DWORD WriteTotalTimeoutMultiplier; /* 设置每个字符的写入时间 */

    DWORD WriteTotalTimeoutConstant; /* 设置所有字符的写入时间 */

    } COMMTIMEOUTS,*LPCOMMTIMEOUTS;

    (2) 设置波特率等相关参数

    仍然先用GetCommState得到DCB结构,修改其中的某些参数后再用SetCommState写入DCB结构。

    BOOL WINAPI GetCommState(

    HANDLE hFile,

    LPDCB lpDCB

    );

    BOOL WINAPI SetCommState(

    HANDLE hFile,

    LPDCB lpDCB

    );

    DCB数据结构我们初级学者需要关注:波特率、校验位、停止位、发送数据位数。

    (3) 设置缓冲区大小,根据程序要接收/发送的数据大小来决定。

    BOOL WINAPI SetupComm(

    HANDLE hFile,

    DWORD dwInQueue,

    DWORD dwOutQueue

    );

    (4) 读取/写入数据

    BOOL WINAPI ReadFile(

    HANDLE hFile,

    LPVOID lpBuffer, //存放数据的缓冲区

    DWORD nNumberOfBytesToRead, //一次想要读入的数据长度

    LPDWORD lpNumberOfBytesRead, //实际读入的数据长度

    LPOVERLAPPED lpOverlapped

    );

    BOOL WINAPI WriteFile(

    HANDLE hFile,

    LPCVOID lpBuffer,

    DWORD nNumberOfBytesToWrite,

    LPDWORD lpNumberOfBytesWritten,

    LPOVERLAPPED lpOverlapped

    );

    2.3.3 串口缓冲区配置

    在程序运行的时候,应该保证设置的缓冲区是“干净”的。所以在读数据或者写数据之前,可以先清空一下缓冲区。

    //清空缓冲区

    BOOL WINAPI PurgeComm(

    HANDLE hFile,

    DWORD dwFlags

    );

    //清除错误

    BOOL WINAPI ClearCommError(

    HANDLE hFile,

    LPDWORD lpErrors,

    LPCOMSTAT lpStat

    );

    2.4完整的读串口代码

    #include `

    #include

    int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,char rBuf[])

    {//缓冲区

    DWORD rSize = 0;

    DWORD dwError;//清除错误

    COMSTAT cs;

    COMMTIMEOUTS timeouts;//超时数据结构

    DCB dcb;//串口通信配置文件---用LPDCB类型会报错

    HANDLE hCom;//串口的句柄(实例)| the instance of com

    hCom = CreateFile("COM3",//串口的名字

    GENERIC_READ | GENERIC_WRITE, //串口打开方式

    0,//共享方式

    NULL,//安全属性

    OPEN_EXISTING,//指定文件的动作

    0,//文件属性---不指定就默认为同步IO

    NULL//指向模板文件的句柄

    );

    if(hCom == INVALID_HANDLE_VALUE)

    {

    return -1;

    }

    ///

    //同步IO需要设置读数据超时

    //

    if(!(GetCommTimeouts(hCom,&timeouts)))//获的COMMTIMEOUTS结构失败!

    {

    CloseHandle(hCom);

    }

    timeouts.ReadIntervalTimeout = 1000;//读取每个字符之间的超时

    timeouts.ReadTotalTimeoutMultiplier = 500;//读取一个字符的超时

    timeouts.ReadTotalTimeoutConstant=5000;//固定总超时

    timeouts.WriteTotalTimeoutConstant = 0;//写入字符之间超时

    timeouts.WriteTotalTimeoutMultiplier = 0;//写入字符总超时

    if(!(SetCommTimeouts(hCom,&timeouts)))//设置COMMTIMEOUTS结构失败

    {

    CloseHandle(hCom);

    }

    //设置缓冲区大小

    ///

    if(!SetupComm(hCom,500,500))//设置读写缓冲区失败

    {

    CloseHandle(hCom);

    }

    //

    //设置波特率等其它读文件配置

    /

    if(GetCommState(hCom,&dcb)==0)//获得DCB数据失败

    {

    CloseHandle(hCom);

    }

    //dcb.DCBlength = sizeof(DCB);

    dcb.BaudRate = nBaud;//波特率为4800

    dcb.Parity = parity;//校验方式为无校验

    dcb.ByteSize = bytesize;//数据位为8位

    dcb.StopBits = stopbits;//停止位为1位

    if (!SetCommState(hCom,&dcb))//设置串口通信配置项失败

    {

    CloseHandle(hCom);

    }

    //

    //清除缓冲区

    /

    PurgeComm(hCom,PURGE_RXCLEAR|PURGE_TXCLEAR);

    ///

    //清除错误

    ///

    if(!(ClearCommError(hCom,&dwError,&cs)))

    {

    CloseHandle(hCom);

    }

    //开始读取缓冲口的数据

    ///

    //读取串口数据

    if(INVALID_HANDLE_VALUE != hCom)

    {

    WriteFile

    ReadFile(hCom,rBuf,accdatalength,&rSize,NULL);

    printf("%d \n",rSize);

    if(rSize)

    {

    CloseHandle(hCom);

    return 1;

    }

    else

    {

    CloseHandle(hCom);

    return 0;

    }

    }

    else

    {

    CloseHandle(hCom);

    return 2;

    }

    }

    void main()

    {

    int i;

    char buf[18] = {0};

    int a,b,c,d,e;

    printf("请输入相关参数:");

    scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);

    while(1)

    {

    if(Comm(a,b,c,d,e,buf)==1)

    {

    for(i=0;i<17;i++)

    {

    printf("%c ",buf[i]);

    }

    printf("\n");

    }

    else

    {

    printf("%d \n",Comm(a,b,c,d,e,buf));

    break;

    }

    }

    }

    运行结果

    499fc035ff815b9a6487ff7bff7d72ff.png

    三、JAVA-JNI  java程序调用C++程序

    参考博客

    在写java程序调用C程序之前,写过C#程序调用用C#封装好的dll程序。然后,我以为,java程序调用C程序也可以直接把C封装好的dll程序拿过来直接用就好。结果就是一直报错。那么接下来就是正确的调用方式。

    工具:eclipse

    3.1

    首先在新建一个类,类的名字随意。最好加上main()函数方便我们进行模块调试。在这个类里面。在这个类里面我们要自己定义将会用C/C++实现的函数。并且必须用到java提供的System.loadLibrary()函数。如下:

    `

    public class Com {

    static {

    System.loadLibrary("CommDLL");//静态语句块,保证在创建该类的时候,该方法必须且只会调用一次。参数就是编写的动态库名称

    }

    public native int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,String ComName,char[] rBuf);//将要用C/C++实现的函数

    public static void main(String[] args) {

    int term = new Com().Comm(4800, 0, 8, 0, 17,"COM3", Buffer);

    }

    }

    `

    注:native 关键字表示,这个函数为本地函数。尽管没用java语言实现,但它有自己的实体。

    3.2

    找到刚编写的java源程序文件所在的位置。然后如下操作:

    676d4a3a5fe55f47c97cf187dcfc26db.png

    注:马赛克的位置是暂时还不该有的文件

    进入控制台:

    95f62b6b15b1d022ca45f6e80e562813.png

    输入 javac -d ./ Com.java 。即是根据将java文件经过编译生成二进制文件(class文件)

    6ab8fdce4c09ed1c80954f7f9f14ff3a.png

    83d035c6507ef0de59d4920f2fcd2d5a.png

    输入 javac -h ./ Com.java 生成相关的头文件。

    cb0ff9800be5b1591839d81dcc9427d8.png

    bd41d0125e073a2b237e616f14859910.png

    注:如果报错:'javac不是内部或外部命令,也不是可运行的程序或批处理文件。'请参考相关博客添加相关的环境变量。参考博客。

    3.3

    在生成了相关的库文件的编写后。我们要用这个库文件有两种办法。

    1:直接将生成的dll文件加入默认的环境变量里面。(但是不是很推荐这个办法,因为我们编写的库,仅仅只是在自己的程序上用一用。没有很大的普适性。)

    2:将生成的dll文件拷贝到自己源文件下面。同时配置一下自己的java程序。

    右键src--->properties--->Native Library--->Workspace

    bcad91efe3552c8a2da17426c52aca71.png

    3.4

    运行代码:

    public class Com {

    static {

    System.loadLibrary("CommDLL");//静态语句块,保证在创建该类的时候,该方法必须且只会调用一次。

    }

    public native int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,String ComName,byte[] rBuf);

    public static void main(String[] args) {

    // TODO Auto-generated method stub

    byte[] Buffer = new byte[18];

    while(true)

    {

    int term = new Com().Comm(4800, 0, 8, 0, 17,"COM3", Buffer);

    if(term==1)

    {

    for(int i=0;i<17;i++)

    {

    System.out.print(Buffer[i]+" ");

    }

    System.out.println();

    }

    }

    }

    }

    运行结果

    67b4a947597dea16065b5cd78ea8d66d.png

    四、C/C++封装动态运行库

    4.1:关于工具

    一开始用的工具是VC++6.0,尽管工具有点老,但是它足够小。动态库编好了,在eclipse上面运行的时候,出现了错误,大致意思就是:“32位的动态库,没有办法在64位的设备上面”。 如果,我还想继续使用这个动态库,已知的解决办法就是:下载一个32位的java   JDK包。但是,相比配置一个可以运行32位的环境,我更加倾向于编译生成一个64位的动态运行库。然后,我就把代码粘到了VS上面。一般写代码我不太喜欢在VS上面,虽然它的功能很强太,但是我的电脑负载它真的很费力。

    4.2 用JNI编写本地函具体步骤

    * 1:建立DLL程序:文件--->新建--->项目--->windows桌面--->动态链接库

    83e01c46e3a66a03a797ff3855e8add0.png

    821c9869d620f6965535bb1e0dd891e9.png

    4.2 代码细节

    * 1:新建一个头文件,把在第三节里面生成的头文件内容复制粘贴过来。

    4391cd34fae091a2cd98ac927fce05b6.png

    de16741baa8c65b760faeaf058e1e66c.png

    4c233a66da7c2e8191254d6c20e3e7b6.png

    61ce9c043dbdb9191d04dc5168b832da.png

    * 2:具体cpp文件实现。

    当我把VC里面的代码直接粘贴过来的时候,就直接报错了。const char* 不可以转换为LPCWSTR。我想强制转化成LPCSTTR那肯定不可以的,但是强制转化为wchar *这个是可以的。因为报错的原因就是函数createFile()想要的文件名字应该是宽字符传进去的。但是当时我只解用了将普通字符转成宽字符的函数MultiByteToWideChar,不了解两种字符的可以自行百度一下。用了这个函数后报错没有了。

    但是,为了程序的健壮性我决定,把串口的名字暴露出来。然后新的问题出现了,当我想为了适应之前的程序,把串口的名字当中字符数组传进来的时候。java程序又报错,所以编译器太智能了也让人伤心。Java这边发现的我传入的就是一串字符,马上要求我把参数改成字符串类型。那也没办法,我没有能力自己开发一个IDE,所以就把string 传了进去。但是,我们知道C语言其实没有stirng这种类型,后来我又加了一点C++的代码,这样才勉强有了字符串这种类型。好吧,用函数把jstring 类型在转成宽字符类型。经过这次的修改,代码可以单独在VS里面跑起来了。

    VS单独运行代码:

    #include

    #include

    #include

    using std::string;

    int Comm(int nBaud, int parity, int bytesize, int stopbits, int accdatalength,string comName, char rBuf[])

    {

    DWORD rSize = 0;

    DWORD dwError;//清除错误

    COMSTAT cs;

    COMMTIMEOUTS timeouts;//超时数据结构

    DCB dcb;//串口通信配置文件---用LPDCB类型会报错

    HANDLE hCom;//串口的句柄(实例)| the instance of com

    //

    //将string转换为LPCWSTR类型

    //

    int len = comName.length();

    WCHAR buffer[256];

    ///memset原型---extern void *memset(void *buffer, int c, int count) buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度.//

    memset(buffer, 0, sizeof(buffer));//作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法

    MultiByteToWideChar(CP_ACP, 0, comName.c_str(), (len+1), buffer, sizeof(buffer) / sizeof(buffer[0]));

    printf("%d\n", buffer[0]);

    hCom = CreateFile(buffer,//串口的名字

    GENERIC_READ | GENERIC_WRITE, //串口打开方式

    0,//共享方式

    NULL,//安全属性

    OPEN_EXISTING,//指定文件的动作

    0,//文件属性---不指定就默认为同步IO

    NULL//指向模板文件的句柄

    );

    if (hCom == INVALID_HANDLE_VALUE)

    {

    return -1;

    }

    ///

    //同步IO需要设置读数据超时

    //

    if (!(GetCommTimeouts(hCom, &timeouts)))//获的COMMTIMEOUTS结构失败!

    {

    CloseHandle(hCom);

    }

    timeouts.ReadIntervalTimeout = 1000;//读取每个字符之间的超时

    timeouts.ReadTotalTimeoutMultiplier = 500;//读取一个字符的超时

    timeouts.ReadTotalTimeoutConstant = 5000;//固定总超时

    timeouts.WriteTotalTimeoutConstant = 0;//写入字符之间超时

    timeouts.WriteTotalTimeoutMultiplier = 0;//写入字符总超时

    if (!(SetCommTimeouts(hCom, &timeouts)))//设置COMMTIMEOUTS结构失败

    {

    CloseHandle(hCom);

    }

    //设置缓冲区大小

    ///

    if (!SetupComm(hCom, 500, 500))//设置读写缓冲区失败

    {

    CloseHandle(hCom);

    }

    //

    //设置波特率等其它读文件配置

    /

    if (GetCommState(hCom, &dcb) == 0)//获得DCB数据失败

    {

    CloseHandle(hCom);

    }

    //dcb.DCBlength = sizeof(DCB);

    dcb.BaudRate = nBaud;//波特率为4800

    dcb.Parity = parity;//校验方式为无校验

    dcb.ByteSize = bytesize;//数据位为8位

    dcb.StopBits = stopbits;//停止位为1位

    if (!SetCommState(hCom, &dcb))//设置串口通信配置项失败

    {

    CloseHandle(hCom);

    }

    //

    //清除缓冲区

    /

    PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);

    ///

    //清除错误

    ///

    if (!(ClearCommError(hCom, &dwError, &cs)))

    {

    CloseHandle(hCom);

    }

    //开始读取缓冲口的数据

    ///

    //读取串口数据

    if (INVALID_HANDLE_VALUE != hCom)

    {

    ReadFile(hCom, rBuf, accdatalength, &rSize, NULL);

    printf("%d \n", rSize);

    if (rSize)

    {

    CloseHandle(hCom);

    return 1;

    }

    else

    {

    CloseHandle(hCom);

    return 0;

    }

    }

    else

    {

    CloseHandle(hCom);

    return 2;

    }

    }

    void main()

    {

    int i;

    char buf[18] = { 0 };

    int a, b, c, d, e;

    char ComName[6];

    printf("请输入相关参数:");

    std::cin >> a >> b >> c >> d >> e>>ComName;

    while (1)

    {

    int t = Comm(a, b, c, d, e, ComName, buf);

    if (t == 1)

    {

    for (i = 0; i < 17; i++)

    {

    printf("%c ", buf[i]);

    }

    printf("\n");

    }

    else

    {

    printf("%d\n", t);

    break;

    }

    }

    }

    3:JNI中基本类型的处理

    完成这个作业之前我只是知道有JNI这个知识点,但是确实没有系统的学习过。但是我就自己学的一点点东西可以总结一下。java里面的基础类型可以放到C/C++里面使用但是像数组之类的数据类型,必须有Java认同的类型稍作处理,才可以在C/C++的环境里面运行。具体请参考:参考博客这片博客好像是sun官网的中翻,值得参考。

    4:成功的DLL源代码:

    #include "pch.h"

    #include "comm.h"

    #include

    #include

    #include

    using std::string;

    /

    //

    JNIEXPORT jint JNICALL Java_Com_Comm(JNIEnv* env, jobject, jint nBaud, jint parity, jint bytesize, jint stopbits, jint accdatalength,jstring comName, jbyteArray rBuf)

    {DWORD rSize = 0;

    DWORD dwError;//清除错误

    COMSTAT cs;

    COMMTIMEOUTS timeouts;//超时数据结构

    DCB dcb;//串口通信配置文件---用LPDCB类型会报错

    HANDLE hCom;//串口的句柄(实例)| the instance of com

    BYTE rBuffer[255];

    //

    //将jstring转换为LPCWSTR类型

    //

    WCHAR* buffer = (WCHAR*)env->GetStringChars(comName,NULL);

    hCom = CreateFile(buffer,//串口的名字

    GENERIC_READ | GENERIC_WRITE, //串口打开方式

    0,//共享方式

    NULL,//安全属性

    OPEN_EXISTING,//指定文件的动作

    0,//文件属性---不指定就默认为同步IO

    NULL//指向模板文件的句柄

    );

    if (hCom == INVALID_HANDLE_VALUE)

    {

    return -1;

    }

    ///

    //同步IO需要设置读数据超时

    //

    if (!(GetCommTimeouts(hCom, &timeouts)))//获的COMMTIMEOUTS结构失败!

    {

    CloseHandle(hCom);

    }

    timeouts.ReadIntervalTimeout = 1000;//读取每个字符之间的超时

    timeouts.ReadTotalTimeoutMultiplier = 500;//读取一个字符的超时

    timeouts.ReadTotalTimeoutConstant = 5000;//固定总超时

    timeouts.WriteTotalTimeoutConstant = 0;//写入字符之间超时

    timeouts.WriteTotalTimeoutMultiplier = 0;//写入字符总超时

    if (!(SetCommTimeouts(hCom, &timeouts)))//设置COMMTIMEOUTS结构失败

    {

    CloseHandle(hCom);

    }

    //设置缓冲区大小

    ///

    if (!SetupComm(hCom, 500, 500))//设置读写缓冲区失败

    {

    CloseHandle(hCom);

    }

    //

    //设置波特率等其它读文件配置

    /

    if (GetCommState(hCom, &dcb) == 0)//获得DCB数据失败

    {

    CloseHandle(hCom);

    }

    //dcb.DCBlength = sizeof(DCB);

    dcb.BaudRate = nBaud;//波特率为4800

    dcb.Parity = parity;//校验方式为无校验

    dcb.ByteSize = bytesize;//数据位为8位

    dcb.StopBits = stopbits;//停止位为1位

    if (!SetCommState(hCom, &dcb))//设置串口通信配置项失败

    {

    CloseHandle(hCom);

    }

    //

    //清除缓冲区

    /

    PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);

    ///

    //清除错误

    ///

    if (!(ClearCommError(hCom, &dwError, &cs)))

    {

    CloseHandle(hCom);

    }

    //开始读取缓冲口的数据

    ///

    //读取串口数据

    if (INVALID_HANDLE_VALUE != hCom)

    {

    ReadFile(hCom, &rBuffer, accdatalength, &rSize, NULL);

    if (rSize)

    {

    jbyte* term;//将RBuffer中的值赋给rBuf

    term = env->GetByteArrayElements(rBuf,FALSE);

    for (int i = 0; i < accdatalength; i++)

    {

    term[i] = rBuffer[i];

    }

    env->ReleaseByteArrayElements(rBuf,term, JNI_COMMIT);

    CloseHandle(hCom);

    return 1;

    }

    }

    else

    {

    CloseHandle(hCom);

    return 1;

    }

    env->ReleaseStringChars(comName,(jchar *)buffer);//释放空间

    CloseHandle(hCom);

    return 2;

    }

    注:代码写在自己新建的和头文件同名的自己建立的源文件(.cpp)里面。

    4.3 配置

    在生成DLL文件之前,我们还必须做一些重要的配置。

    1:把java jdk里面的一些文件拷贝到DLL文件里面去。

    aa9ac7c2804520c710baf5aa4a16b59c.png

    3c42c5c6dcc49e795697d101efff6edd.png

    将框起来的三个头文件复制到DLL源程序的文件里面。

    a4e665d506dec80174932ac7f6b5f68a.png

    2:修改一下DLL项目的配置:

    6834495230661d1ac33e236fbbccbe29.png

    右键项目 ---> 属性--->VC++目录--->包含目录(把DLL程序所在的文件路径添加进去)

    56a2bbbba8b812ddd6b5fee2905f09db.png

    最后,我们在点击生成。就OK啦。

    3acbde09df66126fd22660f5bf4a4958.png

    到此结束啦,希望可以帮助到你!

    展开全文
  • 基于C语言的java串口通信程序目录1.前言2.windows ?串口通信API3.C/C++封装 ?动态运行库4.JAVA-JNI ?java程序调用C++程序一、前言ensp?;写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51...

    基于C语言的java串口通信程序

    目录

    1.前言

    2.windows ?串口通信API

    3.C/C++封装 ?动态运行库

    4.JAVA-JNI ?java程序调用C++程序

    一、前言

    ensp?;写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51单片机传送来的一些数据。单片机的数据由USB转串口发送至上位机,要处理这些数据,就会用到windows提供一些API(Application Programming Interface,应用程序接口)。java在安装了相关的包后,比如JNative.jar,可以直接用该包提供的接口来进行调用windowsAPI。但是我才接触java。而且整个作业,我仅仅只要一部分来处理这个数据。安装一个java包,实在是大可不必,所以就用C/C++来写一个的终端,封装一下放在java程序里面。

    二、windows串口通信API

    ??2.1 ? 工具:VC++6.0

    ??2.2 ? 概述:windows操作系统的设备无关性将所有的外设都当做文件来操作,那么我们写串口通信就直接将串口当做文件来读写。那么我们打开串口后一定要记得关闭,这个很重要

    ??2.3 ? 串口通信程序概述

    2.3.1 打开/关闭串口

    HANDLE WINAPI CreateFileW(

    LPCWSTR lpFileName,

    DWORD dwDesiredAccess,

    DWORD dwShareMode, //共享模式

    LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性

    DWORD dwCreationDisposition, //指定文件的动作

    DWORD dwFlagsAndAttributes, //文件属性---不指定就默认为同步IO

    HANDLE hTemplateFile //模板文件

    );

    BOOL WINAPI CloseHandle(

    HANDLE hObject

    );

    返回值:一个串口的句柄。

    参数解释:

    lpFileName——串口名字。?当为COM1~COM9的时候可以直接写入但是大于10会有另外的写法。以COM10为例:\.\COM10。

    lpFileName——打开方式。?简单来说这个就是打开文件是读还是写。GENERIC_READ(读)|GENERIC_WRITE(写)。还有其它的两个值,详细请在编辑器中直接按下F12看看他们的定义。

    如果我们要定义一个同步IO的话,我们的打开方式必须要有读动作。

    dwShareMode指定该端口的共享属性。?对于不能共享的串口,它必须设置为0。这就是文件与通信设备之间的主要差异之一。如果在当前的应用程序调用CreateFile()时,另一个应用程序已经打开了串口,该函数就会返回错误代码,原因是两个应用程序不能共享一个端口。然而,同一个应用程序的多个线程可以共享由CreateFile()返回的端口句柄,并且根据安全性属性设置,该句柄可以被打开端口的应用程序的子程序所继承。

    dwCreationDisposition指定文件的动作。?指定如果CreateFile()正在被已有的文件调用时应采取的动作。因为串口总是存在,fdwCreate必须设置成OPEN_EXISTING。该标志告诉Windows不用企图创建新端口,而是打开已经存在的端口。

    调用该函数后,如果没有穿件成功将会返回INVALID_HANDLE_VALUE。

    2.3.2 配置串口通信

    (1)?当我们设置同步IO通信的时候,需要设置一下通信超时。一般情况下,我们用GetCommTimeouts来获得COMMTIMEOUTS结构体,再利用SetCommTimeouts来写入。

    BOOL WINAPI GetCommTimeouts(

    HANDLE hFile,

    LPCOMMTIMEOUTS lpCommTimeouts

    );

    BOOL WINAPI SetCommTimeouts(

    HANDLE hFile,

    LPCOMMTIMEOUTS lpCommTimeouts

    );

    COMMTIMEOUTS:

    typedef struct _COMMTIMEOUTS {

    DWORD ReadIntervalTimeout; /* 设置两个字符之前的最大读取时间 */

    DWORD ReadTotalTimeoutMultiplier; /* 设置每个字符的读取时间 */

    DWORD ReadTotalTimeoutConstant; /* 设置所有字符读取的最大时间 */

    DWORD WriteTotalTimeoutMultiplier; /* 设置每个字符的写入时间 */

    DWORD WriteTotalTimeoutConstant; /* 设置所有字符的写入时间 */

    } COMMTIMEOUTS,*LPCOMMTIMEOUTS;

    (2)?设置波特率等相关参数

    仍然先用GetCommState得到DCB结构,修改其中的某些参数后再用SetCommState写入DCB结构。

    BOOL WINAPI GetCommState(

    HANDLE hFile,

    LPDCB lpDCB

    );

    BOOL WINAPI SetCommState(

    HANDLE hFile,

    LPDCB lpDCB

    );

    DCB数据结构我们初级学者需要关注:波特率、校验位、停止位、发送数据位数。

    (3)?设置缓冲区大小,根据程序要接收/发送的数据大小来决定。

    BOOL WINAPI SetupComm(

    HANDLE hFile,

    DWORD dwInQueue,

    DWORD dwOutQueue

    );

    (4)?读取/写入数据

    BOOL WINAPI ReadFile(

    HANDLE hFile,

    LPVOID lpBuffer, //存放数据的缓冲区

    DWORD nNumberOfBytesToRead, //一次想要读入的数据长度

    LPDWORD lpNumberOfBytesRead, //实际读入的数据长度

    LPOVERLAPPED lpOverlapped

    );

    BOOL WINAPI WriteFile(

    HANDLE hFile,

    LPCVOID lpBuffer,

    DWORD nNumberOfBytesToWrite,

    LPDWORD lpNumberOfBytesWritten,

    LPOVERLAPPED lpOverlapped

    );

    2.3.3 配置串口通信

    基于C语言的java串口通信程序 相关文章

    java-字符流

    前言 昨天学习了java的字节流,可以用字节流来读写文件。但是读取和写入的内容并不是内容本身,而是其对应的ASCII码。今天学习的字符流就可以规避这个问题,将内容以字符的形式进行读写。 使用字符流读取文件 1 package IO流; 2 3 import java.io.FileReader

    Java进阶专题(二十五) 分布式锁原理与实现

    前言 ?现如今很多系统都会基于分布式或微服务思想完成对系统的架构设计。那么在这一个系统中,就会存在若干个微服务,而且服务间也会产生相互通信调用。那么既然产生了服务调用,就必然会存在服务调用延迟或失败的问题。当出现这种问题,服务端会进行重试等

    Java 经验书

    目录 目录 目录 正文 字节 转 String Base64Encoder 的使用 正文 字节 转 String 在开发中,会遇到各种 byte 类型转换为 String 的情况 下面做些记录 // 1. String.valueOf() 效率最高的方法String s = String.valueOf('c'); String s = String.valueOf(new c

    Java常用的函数式接口

    Supplier T 接口 java.util.function.Supplier T 接口仅包含一个无参的方法: T get() :用来获取一个泛型参数指定类型的对象数据。 Supplier T 接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的 get方法就会产生什么类型的数据。 示例 pack

    实验-继承super.doc

    Account.java package com.atguigu.exer2;public class Account { private int id;//账号 private double balance;//余额 private double annualInterestRate;//年利率 public Account(int id, double balance, double annualInterestRate) { super(); this.

    一篇文章图文并茂地带你轻松学完 JavaScript 闭包

    JavaScript 闭包 为了更好地理解 JavaScript 闭包,笔者将先从 JavaScript 执行上下文以及 JavaScript 作用域开始写起,如果读者对这方面已经了解了,可以直接跳过。 1. 执行上下文 简单来说, JavaScript 有三种代码运行环境,分别是: Global Code 是 JavaS

    Java基础(10) | 抽象

    #什么是抽象方法 加上abstract关键字,然后去掉方法体,直接分号结束 抽象方法所在的类必须是抽象类才行,在class之前写上abstract即可 public abstract class Animal{ //抽象类 public abstract void eat(); //抽象方法} # 注意事项 抽象方法所在的类必须是

    专业Java报表工具Stimulsoft Reports.Java常见问题解答(二)

    Stimulsoft Reports.Java是一个专为在Java应用程序中的报表进行交互和处理的报表工具。 Java技术允许在不同的平台、不同的操作系统和不同的硬件上使用程序。正因为这样,Stimulsoft Reports.Java现在几乎在任何地方都可用,同时还是一个拥有高质量的功能和用

    Unit5Java数据类型

    Unit5Java数据类型 一、Java标识如何命名 标识符就是名字,包括变量名,类名,方法名 Java标识符命名规则:由数字,字母,$组成,不能以数字开头,不能是关键字 二、Java关键字 abstract continue for new switch assert default goto package synchronized

    Java基础学习3

    Java语法学习3 基本运算符 关系运算符返回结果为布尔类型 %:取余 模运算 +、-、*、/、% :二元运算符 两个变量间的运算 ++、-- 一元运算符 package Study;public class demo01 { public static void main(String[] args) { //ctrl + d :复制当前行到下一行

    展开全文
  • C51-ARM C语言串口调试发送数据及接收数据以观察所写程序得到结果是否正确
  • 摘要:VC/C++源码,其它分类,单片机控制 51单片机串口通讯C语言源码,其中串口测试程序完成串口发送任意字符到单片机,单片机通过P0口LED灯显示。比如 发送16进制的 00 单片机的LED灯全亮 发送FF灯全灭  首先 烧写...
  • 这是一个最简单的Linux下的C语言串口驱动程序,使用了最简单的方式实现了异步发送接收api接口,并且有demo使用例程。
  • 51单片机串口通讯C语言源码,其中串口测试程序完成串口发送任意字符到单片机,单片机通过P0口LED灯显示。比如 发送16进制的 00 单片机的LED灯全亮 发送FF灯全灭 首先 烧写程序到单片机 晶振 11.0592MHZ 连接好串口...
  • 本文着重介绍三线多环回型结构电缆结构的构成,设计了新的发送/接收收程序来防止信息丢失,用Turbo C语言实现了个人计算机同智能仪表的通讯程序设计.
  • 本意是通过串口发送4个字节数据,单片机串口接收后,发送回4个字节数据(在串口助手显示出来)。 但我通过uvison3下载到stc12c5a60s2最少单片机系统,通过串口测试工具(波特率19200,校验位:无,数据位:8,停止...
  • 串口通信——写串口C语言

    千次阅读 2017-07-28 12:59:32
    C语言程序,将一个文件中保存的控制LED的十六进制数读取,并写入串口由433M发送至连接有另一433M的MSP430单片机  C语言程序:  #include #include FILE * fileFP; int main(void) { FILE *fp; int temp; int ...
  • Arduino 串口发送指令程序

    千次阅读 2019-03-13 19:28:35
    从社团成员到作为社团主席的我,经历过做项目的考验和敲程序的洗礼,从中或多或少有一定的知识积累。其中,自己掌握的语言有C语言、C sharp、C++;熟悉各种常用软件:Arduino IDE、SolidWorks、RDworks、Proteus、VS...
  • //串口发送忙标志位 BOOL UartReceived; //串口数据接收完成标志位 BYTE UartRecvStep; //串口数据接收控制 BYTE TimeOut; //串口通讯超时计数器 BYTE xdata TxBuffer[256]; //串口数据发送缓冲区 BYTE xdata Rx...
  • 通过C语言实现51单片机串口通信,上位机发送相应数字单片机接收数字点亮相应小灯并返回接收到的数据;
  • 装有linux系统的PC和串口微型打印机相连,怎么通过C语言设计一个串口程序,把打印机的控制指令比如(ESC HT )十六进制(1B 09), (ESC &) 十六进制(1C 26) , 这样的指令,通过串口程序发送给打印机达到控制...
  • C语言编写串口程序

    千次阅读 2005-10-27 10:30:00
    在当今,流行的编程软件种类繁多,它们编程方便、易于维护,但是在与硬件直接打交道和编制系统软件时却...这是因为通讯的各个计算机CPU速度不一样(这会导致“错帧”)以及发送发送数据速度比接收机接收速度快(这
  • 本文提供了设置串口通讯的接口,方便大家对程序的复用,感觉还是面向对象的语言更方便呀;在给模块发送指令后需要读取模块返回的数据时,保险起见采用阻塞式读取,且串口一次只能读取8位byte数据,注意读取数据的...
  • 串口发送接收程序,使用于使用串口发送或接收数据的场合。
  • 用STC15F2K61S2芯片的串口发送字符串的C语言程序
  • 通过pc端的c++语言编程实现与单片机的通讯,可用于pc端c++处理程序后给单片机发送一个trigger指令的情况。 使用方法: 1.将contest.cpp中的代码加入需要的程序中 2.将PCB板上UART1的IO口通过usb转TTL工具与电脑的...
  • 在执行串口测试任务时,PC端向下位机发送串口指令有两种常用的格式:ASCII字符串,比如:AT+CFUN=1整数数组,比如:[0x59, 0x03, 0x01, 0x02, 0x03]在Python程序中,PySerial库的数据收发API的参数都是bytes类型。...
  • 串口通讯程序,单片机与上位机的通讯,c语言源代码,发送字符或者字符串
  • 温湿度传感器51单片机C语言程序功能:波特率9600 串口发送温湿度数据 数据格式:湿度 温度 校验和 例如串口发送数据 59 00 24 00 53 则湿度为59 温度为24 校验和为53 公司:DHT11参考例程 芯片:M8 晶振:外部 7...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 185
精华内容 74
关键字:

串口发送程序c语言

c语言 订阅