⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 Linux环境下的串口通讯程序
💻 CPP
字号:
/*
 * for Embedded System Develoe and Debug
 * Main used in monitor the BLOB bootstrap
 * The more detailed of BLOB see BLOB source program
 *
 * Copyright(C) HCC
 * HuNan Computer Information Software Co.,Ltd.
 * ZouWeiJun 2001-07-20
 */
//---------------------------------------------------------------------------
#include <clx.h>
#pragma hdrstop

#include "main.h"
#include "checkcom.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.xfm"

#include <mem.h>
#include <fstream.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>

//#include "api232-c.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//#pragma resource "*.dfm"
TFormMain *FormMain;
unsigned int Lines = 0;
int com_fd;
TCheckCom *threadCC;

//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::Button_browseClick(TObject *Sender)
{
	OpenDialog_df->Execute();
    Edit_fn->Text = OpenDialog_df->FileName;
}
//---------------------------------------------------------------------------

/*
void TFormMain::fnPortSet(void)
{
	int port[4]    = {0x01, 0x02, 0x03, 0x04};
	int databit[4] = {0x00, 0x01, 0x02, 0x03};
	int stopbit[2] = {0x00, 0x04};
	int parity[5]  = {0x00, 0x08, 0x18, 0x28, 0x38};
	int baudrate[6]= {0x07, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};

	dn_port    = port[RadioGroup_port->ItemIndex];
    dn_databit = databit[RadioGroup_databit->ItemIndex];
    dn_stopbit = stopbit[RadioGroup_stopbit->ItemIndex];
    dn_parity  = parity[RadioGroup_parity->ItemIndex];
    dn_baudrate= baudrate[RadioGroup_baudrate->ItemIndex];
}
*/

void __fastcall TFormMain::Button_dlClick(TObject *Sender)
{
	if(nDownState == eDownload)
    {
		if (MessageDlg("Are you sure cancel downloading ?",	mtConfirmation,
        				TMsgDlgButtons() << mbYes << mbNo, 0) == mrNo)
        	return;
    	nDownCancel = eCancel;
        Button_dl->Caption = "Download";
        nDownState = eIdle;
        return;
    }

	ProgressBar_fp->Position = 0;

	if( nPortStatus != ePORT_OPEN )
    {
    	Application->MessageBox("Serial port not open, cann't download !",
        		   "Error",	 TMessageButtons() <<smbAbort);
    	return;
    }
    if(Edit_fn->Text == "")
    {
    	Application->MessageBox("Please input download file !",
        		   "Error",	 TMessageButtons() <<smbAbort);
        return;
    }

    char fbuf[256];
    Edit_fn->SelectAll();
    Edit_fn->GetSelTextBuf(fbuf, Edit_fn->SelLength+1);
    fstream fImage(fbuf, ios::in|ios::binary);
    if(!fImage)
    {
    	Application->MessageBox("Open file failed !",
        		   "Error",	 TMessageButtons() <<smbAbort);
        return;
    }

   	Button_dl->Caption = "Cancel";
    nDownState = eDownload;
    nDownCancel = eDowning;

    GroupBox_com->Enabled = false;

    fImage.seekg(0, ios::end);

    unsigned long flen = fImage.tellg();
    unsigned char * buf;
    try
    {
    	buf = new unsigned char[flen+1];
        memset(buf, 0, flen+1);
    }
    catch(std::bad_alloc error)
    {
    	Application->MessageBox("malloc new memory failed !",
        		   "Error",	 TMessageButtons() <<smbAbort);
        fImage.close();
        return;
    }

    fImage.seekg(0, ios::beg);
    fImage.read(buf, flen);

    unsigned int read_num = fImage.gcount();
    while( read_num < flen )
    {
    	fImage.read(buf+read_num, flen-read_num);
        read_num += fImage.gcount();
    }
    UUEncode(buf, flen);
	fImage.close();
    delete []buf;

   	Button_dl->Caption = "Download";
    nDownState = eIdle;
    nDownCancel = eCancel;

    GroupBox_com->Enabled = true;
}
//---------------------------------------------------------------------------


