一个用api函数与单片机串行通信的问题
本人刚学vc不久,基础比较差。遇到一个比较怪异的问题。
目的是用pc输出数据来控制51单片机的一个动态LED显示电路,现在碰到的问题是,在单片机电源关闭的情况下,我的上位机程序发送和接收数据居然是正常的,所有api函数返回值无误。打开单片机电源后,LED显示没有变化。
因为所需读写操作很简单,我上位机程序没有建立线程。
下位机程序已用串口调试助手调试成功,能实现发送数据<0x80时,led显示三位数减1,发送数据>=0x80时,led显示三位数加1
上位机主要程序代码:
//打开串口
BOOL CSPortDownloadView::OpenConnection(CString m_sport,int i)
{
COMMTIMEOUTS commtimeouts;
BOOL fRetVal=FALSE; //设置函数的返回值
if((m_idComDev[i]=CreateFile(m_sport,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL
NULL))==INVALID_HANDLE_VALUE)
{
CString str;
str.Format("打开串口com%d失败",i+1);
AfxMessageBox(str);
CloseHandle(m_idComDev[i]);
m_idComDev[i]=(HANDLE)-1;
return FALSE;
}
SetCommMask(m_idComDev[i],EV_RXCHAR); //设置通信事件为输入缓冲区收到新字符
SetupComm(m_idComDev[i],1024*2,1024*4); //设置缓冲区大小 读缓冲2k 写缓冲4k
PurgeComm(m_idComDev[i],
PURGE_TXABORT|PURGE_TXABORT|PURGE_TXCLEAR|PURGE_TXCLEAR); //把输入输出缓冲区清光
commtimeouts.ReadIntervalTimeout=200; //读时间间隔超时设置为0.2秒
commtimeouts.ReadTotalTimeoutConstant=0;
commtimeouts.ReadTotalTimeoutMultiplier=0;
commtimeouts.WriteTotalTimeoutConstant=0;
commtimeouts.WriteTotalTimeoutMultiplier=5000; //写时间总超时设置为5秒
SetCommTimeouts(m_idComDev[i],&commtimeouts); //设置超时函数
fRetVal=SetupConnection(i);
if(!fRetVal)
{
CString str;
str.Format("串口com%d初始化失败",i+1);
AfxMessageBox(str);
CloseHandle(m_idComDev[i]);
m_idComDev[i]=(HANDLE)-1;
}
return fRetVal;
}
//串口初始化
BOOL CSPortDownloadView::SetupConnection(int i)
{
BOOL fRetVal=FALSE;
dcb.DCBlength=sizeof(DCB);
GetCommState(m_idComDev[i],&dcb); //读取串口状态
//初始化串口:
dcb.BaudRate=CBR_9600;
dcb.ByteSize=8;
dcb.fParity=FALSE;
dcb.StopBits=ONESTOPBIT; //波特率9600,8个数据位,无校验位,一个停止位
dcb.fOutxDsrFlow=FALSE;
dcb.fOutxCtsFlow=FALSE;
dcb.fOutX=FALSE;
dcb.fInX=FALSE;
dcb.fDtrControl=FALSE;
dcb.fRtsControl=FALSE;
dcb.fBinary=TRUE; //是否允许二进制传输,该属性必须设为true
fRetVal=SetCommState(m_idComDev[i],&dcb);
return fRetVal;
}
//读串口
int CSPortDownloadView::ReadCommBlock(int i,unsigned char *lpBlock,int MaxLength)
{
BOOL fReadStat;
COMSTAT ComState;
DWORD dwErrorFlags,dwLength=0;
ClearCommError(m_idComDev[i],&dwErrorFlags,&ComState);
dwLength=min((DWORD)MaxLength,ComState.cbInQue);
if(dwLength>0)
{
fReadStat=ReadFile(m_idComDev[i],
lpBlock,
dwLength,
&dwLength,
NULL);
}
return dwLength;
}
//写串口
BOOL CSPortDownloadView::WriteCommBlock(int i,unsigned char *lpBlock,long num)
{
COMSTAT ComState;
BOOL fWriteState;
DWORD dwErrorFlags,dwBytesWritten;
ClearCommError(m_idComDev[i],&dwErrorFlags,&ComState);
fWriteState=WriteFile(m_idComDev[i],
lpBlock,
num,
&dwBytesWritten,
NULL);
return fWriteState;
}
void CSPortDownloadView::OnStart()
{
// TODO: Add your command handler code here
CString str; //提示信息
CComSet comset;
comset.m_ComNum=Com_Num;
BOOL fRetVal=FALSE;
if(comset.DoModal()==IDOK)
{
Com_Num=comset.m_ComNum;
CloseConnection(Com_Num);
CString s;
s.Format("COM%d",Com_Num);
fRetVal=OpenConnection(s,Com_Num);
if(!fRetVal) {return;}
unsigned char addch=0xff;
unsigned char subch=0;
unsigned char sendbuf[10];
unsigned char readbuf[10];
switch(comset.choice)
{
case 0:
endbuf[0]=addch; //增加一条信息
break;
case 1:
sendbuf[0]=subch; //减少一条信息
break;
default: ;
}
//写入串口
BOOL Writeflag=WriteCommBlock(Com_Num,sendbuf,1); //只发送sbuf中的第一个数据
if(!Writeflag)
{
str.Format("发送失败");
AfxMessageBox(str);
return;
}
//校验信息
int num=0;
for(int k=0;k<10;k++)
{
Sleep(500);
num=ReadCommBlock(Com_Num,&readbuf[0],1); //读出一帧数据到readbuf
if(num==1) break;
}
if((num!=1)|(readbuf[0]!=sendbuf[0])) //如果读出的数据不只一帧,或者校验数据不等,则校验失败
{
str.Format("校验失败");
AfxMessageBox(str);
return;
}
str.Format("发送并校验成功");
AfxMessageBox(str);
return;
}
}
下位机程序也贴一下吧:
#include <reg51.h>
#define disp P0
#define scanner P1
void Delay1m(int);
int Devide(int,int);
int count;
bit readflag;
unsigned char ch;
main()
{
int dec_bit,dec_num; //分别表示十进制三位数的位,和十进制三位数每一位数的大小
char scan;
char TAB[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
count=10;
dec_num=0;
readflag=0;
//串行初始化
PCON=0; //比特率不加倍
TMOD=0x20; //Timer1设为mode2,作为比特率产生
TL1=0xfd;
TH1=0xfd; //比特率为9600
TR1=1; //启动定时器
SCON=0x50; //设定串行通信为模式1,允许接收
ET1=1; //打开TF1中断
ES=1; //打开串行中断
EA=1; //允许打开所有中断
TI=1;
while(1)
{
scan=0x01;
for(dec_bit=1;dec_bit<=3;dec_bit++)
{
dec_num=Devide(dec_bit,count);
disp=TAB[dec_num];
scanner=~scan;
Delay1m(0.5);
scan<<=1;
if(scan==0x08)
{
scan=0x01;
}
if(readflag==1)
{
SBUF=ch;
while (TI==0);
TI=0;
readflag=0;
}
}
}
}
//延时1ms函数
void Delay1m(int x)
{
int i,j;
for(i=1;i<=x;i++)
{
for(j=1;j<125;j++);
}
return;
}
//分离三位数的个位十位百位
int Devide(int i,int j)
{
switch (i)
{
case 1:
return j%10;
case 2:
return (j%100)/10;
case 3:
return (j%1000)/100;
}
}
//串行中断服务子程序
void OnReceive(void) interrupt 4 using 3
{
/* EA=0; //保护现场,关闭中断
while(RI==0);
RI=0;
count++;
EA=1; //开中断 */
if(RI)
{
RI=0;
ch=SBUF;
if(ch<0x80)
count=count-1;
else
count++;
readflag=1;
}
return;
}