导航
  • 主页
  • VC综合技术
  • MFC新技术
  • 互联网技术
  • .NET 技术
  • VC/MFC界面
  • VC/MFC 进程
  • VC/MFC 数据库
  • VC++技术资源

一个用api函数与单片机串行通信的问题

liozzlee 2009-08-12 01:40:39
本人刚学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;
}


...全文
80 点赞 收藏 8
写回复
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
liozzlee 2009-08-12
在线继续等高人指导~
回复
liozzlee 2009-08-12
[Quote=引用 6 楼 zoulie 的回复:]
引用 5 楼 liozzlee 的回复:
引用 3 楼 zoulie 的回复:
可以下个比特精灵测试下有没有成功


比特精灵,是那个BT下载软件?

呵呵,打错了,是串口精灵
[/Quote]


我看了下这个软件,ms是用来调下位机程序的,我现在是上位机程序出问题了
回复
zoulie 2009-08-12
[Quote=引用 5 楼 liozzlee 的回复:]
引用 3 楼 zoulie 的回复:
可以下个比特精灵测试下有没有成功


比特精灵,是那个BT下载软件?
[/Quote]
呵呵,打错了,是串口精灵
回复
liozzlee 2009-08-12
[Quote=引用 3 楼 zoulie 的回复:]
可以下个比特精灵测试下有没有成功
[/Quote]

比特精灵,是那个BT下载软件?
回复
liozzlee 2009-08-12
[Quote=引用 2 楼 jennyvenus 的回复:]
在writefile的时候,将一次性write多个字节改成分多次,每次只write一个字节试试。

另外,检查scon的设置,是否跟pc程序完全一致。

[/Quote]

异步传输从哪看出来的?
我把writefile改成
DWORD bytes_written;
for(int j=0;j<num;j++)
{
fWriteState=WriteFile(m_idComDev[i],
lpBlock,
1,
&dwBytesWritten,
NULL);
if(!fWriteState) return fWriteState;
bytes_written+=dwBytesWritten
}

还是没有用,跟不设置线程有没有关系?

scon设置为8位UART可变比特率,REN=1允许接收,我看很多人都这么编的。
回复
zoulie 2009-08-12
可以下个比特精灵测试下有没有成功
回复
在writefile的时候,将一次性write多个字节改成分多次,每次只write一个字节试试。

另外,检查scon的设置,是否跟pc程序完全一致。
回复
好像是个串口通讯,而且是异步传输,那么接不接设备,PC程序发送肯定是成功的。
回复
发动态
发帖子
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……