bool TFormMain::fnOpenPort(void)
{
    if(sio_open(RadioGroup_port->ItemIndex) != SIO_OK)
    {
		nPortStatus = ePORT_CLOSE;
        return false;
    }
//	fnPortSet();
/*
    if(sio_ioctl(dn_port, dn_baudrate, dn_databit|dn_stopbit|dn_parity) != SIO_OK)
    {
        sio_close(dn_port);
		nPortStatus = ePORT_CLOSE;
        return false;
    }

    if(sio_cnt_irq(dn_port, fnIsrReceive, 1) != SIO_OK)
    {
        sio_close(dn_port);
		nPortStatus = ePORT_CLOSE;
        return false;
    }
*/
    nPortStatus = ePORT_OPEN;
    return true;
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::FormCreate(TObject *Sender)
{
	nDownState = eIdle;
    signal(SIGUSR1, fnIsrReceive);
    threadCC = new TCheckCom(true);
    com_fd = p_com_fd = -1;
	fnOpenPort();
}
//---------------------------------------------------------------------------

/* Interrupt Service Routine */
void fnIsrReceive(int port)
{
	char buf[16*1024];
    char tmpbuf[16*1024];
    char * p;
	int recv_num = 0;
	int deal_count = 0;

/*
	recv_num = sio_iqueue(port);
    if(recv_num >= sizeof(buf))
    {
    	MessageBox(0, "No enough data buffer receive data",
        		   "Error",	MB_ICONERROR | MB_SYSTEMMODAL);
        return;
    }
*/
    recv_num = read(com_fd, buf, sizeof(buf)-1);
    while(recv_num > 0)
    {
        buf[recv_num] = 0;

        while(deal_count < recv_num)
        {
		    tmpbuf[0] = 0;
            p = tmpbuf;
        	while(buf[deal_count]>=0x20)
            {
                *p++ = buf[deal_count++];
            }
            *p = 0;
            if(tmpbuf[0])
	    		FormMain->Memo_readmsg->Lines->Strings[Lines] =
		    		FormMain->Memo_readmsg->Lines->Strings[Lines] + tmpbuf;

    		if( buf[deal_count] == '\r' )
            {
            	deal_count++;
			    continue;
            }
	    	else if( buf[deal_count] == '\n' )
		    {
			    Lines++;
                if(Lines > 10000)
                {	/* lines too big, display error ?? */
                	Lines = 0;
                	FormMain->Memo_readmsg->Clear();
                    continue;
                }
	    		FormMain->Memo_readmsg->Lines->Add("");
                deal_count++;
			    continue;
    		}
	    	else if( buf[deal_count] == '\t' )
		    {
			    FormMain->Memo_readmsg->Lines->Strings[Lines] =
    				FormMain->Memo_readmsg->Lines->Strings[Lines] + "    ";
                deal_count++;
		    	continue;
    		}
	    	else if( buf[deal_count] == '\b' )
		    {
    			unsigned char len = FormMain->Memo_readmsg->Lines->Strings[Lines].Length();
	    		FormMain->Memo_readmsg->Lines->Strings[Lines] =
		    		FormMain->Memo_readmsg->Lines->Strings[Lines].Delete(len, 1);
                deal_count+=3;
                continue;
	    	}
            else
        	    deal_count++;
        }
        recv_num = read(com_fd, buf, sizeof(buf)-1);
    }

}
//---------------------------------------------------------------------------

void __fastcall TFormMain::RadioGroup_portClick(TObject *Sender)
{
/*
	if( nPortStatus == ePORT_OPEN )
    	sio_close(dn_port);
*/
    fnOpenPort();
}
//---------------------------------------------------------------------------


void __fastcall TFormMain::RadioGroup_databitClick(TObject *Sender)
{
    sio_set();
/*
	fnPortSet();
    sio_ioctl(dn_port, dn_baudrate, dn_databit|dn_stopbit|dn_parity);
*/
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::FormClose(TObject *Sender, TCloseAction &Action)
{
    close(com_fd);
    threadCC->Terminate();
/*
	if(nPortStatus == ePORT_OPEN)
    	sio_close(dn_port);
*/
}
//---------------------------------------------------------------------------


void TFormMain::fnSerialOutputString(const unsigned char * s)
{
	while( *s )
    	fnSerialOutputByte(*s++);
}

void TFormMain::fnSerialOutputByte(const unsigned char c)
{
    int i, j = 0;

    while( j<1 )
        j = write(com_fd, (unsigned char *)&c, 1);
/*
    for(i=0; i<10; i++)
    {
        if( j > 0 )
            break;
        else if( j == 0)
            continue;
        else
            Application->MessageBox(strerror(errno), "Error", TMessageButtons() <<smbAbort);
        usleep(10);
    }
    if(i >= 10)
    {
        Application->MessageBox("Write serial port error", "Error", TMessageButtons() <<smbAbort);
        return;
    }
*/
	if( c == '\n' )
    	fnSerialOutputByte('\r');
}

void TFormMain::UUEncode(unsigned char * bufBase, int bufLen)
{
	register int ch, n;
	register char *p;
	char buf[80];

    ProgressBar_fp->Max = bufLen/45;
    if( (bufLen % 45) )
    	ProgressBar_fp->Max++;

	fnSerialOutputString("begin 644 testme.jdb\n");
	while (bufLen > 0)
    {
    	if(nDownCancel == eCancel)
        	break;

		n = (bufLen > 45) ? 45 : bufLen;
		memcpy(buf, bufBase, n);
		bufBase += n;
		bufLen -= n;
		ch = ENC(n);
		fnSerialOutputByte(ch);
		for (p = buf; n > 0; n -= 3, p += 3)
        {
			ch = *p >> 2;
			ch = ENC(ch);
			fnSerialOutputByte(ch);
			ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
			ch = ENC(ch);
			fnSerialOutputByte(ch);
			ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
			ch = ENC(ch);
			fnSerialOutputByte(ch);
			ch = p[2] & 077;
			ch = ENC(ch);
			fnSerialOutputByte(ch);
		}
		fnSerialOutputByte('\n');
        ProgressBar_fp->Position++;
        Application->ProcessMessages();
	}
	ch = ENC('\0');
	fnSerialOutputByte(ch);
	fnSerialOutputByte('\n');
	fnSerialOutputString("end\n");
}

void __fastcall TFormMain::Memo_readmsgDblClick(TObject *Sender)
{
	Memo_readmsg->Clear();
	Lines = 0;
}
//---------------------------------------------------------------------------


void __fastcall TFormMain::Memo_readmsgKeyPress(TObject *Sender, char &Key)
{
	fnSerialOutputByte(Key);
}
//---------------------------------------------------------------------------

int TFormMain::sio_open(int port)
{
    char buff[256];

    threadCC->Terminate();

    if(com_fd > 0)
        close(com_fd);

    sprintf(buff, "/dev/ttyS%1d", port);
    com_fd = open(buff, O_RDWR | O_NONBLOCK);
    if(com_fd < 0)
    {
    	Application->MessageBox("Cannt open comm port",
        		   "Error",	TMessageButtons() <<smbAbort);
        com_fd = -1;
        p_com_fd = com_fd;
        return SIO_ERROR;
    }
    p_com_fd = com_fd;
    if(sio_set() != SIO_OK)
    {
    	Application->MessageBox("set comm port error",
        		   "Error",	TMessageButtons() <<smbAbort);
        com_fd = -1;
        p_com_fd = com_fd;
        return SIO_ERROR;
    }
    threadCC = new TCheckCom(false);
    return SIO_OK;
}
int TFormMain::sio_set(void){	termios term;

	if( com_fd <= 0 )
		return SIO_ERROR;

	if (tcgetattr(com_fd, &term) < 0)
    {
		Application->MessageBox("tcgetattr error", "Error", TMessageButtons() <<smbAbort);
		return SIO_ERROR;
	}

    cfmakeraw(&term);
    cfsetspeed(&term, Baudrate_table[RadioGroup_baudrate->ItemIndex]);
	term.c_ispeed = Baudrate_table[RadioGroup_baudrate->ItemIndex];
    term.c_ospeed = Baudrate_table[RadioGroup_baudrate->ItemIndex];
    term.c_cflag |= Bitcnt_table[RadioGroup_databit->ItemIndex];
    switch (RadioGroup_stopbit->ItemIndex)
    {
      case 0:
            term.c_cflag &= (~CSTOPB);
            break;
      case 1:
            term.c_cflag |= CSTOPB;
            break;
    }

    switch(RadioGroup_parity->ItemIndex)
    {
      case 0:
        term.c_cflag &= (~PARENB);
        break;
      case 1:
        term.c_cflag |= PARENB | PARODD;
        break;
      case 2:
        term.c_cflag |= PARENB & (~PARODD);
        break;
    }
//    term.c_lflag &= (~(ICANON | ECHO | ECHOE | ISIG));
//    term.c_oflag &= (~ OPOST);
    term.c_cc[VTIME] = 0;
    term.c_cc[VMIN] = 1;
    tcflush(com_fd, TCIFLUSH);
	if(tcsetattr(com_fd, TCSANOW, &term) < 0)
	{
		Application->MessageBox("tcgetattr error", "Error", TMessageButtons() <<smbAbort);
		return SIO_ERROR;
	}
    return SIO_OK;
}


void __fastcall TFormMain::Memo_readmsgKeyUp(TObject *Sender, WORD &Key,
      TShiftState Shift){    char ch;
    ch = char(Key);
    if(Shift == TShiftState() <<ssCtrl)
    {
        switch(ch)
        {
        case '\\': fnSerialOutputByte(28); break;
        case  'H': fnSerialOutputByte(8);  break;
        case  'U': fnSerialOutputByte(21); break;
        case  'D': fnSerialOutputByte(4);  break;
        case  'Q': fnSerialOutputByte(17); break;
        case  'S': fnSerialOutputByte(19); break;
        case  'Z': fnSerialOutputByte(26); break;
        case  'Y': fnSerialOutputByte(25); break;
        case  'V': fnSerialOutputByte(22); break;
        case  'W': fnSerialOutputByte(23); break;
        case  'R': fnSerialOutputByte(18); break;
        case  'O': fnSerialOutputByte(15); break;
        case  'C': fnSerialOutputByte(3);  break;
        }
    }
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -