當前位置:首頁 » 編程語言 » c語言控制串口
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言控制串口

發布時間: 2022-04-17 10:12:05

⑴ windows下c語言怎麼對串口進行讀寫操作

windows下對串口的操作可以通過WindowsAPI進行,也可以通過Linux下的read什麼的直接操作,但是這種情況需要了解電路結構,比較麻煩,第三種有第三方提供的庫,但是大多數針對C++,所以可能比較難找到順手的第三方庫.
那麼,接下來就見要介紹一下串口通信用WindowsAPI通信的方式.

我們會發現,在文件名的位置填上"comX" X表示com口號,超過十的com口號需要另外的書寫方式,這里不說了,因為網上一抓一大把,接下來,我們要對串口進行一系列的明確設置,這里就用到了一個結構體DCB結構,是專門用來描述一個com口的工作方式的,由於次結構體有28個成員,非常多,而且大部分的設置都是全世界通用的,所以,我們偷個懶,在打開一個com口之後,建立DCB結構體,接下來調用一個函數GetCommState用這個函數把現在com口的數據都寫到DCB里,這樣,比較通用的com口設置就已經弄好了,我們一般情況下只需要改一下DCB的波特率就好了,改好後馬上用SetCommState把剛改好的結構體再寫回去,這樣串口就設置好了,現在還有點麻煩,串口設置好了,我們要它干什麼呢?廢話,讀寫數據唄,嘟~~~~~~可不能用fwrite和fread因為這個com口句柄不是文件句柄,是內核句柄,要用ReadFile和WriteFile來進行讀寫,又出麻煩了,我們怎麼知道單片機什麼時候發數據過來,就算我們知道,計算機什麼時候知道啊?所以,一般的情況下,用ReadFile一直在哪檢查,又是麻煩,通常情況下,一個com口的ReadFile設置是阻塞函數,影響編程啊!!!!!!

怎麼辦,很簡單,你不阻塞嗎,打通你唄,我們再建立里一個結構體COMMTIMEOUTS這個結構體描述里一個com口的相關超時設置,我們用GetCommTimeouts把數據讀回來,具體的設置方法在網上也有,但是要注意,有一個MAXDWORD用它來設置讀間隔超時設置就可以使ReadFile向kbhit()函數一樣完全非阻塞了.
經過一些列的設置,事實上,現在已經可以通信了,要是有人覺得緩存不舒服,用SetupComm函數來重設緩存大小,對於傳輸速度比較快的通信,要把緩存設置的大些.

⑵ 我想用C語言實現一個串口發送的功能

可以。
首先你可以用程序判斷你待發送的字元的校驗和y
設你在校驗位要發送的位為x
設校驗方式為z
因為 x=y xor z
所以 z=x xor y
即根據校驗和y 與 你的要求x 決定用奇校驗還是偶校驗。
要是沒有猜錯,你可能是想用校驗位來多一個發送位,
達到特殊控制功能。不要忘記,上述方法只能在一個字元
發送完成後才能改變校驗方式。

⑶ 如何用C語言控制計算機串口

基本方法是使用CreateFile來建立一個串口文件,然後用overlap的方式進行讀寫

#define SERAIL_PORT_BUF_MAX (1024*8)
typedef HRESULT (*PFN_CMD_PARSE_DATA)(HANDLE hParseApp, LPCSTR szRspCmd, int nCmdLen);

class CUsbSrvApp// : public CWinApp
{
public:
CUsbSrvApp();
~CUsbSrvApp();
BOOL OnSendData(const char *szBuf, int nLen);// 發送數據
int ComConnect(CString strPort); // 連接COM口
HANDLE OpenComPort(CString strPort, int nBaudRate, int nDataBits, int nStopBits, int nParity, int nFlowCtrlType); // 打開串口
void Close(); // 關閉串口

HANDLE m_hCom;
BOOL m_bConnected;
OVERLAPPED m_OverlappedRead;
OVERLAPPED m_OverlappedWrite;
CWinThread *m_pThread;

PFN_CMD_PARSE_DATA m_pRspCmdFunc; // 用來處理接受數據的CALLBACK
HANDLE m_hParseApp;
};

