矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖
楼主: hoverxx

很实用的帖子!VB和51单片机串口通信讲解

[复制链接]
     
发表于 2018-11-15 09:23:55 | 显示全部楼层
VB看起来不舒服还是C好看。
#include "stdafx.h"
#include "SerialPort.h"

using namespace std;

//CSerialPort
CSerialPort::CSerialPort()
{
        m_RunThead = false;

}


CSerialPort::~CSerialPort()
{
}
//'设置串口通讯参数
bool CSerialPort::SetCommParam(int lBaudRate, int cByteSize, int cStopBits, int cParity, int cEOFChar) {

        DCB  dc;
        bool flag = false;
                if (GetCommState(m_HANDLE, &dc) != NULL) {
                        ;
                dc.BaudRate = lBaudRate;
                dc.ByteSize = cByteSize;
                dc.StopBits = cStopBits;
                dc.Parity = cParity;
                dc.EofChar = cEOFChar; //EofChar
                flag = SetCommState(m_HANDLE, &dc);
        }
        return flag;
}
HANDLE CSerialPort::OpenCOM(unsigned char lComPort, int lBaudRate, int cByteSize, int cStopBits, int cParity, int cEOFChar) {
        char  strcom[30];
        sprintf(strcom, "\\\\.\\com%d", lComPort);

        m_HANDLE = CreateFile(strcom, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, /*FILE_FLAG_OVERLAPPED*/0, 0);//
        if (m_HANDLE != INVALID_HANDLE_VALUE) {
                SetCommTimeOut();//'设置超时
                SetCommBuffer(); //' 8, 8 '设置读、写缓冲区大小
                SetCommParam(lBaudRate, cByteSize, cStopBits, cParity, cEOFChar);
        }
        return m_HANDLE;
}


//'设置串口超时
bool CSerialPort::SetCommTimeOut(int dwReadTimeOut, int dwWriteTimeOut) {

        COMMTIMEOUTS ct;
        ct.ReadIntervalTimeout = 1;// dwReadTimeOut;// '读操作时,字符间超时 MAXDWORD
        ct.ReadTotalTimeoutMultiplier = 1;// 30;// dwReadTimeOut;// '读操作时,每字节超时
        ct.ReadTotalTimeoutConstant = 1;// 30;// dwReadTimeOut;// '读操作时,固定超时(总超时 = 每字节超时*字节数 + 固定超时)
        ct.WriteTotalTimeoutMultiplier = dwWriteTimeOut; //'写操作时,每字节超时
        ct.WriteTotalTimeoutConstant = dwWriteTimeOut; //'写操作时,固定超时(总超时=每字节超时*字节数+固定超时)
        return (SetCommTimeouts(m_HANDLE, &ct));
}
//'设置串口读写缓冲区大小
bool CSerialPort::SetCommBuffer(int dwBytesRead, int dwBytesWrite) {

        if (m_HANDLE == NULL) return false;
        return SetupComm(m_HANDLE, dwBytesRead, dwBytesWrite);
}
//        '清空串口缓冲区
void CSerialPort::ClearComm(bool InBuffer, bool OutBuffer) {
        if (InBuffer == true)        PurgeComm(m_HANDLE, PURGE_RXABORT | PURGE_RXCLEAR);                // '清空输入缓冲区
        if (OutBuffer == true)         PurgeComm(m_HANDLE, PURGE_TXABORT | PURGE_TXCLEAR);                        //'清空输出缓冲区
}
//'关闭串口
void  CSerialPort::CloseComm(void) {
        ClearComm();
        CloseHandle(m_HANDLE);
}
//'读串口
int CSerialPort::ReadComm(BYTE *BytesBuffer, DWORD  bufferLong) {
        DWORD dwBytesRead = 0;
        //DWORD dwErrorFlags;
        //COMSTAT ComStat;
        //OVERLAPPED m_osRead;

        //ClearCommError(m_HANDLE, &dwErrorFlags, &ComStat);
        ClearComm(true, false);
        ReadFile(m_HANDLE, BytesBuffer, bufferLong, &dwBytesRead, /*&m_ov*/0);
        return dwBytesRead;
}