CUsbSrvApp::CUsbSrvApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
m_bConnected = false;
m_hCom = NULL;
m_pRspCmdFunc = NULL;
}

CUsbSrvApp::~CUsbSrvApp()
{
}
//打開串口通信,並返回串口句柄
HANDLE CUsbSrvApp::OpenComPort(CString strPortName,
int nBaudRate,
int nDataBits,
int nStopBits,
int nParity,
int nFlowCtrlType)
{
DCB dcb;
COMMTIMEOUTS CommTimeOuts ;
COMMCONFIG ComConfig;
HANDLE hComPort;

CString strPort;
strPort.Format("\\\\.\\%s",strPortName); // COM口的文件名應該是 \\.\COMXX

//打開窗口其實就是創建一個文件
hComPort = CreateFile(strPort,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);

if (INVALID_HANDLE_VALUE == hComPort)
return INVALID_HANDLE_VALUE;

// 設置一些COM口通訊參數和OVERLAP
CommTimeOuts.ReadIntervalTimeout = -1;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0x1388;
SetCommTimeouts( m_hCom, &CommTimeOuts ) ;

SetDefaultCommConfig(strPortName, &ComConfig, sizeof(COMMCONFIG));
GetCommState(m_hCom, &dcb ) ;

dcb.BaudRate = nBaudRate;
dcb.ByteSize = nDataBits;
dcb.StopBits = nStopBits;
dcb.fParity = (NOPARITY != nParity);
dcb.Parity = nParity;
//set the receive char
dcb.EvtChar = 0x0D;

switch(nFlowCtrlType)
{
case 0: //no flow control
break;

case 1://HARD_FLOW_CTRL:

dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = TRUE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = TRUE;
dcb.fRtsControl = RTS_CONTROL_TOGGLE;
break;

case 2://SOFT_FLOW_CTRL:
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
break;
}
BuildCommDCB(_T("baud=115200 parity=N data=8 stop=1"),&dcb);
SetCommState(hComPort, &dcb ) ;
SetCommMask(hComPort, 0);
SetCommMask(hComPort, EV_RXCHAR|EV_CTS|EV_DSR|EV_RLSD|EV_RING);
SetupComm( hComPort, SERAIL_PORT_BUF_MAX,SERAIL_PORT_BUF_MAX) ;
//clear read and write buffer
PurgeComm( hComPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );

return hComPort;
}

void CUsbSrvApp::Close()
{
if(m_bConnected)
{
m_bConnected = false;
CloseHandle(m_hCom);
m_hCom = NULL;
}
}

// 這個線程是監視串口數據,一旦有數據則讀取並調用CALLBACK通知客戶端
UINT ReceiveComData(LPVOID pParam)
{
CUsbSrvApp *pUsbSrv = (CUsbSrvApp *)pParam;
HANDLE hComPort = pUsbSrv->m_hCom;

DWORD dwEvtMask=0;
DWORD dwErrorFlags;

SetCommMask( hComPort, EV_RXCHAR);
OVERLAPPED osRead;
osRead.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
DWORD dwTransfer = 0;
while(pUsbSrv->m_bConnected)
{
if( !WaitCommEvent( hComPort, &dwEvtMask,&osRead))
{
if( GetLastError()== ERROR_IO_PENDING)
{
WaitForSingleObject(osRead.hEvent, INFINITE);
if(dwEvtMask&EV_RXCHAR==EV_RXCHAR)
{
COMSTAT ComStat={0} ;
DWORD dwReadLen = 0;
DWORD dwBytesRead = 0;
DWORD dwTotalLen = 0;
ClearCommError(hComPort, &dwErrorFlags, &ComStat );
dwTotalLen = ComStat.cbInQue;
dwReadLen = (SERAIL_PORT_BUF_MAX > dwTotalLen)?dwTotalLen:SERAIL_PORT_BUF_MAX;

BYTE *pBuf = new BYTE[dwTotalLen+1];
memset(pBuf, 0 , dwTotalLen+1);
DWORD nReadBufLen=0;
while(dwTotalLen>0)
{

if(FALSE == ReadFile( hComPort, pBuf+nReadBufLen,dwReadLen, &dwBytesRead,&pUsbSrv->m_OverlappedRead))
{
if(GetLastError() == ERROR_IO_PENDING)
{
GetOverlappedResult(hComPort,&osRead, &dwTransfer, TRUE );
}
break;
}

nReadBufLen +=dwBytesRead;
dwTotalLen -=dwBytesRead;
dwReadLen -= dwBytesRead;
dwReadLen = (SERAIL_PORT_BUF_MAX>dwReadLen)?dwReadLen:SERAIL_PORT_BUF_MAX;
}
if(pUsbSrv->m_pRspCmdFunc!=NULL&&nReadBufLen!=0)
{
pUsbSrv->m_pRspCmdFunc(pUsbSrv->m_hParseApp, (char*)pBuf,nReadBufLen);
}

delete pBuf;

ClearCommError(hComPort, &dwErrorFlags, &ComStat );
int len =0;//= m_retList.GetSize();
}//endif if(dwEvtMask&EV_RXCHAR==EV_RXCHAR)
}//endif if( GetLastError()== ERROR_IO_PENDING)
}//endif if( !WaitCommEvent( hComPort, &dwEvtMask,&o))
else
{
if(GetLastError() == ERROR_IO_PENDING) {
GetOverlappedResult(hComPort, &osRead, &dwTransfer, TRUE ); // sleep thread
}
}
Sleep(1);
} //endwhile while(m_bConnected)
return 0;
}

int CUsbSrvApp::ComConnect(CString strPort)
{
int nBaudRate = 115200;
int nDataBits = 8;
int nStopBits = 1;
int nParity = 0;
int nFlowCtrl = 1;

if (NULL != m_hCom || m_bConnected)
{
return 0;
}
m_hCom = OpenComPort(strPort,nBaudRate,nDataBits,nStopBits,nParity,nFlowCtrl);
if( INVALID_HANDLE_VALUE == m_hCom)
{
m_hCom = NULL;
return 0;
}
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

m_pThread = AfxBeginThread( ReceiveComData,(void*)this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED ,NULL );

if( NULL == m_pThread )
{
CloseHandle( m_hCom );
m_hCom = NULL;
return FALSE;
}
else
{
m_bConnected = TRUE;
m_pThread->ResumeThread( );
}

return TRUE;
}

int CUsbSrvApp::OnSendData(const char *szBuf, int nLen)
{
BOOL bWriteStat;
BOOL bWrite = TRUE;
DWORD dwBytesWrite = 0;
DWORD dwBytesWritten = 0;
int dwByteswrittenTotal = 0;

if (NULL == m_hCom)
return 0;

int nSentTimes=0;

while(dwByteswrittenTotal<nLen&&nSentTimes<10)
{
nSentTimes++;
dwBytesWrite = nLen-dwByteswrittenTotal;
bWriteStat = WriteFile( m_hCom, szBuf+dwByteswrittenTotal, dwBytesWrite, &dwBytesWritten, &m_OverlappedWrite );

if( !bWriteStat)
{
if ( GetLastError() == ERROR_IO_PENDING )
{
dwBytesWritten = 0;
bWrite = FALSE;
}
}
if (!bWrite)
{
bWrite = TRUE;

bWriteStat = GetOverlappedResult(m_hCom, // Handle to COMM port
&m_OverlappedWrite, // Overlapped structure
&dwBytesWritten, // Stores number of bytes sent
TRUE); // Wait flag
//deal with the error code
}
dwByteswrittenTotal += dwBytesWritten;
}
if(dwByteswrittenTotal<nLen)
return 0;
else
return 1;
}

⑷ c語言串口通訊過程

分接收端和發送端。
接收端:
1·打開com1埠
fd=fopen("/dev/ttys0",方式);
2·取得當前串口值,保存到結構體變數oldtio
tcgetattr(fd,&oldtio);
3·串口結構體變數newtio清0.
bzero(&newtio,sizeof(newtio))
4·設置串口參數
主要設置比特率、是否忽略奇偶校驗錯誤,啟用正規模式等等。
接收端
1·打開com埠
2·取得當前串口值
3·串口結構體變數清0
4·設置串口參數。

⑸ c語言怎麼實現串口通信

編程原理
程序1為查詢通信方式介面程序,為一典型的數據採集常式。其中bioscom()函數初始化COM1(此函數實際調用BIOS
INT
14H中斷0號功能)。這樣在程序中就避免了具體設置波特率因子等繁瑣工作,只需直接訪問發送/接收寄存器(3F8H)和線路狀態寄存

⑹ 怎麼用C語言中斷方式實現串口的讀寫

#include <stdio.h>
#include <dos.h>
#include <time.h>

#define LSB 0
#define MSB 1

#define RXR 0
#define TXR 0
#define IER 1
#define IIR 2
#define LCR 3
#define MCR 4
#define LSR 5
#define MSR 6

#define Com1_base 0x3f8
#define uchar unsigned char

volatile uchar inputData;
volatile uchar onInput = 0x00;
volatile uchar onOutput = 0x00;
volatile uchar inputdata[256]; /*設設置接收緩沖區大小*/
volatile unsigned int count; /*中斷接收的數據數目*/
int datacount;/*當前已發送數據條數*/

void interrupt (*OldVect)(); /*函數是用來獲取中斷處理程序的入口地址的*/
void interrupt SerialISR();

void InitCom()
{
uchar inttemp;
/*設置波特率什麼的*/
outportb(Com1_base+LCR,0x80); /*使LCR的高位為1,以便讀取其它寄存器*/
outportb(Com1_base+LSB,0x0c); /*除數鎖存器(低8位)DLL*/
outportb(Com1_base+MSB,0x00); /*除數鎖存器(高8位)DLH 產生2400波特率*/
outportb(Com1_base+LCR,0x03); /*8位數據,1位停止位,無校驗*/
outportb(Com1_base+IER,0x01); /*接收採用中斷方式*/

/*設置中斷向量*/
OldVect = getvect(0x0c); /*函數是用來獲取中斷處理程序的入口地址的*/
disable();
inttemp = inportb(0x21)&0xef;
outportb(0x21,inttemp);
setvect(0x0c,SerialISR); /*設置SerialISR的中斷入口地址為0X0C*/
enable();
}

void CloseCom()
{
disable();
outportb(Com1_base+IER,0x00); *禁止中斷*/
outportb(Com1_base,0x00);
outportb(0x21,inportb(0x21)|~(0xef));
setvect(0x0c,OldVect);
}

void interrupt SerialISR()
{
/*串口中斷服務代碼*/
inputData = inportb(Com1_base+RXR);
onInput = 0x01;
inputdata[count]=inputData;
count++;
/*服務代碼結束*/
outportb(0x20,0x20); /*中斷結束的代碼*/
}

void SendChar(uchar key)
{
while( ((inportb(Com1_base + LSR)) & 0x40) == 0);
outportb(Com1_base + TXR,key);
}
/*...........延時函數......................*/
void delay(unsigned int n)
{
unsigned int i,k;
for(k=0;k<n;k++)
{
for(i=1;i<1142;i++)
;
}
}

/*........CDMA命令發送函數.................*/
void CDMA_CommandSend(char *p,unsigned int n)
{

int i,k,m,l;
int flag=0;
int selse_flag=0; int selse_flag_1=0;
int selse_flag1=0;int selse_flag1_1=0;
time_t start,end;
double dif=0;
char a;

uchar bExit_flag = 0x00;
count=0;
while(!bExit_flag)
{
count=0;
for(i=0;i<n;i++)
{SendChar(*p);delay(9000);p++;}

/*..........等待2S..................*/
time (&start);
dif=0;
while(dif<2)
{
delay(9000);
time (&end);
dif = difftime (end,start);
}
if(count>14)
{
time (&start);
dif=0;
while(dif<3)
{
delay(9000);
time (&end);
dif = difftime (end,start);
}
}

/*..........判斷發送命令是否成功..................*/
for(m=0;m<count;m++)
{
if(count>10)
{
for(l=0;l<count;l++)
{
if(inputdata[l-1]=='N'&&inputdata[l-2]=='E'&&inputdata[l-3]=='P'&&inputdata[l-4]=='O'&&inputdata[l-5]=='P'&&inputdata[l-6]=='P'&&inputdata[l-7]=='P'&&inputdata[l-8]=='V') { selse_flag_1=1;}
if(inputdata[l-1]=='N'&&inputdata[l-2]=='E'&&inputdata[l-3]=='P'&&inputdata[l-4]=='O'&&inputdata[l-5]=='P'&&inputdata[l-6]=='C'&&inputdata[l-7]=='T'&&inputdata[l-8]=='V') { selse_flag1_1=1;}
}

if(selse_flag_1==1){if(inputdata[m-1]=='3'&&inputdata[m-2]=='3'&&inputdata[m-3]==':'&&inputdata[m-4]=='T') selse_flag=1;}
if(selse_flag1_1==1){if(inputdata[m-1]=='0'&&inputdata[m-2]==','&&inputdata[m-3]=='1'&&inputdata[m-4]==':'&&inputdata[m-5]=='N') selse_flag1=1;}

if(selse_flag_1==1||selse_flag1_1==1)
{
if(selse_flag==1) {if(inputdata[m-1]=='0'&&inputdata[m-2]==':'&&inputdata[m-3]=='N'&&inputdata[m-4]=='E') flag=1;}
if(selse_flag1==1) {if(inputdata[m-1]=='0'&&inputdata[m-2]==','&&inputdata[m-3]=='1'&&inputdata[m-4]==':'&&inputdata[m-5]=='S') flag=1;}
}
else {if(inputdata[m-1]=='O'&&inputdata[m]=='K') {flag=1; }}
}
else {if(inputdata[m-1]=='O'&&inputdata[m]=='K') flag=1; }
}
if(flag==1){bExit_flag = 0x01;}
else {p=p-n; }

for(i=0;i<count;i++) printf("%c",inputdata[i]);
/*........按空格停止測試.............................*/
if(kbhit()){a=getch(); if(a==' '){CloseCom(); exit(1);}}

}
}

/*........數據測試發送任務.....................*/
void Data_Send(char *pcomd,int n,char *pdata,int m)
{
int i,k,l;time_t start,end;
double dif=0;
count=0;
for(i=0;i<n;i++)
{
SendChar(*pcomd);delay(9000);pcomd++;
}
time (&start);
dif=0;
while(dif<0.2)
{
delay(9000);
time (&end);
dif = difftime (end,start);
}

for(l=0;l<m;l++)
{
SendChar(*pdata);pdata++;
}

printf("The data num:%d",datacount);
datacount++;
}

void main()
{int i;char a;
/*........模塊測試命令..................................*/
uchar CDMA_COMMAND_1[]={"at\r"};
uchar CDMA_COMMAND_2[]={"atz\r"};
uchar CDMA_COMMAND_3[]={"ate1v1\r"};
uchar CDMA_COMMAND_4[]={"AT+CRM=1;+CPS=33;+CMUX=1;+CTA=0\r"};
uchar CDMA_COMMAND_5[]={"AT+VPPPOPEN\r"};
uchar CDMA_COMMAND_6[]={"AT+VTCPOPEN=1,\"60.63.42.129\",1234\r"};
uchar CDMA_COMMAND_7[]={"AT+VTCPSEND=1,20\r"};
uchar CDMA_DATA[]={"ABCDEFGHIJKLMNOPQRST"};
uchar CDMA_COMMAND_9[]={"AT+VPPPCLOSE\r"};
uchar CDMA_COMMAND_8[]={"AT+VTCPCLOSE=1\r"};
uchar bExit_flag1 = 0x00;
time_t start,end;
double dif=0;
InitCom();/*初始化埠1*/
inputData = inportb(Com1_base+RXR);
while(!bExit_flag1)
{
/*.................................................................*/
if(kbhit()) /*按任意鍵開始測試CDMA*/
{
/*.............................................................. ...*/

/*.........發送TCP斷開命令.....................................*/
CDMA_CommandSend(CDMA_COMMAND_8,strlen(CDMA_COMMAND_8));
/*.........發送PPP斷開命令......................................*/
CDMA_CommandSend(CDMA_COMMAND_9,strlen(CDMA_COMMAND_9));

/*.........發送AT命令..........................................*/
CDMA_CommandSend(CDMA_COMMAND_1,strlen(CDMA_COMMAND_1));
/*.........發送ATZ命令.........................................*/
CDMA_CommandSend(CDMA_COMMAND_2,strlen(CDMA_COMMAND_2));
/*.........發送ATE1V1命令......................................*/
CDMA_CommandSend(CDMA_COMMAND_3,strlen(CDMA_COMMAND_3));
/*.........發送AT初始化命令....................................*/
CDMA_CommandSend(CDMA_COMMAND_4,strlen(CDMA_COMMAND_4));
/*.........發送PPP拔號命令.....................................*/
CDMA_CommandSend(CDMA_COMMAND_5,strlen(CDMA_COMMAND_5));
/*.........發送網路連接命令....................................*/
CDMA_CommandSend(CDMA_COMMAND_6,strlen(CDMA_COMMAND_6));
/*.........發送數據............................................*/
datacount=0;
while(1)
{
Data_Send(CDMA_COMMAND_7,strlen(CDMA_COMMAND_7),CDMA_DATA,strlen(CDMA_DATA));

time (&start);
dif=0;
while(dif<0.2)
{
delay(9000);
time (&end);
dif = difftime (end,start);
}

if(kbhit()){a=getch(); if(a==' '){bExit_flag1 = 0x01; break;}}
}
/*.........發送TCP斷開命令.....................................*/
for(i=0;i<3;i++)
CDMA_CommandSend(CDMA_COMMAND_8,strlen(CDMA_COMMAND_8));
/*.........發送PPP斷開命令......................................*/
for(i=0;i<3;i++)
CDMA_CommandSend(CDMA_COMMAND_9,strlen(CDMA_COMMAND_9));

bExit_flag1 = 0x01;
}

/*.................................................................*/

}
CloseCom(); /*關閉埠1*/
printf("Bye~.\n");
}

⑺ C語言中如何對串口進行操作

C語言會有操作串口的庫函數的,按照串口庫函數標識實現調用就可以了。

⑻ 如何用C語言編一個小程序,直接控制計算機的9針串口線,一直輸出邏輯0。

一般來講,你說的這種功能是這樣實現的:用VB或者VC在計算機上面編寫一個應用程序操作界面,一般稱為上位機,通過COM串口和下位機(一般是一個單片機系統)物理連接,通過上位機發出指令,也就是通過計算機COM串口發出一些數據。通常是要約定好波特率、數據位、校驗等,下位機根據上位機的指令做出執行操作,I/O口輸出一個電平去控制繼電器,再去控制強電。
如果你只保留計算機,用計算機的COM串口直接作為輸出驅動,是有問題的。分析如下,因為計算機的串口主要用途是通訊,即傳送一些RS232電平的信號,比如傳送數字1、2、3。。。或者是字母A、B、C。。。。。等,即使是傳送一位也會同時有0邏輯和1邏輯出現,即不能一直讓串口線的TX線一直輸出邏輯0的,所以無法實現你說的功能。