//'写串口
int CSerialPort::WriteComm(BYTE *BytesBuffer, int byteLong) {
        DWORD dwBytesWrite;

        ClearComm(false, true);
        WriteFile(m_HANDLE, BytesBuffer, byteLong, &dwBytesWrite, /*&m_ov*/0);
        return dwBytesWrite;
}


HANDLE CSerialPort::StartThread() {
        m_Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)this->CommThread, this, 0, NULL);
        //m_Thread = (HANDLE)_beginthread((void(__cdecl *) (void *))CommThread, 0, this);
        return m_Thread;
}

bool CSerialPort::RestartThread()
{
        ResumeThread(m_Thread);
        return TRUE;
}
//
// Suspend the comm thread
//
bool CSerialPort::StopThread() {
        SuspendThread(m_Thread);
        return TRUE;
}

BOOL CSerialPort::CloseThread() {
        m_RunThead = true;
        // Sleep(100);
        CloseHandle(m_Thread);
        return true;
}

int CSerialPort::GetSerialTXDdata(CSerialPort *port,BYTE *buf,int cnt) {

        memcpy(buf, port->m_RXDbuf, cnt);
        return cnt;
}

void CSerialPort::GetCommPortInfo(COMM_PORT_DATA *portinfo, unsigned char id) {

        portinfo->name = id;
        portinfo->index = 0;

        for (int i = 0; i<15; i++)        portinfo->Adr[i] = 10 + i;
        portinfo->addrCnt = 10;
        portinfo->nFrame = 2;
        portinfo->CurFrame = 0;
}
回复 支持 反对

使用道具 举报

     
发表于 2018-11-15 09:24:26 | 显示全部楼层
class CSerialPort
{
public:
        CSerialPort();
        ~CSerialPort();

private:
        HANDLE                                m_Thread;
        HANDLE                                m_hComm;
        HANDLE                                m_HANDLE;
        unsigned char                m_TXDbuf[100];
        unsigned char                m_RXDbuf[512];
        int                                        m_RXD_CNT;
        bool                                m_RunThead;        //采用变量置位 停止线程
public:
        // start/stop comm watching
        COMM_PORT_DATA                s_PortInfo;

        HANDLE                 StartThread();
        bool                RestartThread();
        bool                StopThread();
        BOOL                CloseThread();

        bool SetCommTimeOut(int dwReadTimeOut = MAXDWORD, int dwWriteTimeOut = 3);
        bool SetCommBuffer(int dwBytesRead = 1024, int dwBytesWrite = 512);
        void ClearComm(bool InBuffer = true, bool OutBuffer = true);
        bool SetCommParam(int lBaudRate = 9600, int cByteSize = 8, int cStopBits = 0, int cParity = 0, int cEOFChar = 26);
        void CloseComm();
        void GetCommPortInfo(COMM_PORT_DATA *portinfo, unsigned char id);
        HANDLE OpenCOM(unsigned char lComPort, int cParity = 0, int lBaudRate = 9600, int cByteSize = 8, int cStopBits = 0, int cEOFChar = 26);
        int ReadComm(BYTE *BytesBuffer, DWORD  bufferLong = 1024);
        int WriteComm(BYTE *BytesBuffer, int byteLong);
        //int Get_Comm_Station(void);

        //protected:
        static void        CommThread(LPVOID pParam);
        int GetSerialTXDdata(CSerialPort *port, BYTE *buf, int cnt);


};


回复 支持 反对

使用道具 举报

     
发表于 2018-11-16 11:23:26 | 显示全部楼层
Mon51 发表于 2018-11-15 09:24
class CSerialPort
{
public:

谢谢分享,刚刚接触单片机和VB,请教vb语言写程序注入单片机用什么软件转为汇编语言,谢谢。
回复 支持 反对

使用道具 举报

     
发表于 2018-11-16 11:23:48 | 显示全部楼层
Mon51 发表于 2018-11-15 09:24
class CSerialPort
{
public:

谢谢分享,刚刚接触单片机和VB,请教vb语言写程序注入单片机用什么软件转为汇编语言,谢谢。
回复 支持 反对

使用道具 举报

     
发表于 2018-11-17 13:32:08 | 显示全部楼层
这程序写得有点不专业

1、VB下的字符串是Unicode编码,不是ANSI/GB编码。无论半角、全角都占用2个字节。Unicode下的半角英文字符一般低位与ANSI相同,但Unicode编码的中文编码和GB、BIG5都不一样。

2、String字符串变量和Byte()数组可以直接赋值。但如果你将一个字符串赋值给Byte数组,得到的是Unicode编码的字节。

比如:
Dim strString As String '声明一个字符串
Dim bytBytes() As Byte '声明一个活动Byte数组。

strString = “Hello矿石收音机论坛”

bytBytes() = strString

你将得到一个24字节的bytBytes(),半角编码的高位是0、低位是ANSI(0-127)。全角中文编码是Unicode中文编码。

3、Unicode编码的String和ANSI/GBK编码的String转换函数是Strconv函数。如果想给串口发送ANSI/GBK编码的字符串,需要先将VB下的String用Strconv转码,赋值给一个Byte数组。VB下有Byte数据类型,根本不需要自己编写复杂的取高位、低位的代码(这是QB下的做法)。

比如:
Dim strString_Unicode As String '声明一个字符串
Dim strString_ANSI_GB As String '声明一个字符串
Dim bytBytes_Unicode() As Byte '声明一个活动Byte数组。
Dim bytBytes_ANSI_GB() As Byte '声明一个活动Byte数组。

第一种用法:得到一个ANSI/GB编码字符串(但无法在VB下正常显示)

strString_Unicode = “Hello矿石收音机论坛”
strString_ANSI_GB = Strconv(strString_Unicode,  FormUnicode)


第二种用法:从一个VB字符串直接得到一个ANSI/GB编码Byte数组。
(这个例子说明:VB下某些情况String和Byte数组是可以相互赋值的)

strString_Unicode = “Hello矿石收音机论坛”
bytBytes_ANSI_GB() = Strconv(strString_Unicode,  FormUnicode)


4、如果你从串口接收到的数据是ANSI/GB码(建议用Byte数组),可以用Strconv函数转换成Unicode码。

比如:
Dim strString_Unicode As String '声明一个字符串
Dim strString_ANSI_GB As String '声明一个字符串
Dim bytBytes_Unicode() As Byte '声明一个活动Byte数组。
Dim bytBytes_ANSI_GB() As Byte '声明一个活动Byte数组。

'从串口接口数据,存储在bytBytes_ANSI_GB()数组里。

strString_Unicode = Strconv(bytBytes_ANSI_GB(),  Unicode) '将你接受的ANSI/GB编码Byte数据转换为Unicode字符串,在VB下可直接显示。

5、Strconv函数里的String也可以是Byte数组。在VB6下,对String变量操作的函数在很多情况也可以对Byte数组操作。

6、对于数据发送、接收的程序,我一般习惯用Byte数组。其他类型的数组(比如Long、Integer)可以用CopyMemory函数转换为Byte数组。CopyMemory是一个API函数,不是VB自带函数,需要提前声明。
回复 支持 反对

使用道具 举报

     
发表于 2018-11-22 17:26:11 | 显示全部楼层
pdshyh 发表于 2018-11-16 11:23
谢谢分享,刚刚接触单片机和VB,请教vb语言写程序注入单片机用什么软件转为汇编语言,谢谢。

早期大概是90年,有BASIC FOR 51可以用高级语言来写单片机程序,现在个人是用C,用KEIL编译写入单片机。不需要转化成汇编。
回复 支持 反对

使用道具 举报

     
发表于 2018-11-22 17:26:40 | 显示全部楼层
pdshyh 发表于 2018-11-16 11:23
谢谢分享,刚刚接触单片机和VB,请教vb语言写程序注入单片机用什么软件转为汇编语言,谢谢。

早期大概是90年,有BASIC FOR 51可以用高级语言来写单片机程序,现在个人是用C,用KEIL编译写入单片机。
回复 支持 反对

使用道具 举报

     
发表于 2018-11-22 18:19:08 | 显示全部楼层
Mon51 发表于 2018-11-22 17:26
早期大概是90年,有BASIC FOR 51可以用高级语言来写单片机程序,现在个人是用C,用KEIL编译写入单片机。

谢谢指教,我网搜搜看看,谢谢。
回复 支持 反对

使用道具 举报

     
发表于 2019-5-18 10:58:37 | 显示全部楼层
谢谢分享,学习。学习。辛苦了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2024-4-26 21:10

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表