⑼ C語言變成實現串口收發數據

#include <reg51.h>

#include <intrins.h>

unsigned char key_s, key_v, tmp;

char code str[] = "welcome!www.willar.com ";

void send_str();

bit scan_key();

void proc_key();

void delayms(unsigned char ms);

void send_char(unsigned char txd);

sbit K1 = P1^4;

main()

{

TMOD = 0x20; // 定時器1工作於8位自動重載模式, 用於產生波特率

TH1 = 0xFD; // 波特率9600

TL1 = 0xFD;

SCON = 0x50; // 設定串列口工作方式

PCON &= 0xef; // 波特率不倍增

TR1 = 1; // 啟動定時器1

IE = 0x0; // 禁止任何中斷

while(1)

{

if(scan_key()) // 掃描按鍵

{

delayms(10); // 延時去抖動

if(scan_key()) // 再次掃描

{

key_v = key_s; // 保存鍵值

proc_key(); // 鍵處理

}

}

if(RI) // 是否有數據到來

{

RI = 0;

tmp = SBUF; // 暫存接收到的數據

P0 = tmp; // 數據傳送到P0口

send_char(tmp); // 回傳接收到的數據

}

}

}

bit scan_key()

// 掃描按鍵

key_s = 0x00;

key_s |= K1;

return(key_s ^ key_v);

}

void proc_key()

// 鍵處理

{

if((key_v & 0x01) == 0)

{ // K1按下

send_str(); // 傳送字串"welcome!...

}

}

void send_char(unsigned char txd)

// 傳送一個字元

{

SBUF = txd;

while(!TI); // 等特數據傳送


TI = 0; // 清除數據傳送標志

}

void send_str()

// 傳送字串

{

unsigned char i = 0;

while(str[i] != '')

{

SBUF = str[i];

while(!TI); // 等特數據傳送

TI = 0; // 清除數據傳送標志

i++; // 下一個字元

}

}

void delayms(unsigned char ms)

// 延時子程序

{

unsigned char i;

while(ms--)

{

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

}

}

拓展資料

C語言是一門通用計算機編程語言,應用廣泛。C語言的設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、產生少量的機器碼以及不需要任何運行環境支持便能運行的編程語言。

盡管C語言提供了許多低級處理的功能,但仍然保持著良好跨平台的特性,以一個標准規格寫出的C語言程序可在許多電腦平台上進行編譯,甚至包含一些嵌入式處理器(單片機或稱MCU)以及超級電腦等作業平台。

二十世紀八十年代,為了避免各開發廠商用的C語言語法產生差異,由美國國家標准局為C語言制定了一套完整的美國國家標准語法,稱為ANSI C,作為C語言最初的標准。目前2011年12月8日,國際標准化組織(ISO)和國際電工委員會(IEC)發布的C11標準是C語言的第三個官方標准,也是C語言的最新標准,該標准更好的支持了漢字函數名和漢字標識符,一定程度上實現了漢字編程。



⑽ 急!!!單片機C語言實現串口通信編程

以下是我剛改的程序編譯成功了
請參考

#include"reg51.h"
//定義全局變數
unsigned char data_10[10]={0,0,0,0,0,0,0,0,0,0};
unsigned char Time_50ms,count;
bit flag=0;
bit data_flag=0;
/*********************************************************************************************
函數名:UART串口初始化函數
調 用:UART_init();
參 數:無
返回值:無
結 果:啟動UART串口接收中斷,允許串口接收,啟動T/C1產生波特率(佔用)
備 註:振盪晶體為12MHz,PC串口端設置 [ 4800,8,無,1,無 ]
/**********************************************************************************************/
void UART_init (void){
EA = 1; //允許總中斷(如不使用中斷,可用//屏蔽)
ES = 1; //允許UART串口的中斷
TMOD |= 0x20;//定時器T/C1工作方式2
SCON = 0x50;//串口工作方式1,允許串口接收(SCON = 0x40 時禁止串口接收)
TH1 = 0xF3;//定時器初值高8位設置
TL1 = 0xF3;//定時器初值低8位設置
PCON = 0x80;//波特率倍頻(屏蔽本句波特率為2400)
TR1 = 1;//定時器啟動
}
/**********************************************************************************************/
/*********************************************************************************************
函數名:UART串口接收中斷處理函數
調 用:[SBUF收到數據後中斷處理]
參 數:無
返回值:無
結 果:UART串口接收到數據時產生中斷,用戶對數據進行處理(並發送回去)
備 註:過長的處理程序會影響後面數據的接收
/**********************************************************************************************/
void UART_R (void) interrupt 4 using 1{ //切換寄存器組到1
TR0=1; //打開定時器開始計時
RI = 0;//令接收中斷標志位為0(軟體清零)
data_10[count] = SBUF;//將接收到的數據送入變數 UART_data
count++;//接收到一個位元組數據計數+1
if(count>=10) //如果接收到10個數據
{
TR0=0; //停止定時器
TH0 = 0x3C; //給定時器賦初值
TL0 = 0xB0; //給定時器賦初值
count=0;//清零數據計數
//data_flag=1; //數據有效標志位
SBUF = 0x55;//返回數據 55H
while(TI == 0);//檢查發送中斷標志位
TI = 0;//令發送中斷標志位為0(軟體清零)
}
if(flag)
{
TR0=0; //停止定時器
TH0 = 0x3C; //給定時器賦初值
TL0 = 0xB0; //給定時器賦初值
count=0;//清零數據計數
SBUF = 0xff;//返回數據 ffH
while(TI == 0);//檢查發送中斷標志位
TI = 0;//令發送中斷標志位為0(軟體清零)
}
}
/**********************************************************************************************/
/*********************************************************************************************
函數名:定時/計數器初始化函數
調 用:T_C_init();
參 數:無
返回值:無
結 果:設置SFR中T/C1和(或)T/C0相關參數
備 註:本函數控制T/C1和T/C0,不需要使用的部分可用//屏蔽
/**********************************************************************************************/
void T_C_init (void){
TMOD |= 0x01; //高4位控制T/C1 [ GATE,C/T,M1,M0,GATE,C/T,M1,M0 ]
EA = 1;//中斷總開關
TH0 = 0x3C; //16位計數寄存器T0高8位
TL0 = 0xB0; //16位計數寄存器T0低8位(0x3CB0 = 50mS延時)
ET0 = 1; //T/C0中斷開關
TR0 = 0; //T/C0開關
}
/**********************************************************************************************/
/*********************************************************************************************
函數名:定時/計數器0中斷處理函數
調 用:[T/C0溢出後中斷處理]
參 數:無
返回值:無
結 果:重新寫入16位計數寄存器初始值,處理用戶程序
備 註:必須允許中斷並啟動T/C本函數方可有效,重新寫入初值需和T_C_init函數一致
/**********************************************************************************************/
void T_C0 (void) interrupt 1 using 1{ //切換寄存器組到1
TH0 = 0x3C; //16位計數寄存器T0高8位(重新寫入初值)
TL0 = 0xB0; //16位計數寄存器T0低8位(0x3CB0 = 50mS延時)
Time_50ms++; //50ms到 計數+1
if(Time_50ms>=100)
{
Time_50ms=0;// 清零50ms計數
flag=1; //5s時間 標志置位
TR0=0;//關閉計時器
}
}
/**********************************************************************************************/
main()
{
IP = 0x10; //中斷優先順序設置(串口中斷最高優先順序)
UART_init();//初始化串口
T_C_init(); // 初始化計數器
while(1);// 空循環
}