搜索
bottom↓
回复: 54

一个学DELPHI上位机编程者的问题

[复制链接]

出0入0汤圆

发表于 2009-11-7 16:04:25 | 显示全部楼层 |阅读模式
请各位大虾帮忙:
    小弟正在自学上位机编程,遇到了问题。
    程序要求:分别编写一上位机及下位程序。上位机程序使用DELPHI7.0+SPCOMM控件开发;下位机使用AT89S51单片机作为主控器。上下位机使用串口通信。
    当点击上位机上“RUN”按钮时,下位机将开始运行一个跑马表程序(显示0-60循环计数即可),将计数值传送给上位机,而在上位机上某一固定位置处将实时显示下位传送过来的计数值。
    当点击上位机上“STOP”按钮时,下位机将停止计数。同时上位机上计数值也停止计数。
    为使程序简单起见,约定:上位机发送十六进制数A0时,跑马表程序启动;上位机发送十六进制数A1时,跑马表程序停止。
     问题:下位机程序可以在串口调试助手中正常运行,但在我自己编写的DELPHI软件里出现问题:数据显示框里什么数据也没有。
    我是DELPHI初学者,不知道上位机问题出在哪儿,请大虾帮忙指正。

上位机程序如下:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar timer_start_flag;    //定时器0启动标志位
uchar timer_stop_flag;                //定时器0停止标志位
uchar num;                                        //循环计数值
uchar receive_data;                        //接收数据
uchar counter;                                //定时50毫秒溢出值
uchar timer_1s_flag;                //定时1秒溢出标志位

void System_Init()                        //系统初始化
{
        timer_start_flag=0;
        timer_stop_flag=0;
        timer_1s_flag=0;
        num=0;
        receive_data=0;
        counter=0;
        timer_1s_flag=0;

        TMOD=0x21;                                //定时器1 工作方式2 定时器0 工作方式1
        TH0=(65536-50000)/256;               
        TL0=(65536-50000)%256;
        SCON=0x50;                                //串口方式1 允许串口接收
        TH1=0xfd;                                //9600波特率
        TL1=0xfd;                                       
        ET0=1;                                        //开定时器0中断
        ET1=1;                                        //开定时器1中断
        ES=1;                                        //开串口中断
        EA=1;                                        //开总中断       
        TR0=0;                                        //关闭定时器0
        TR1=1;                                        //启动定时器1       
}

void Serial_Send(uchar send_data)                //串口发送函数
{
        ES=0;
        SBUF=send_data/10*16+send_data%10;        //将要发送的数据转换成10进制
//        SBUF=send_data;
        while(!TI);
        TI=0;
        ES=1;       

}

void serial_receive() interrupt 4 using 0                //串口中断接收函数
{
        RI=0;
        receive_data=SBUF;
        switch(receive_data)
        {
                case 0xa0:                //CPU收到0A0H就启动定时器0
                                timer_start_flag=1;
                                break;
                case 0xa1:                //CPU收到0A1H就关闭定时器0
                                timer_stop_flag=1;
                                break;
                       
       
        }               
}

void timer0() interrupt 1 using 1                //定时0中断函数
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        counter++;
        if(counter==20)                        //定时1秒到了吗?
        {       
                counter=0;
                timer_1s_flag=1;
        }       
}


void main()
{
        System_Init();
        while(1)
        {
                if(timer_start_flag==1)
                {
                        timer_start_flag=0;
                        TR0=1;
                }
               
                if(timer_stop_flag==1)
                {
                        timer_stop_flag=0;
                        TR0=0;
                }
               
                if(timer_1s_flag==1)
                {
                        timer_1s_flag=0;
                        Serial_Send(num);                //发送循环计数值
                        num++;
                        if(num==60)
                        {
                                num=0;
                        }
                }
        }

}

上位机程序如下:
unit Myserial;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, SPComm, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button3: TButton;
    ComboBox1: TComboBox;
    Edit2: TEdit;
    Comm1: TComm;
    Label2: TLabel;
    Button2: TButton;
    Button4: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);   //打开串口
begin
      try
          comm1.CommName:='com'+inttostr(combobox1.ItemIndex);
          comm1.BaudRate:=9600;
          comm1.ParityCheck:=false;
          comm1.ByteSize:=_8;
          comm1.StopBits:=_1;
          comm1.startcomm;
          button1.Enabled:=false;    //串口打开按钮
          button2.Enabled:=true;      // RUN按钮
          button3.Enabled:=true;        //  串口关闭按钮
          button4.Enabled:=true;          // STOP按钮
       except
          showmessage('打开串口错误');
       end;

end;

procedure TForm1.Button2Click(Sender: TObject);       //启动跑马表
var
  commandrun:string;
  count:integer;
begin
  commandrun:=inttostr($a0);
  count:=length(commandrun);
if comm1.WriteCommData(pchar(commandrun),count) then
  exit
else  showmessage('启动失败');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
    comm1.stopcomm ;
    button1.enabled := true ;
end;

procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;  //串口接收循环计数值
  BufferLength: Word);
  var
    rbuf:array of byte;
    receivedata:string;
    i:integer;
begin
    setlength(rbuf,bufferlength);
    move(buffer^,pchar(@rbuf)^,bufferlength);
for i:=1 to bufferlength do
begin
    receivedata:=inttostr(rbuf);
    edit2.Text:=receivedata;
end;
end;

procedure TForm1.Button4Click(Sender: TObject);        //停止跑马表
var
  commandstop:string;
  counter:integer;
begin
  commandstop:=inttostr($a1);
  counter:=length(commandstop);
if comm1.WriteCommData(pchar(commandstop),counter) then
      exit
else  showmessage('停止失败');

end;

end.
所有的程序都在里面ourdev_500827.rar(文件大小:197K) (原文件名:DELPHI初学者编上位机的问题.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
头像被屏蔽

出0入0汤圆

发表于 2009-11-7 19:12:32 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入70汤圆

发表于 2009-11-7 20:45:29 | 显示全部楼层
发送 和 接收的代码都有问题

发送改为
comm1.WriteCommData(PAnsiChar(char($A0),1);

接收
Var
  Str: String;
Begin
  SetLength(Str, BufferLength);
  Move(Buffer^, PChar(@Str[1])^, BufferLength);
  edit2.Text: = Str;
end;

出0入0汤圆

 楼主| 发表于 2009-11-7 21:43:13 | 显示全部楼层
请教二楼大虾:
我已经按照您说的改了我的上位机程序.
发送部分如下:
procedure TForm1.Button2Click(Sender: TObject);       //启动跑马表
begin
if comm1.WriteCommData(pchar(char($a0)),1)  then
  exit
else  showmessage('启动失败');
end;

procedure TForm1.Button4Click(Sender: TObject);        //停止跑马表
begin
if comm1.WriteCommData(pchar(char($a1)),1)   then
  exit
else  showmessage('停止失败');
end;

接收部分:
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;  //串口接收循环计数值
  BufferLength: Word);
  var
  str:string;
begin
    setlength(str,bufferlength);
    move(buffer^,pchar(@str[1])^,bufferlength);
    edit2.Text:=str;
  end;

问题:我在调试的过程遇到了问题:当打开串口,点击RUN按钮时,会弹出错误对话框(见附件),并且也看不到接收的数值!
请问这是怎么回事?也不知道是不是我改对了。还有一个问题就是我的错误之处为什么要按照您说的那样改?谢谢

错误对话框 (原文件名:错误.png)

出0入0汤圆

发表于 2009-11-7 22:07:43 | 显示全部楼层
是否试过 cport 控件?

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3411130&bbs_page_no=1&search_mode=1&search_text=cport&bbs_id=9999

出0入0汤圆

 楼主| 发表于 2009-11-7 22:27:53 | 显示全部楼层
cport 控件我没用过。
我是DELPHI初学者,现在的问题是我不知道自己编的DELPHI程序问题出在哪。
哎,烦恼啊

出0入70汤圆

发表于 2009-11-8 01:18:43 | 显示全部楼层
你用的是DELPHI2009或DELPHI2010???

DELPHI2009与之前的DELPHI版本都有兼容问题,因为DELPHI2009是以UniCode为基础了

出0入0汤圆

 楼主| 发表于 2009-11-8 09:09:39 | 显示全部楼层
我用的是DELPHI7+SPCOMM+VISTA操作系统。
请大虾帮忙解决一下我的问题啊。谢谢

出0入0汤圆

 楼主| 发表于 2009-11-8 17:11:44 | 显示全部楼层
没人可以帮我解决下问题?

出0入70汤圆

发表于 2009-11-8 18:55:55 | 显示全部楼层
之前我贴的有点不对,没检查,因为SPCOMM的修改版众多,各有不同

现在这个我测试过了,但下位机我没测试,我仅用是虚拟两个串口测试,发送我接收都正常

Procedure TForm1.Button2Click(Sender: TObject);
Begin
  If Not Comm1.WriteCommData(Char($A0), 1) Then
    showmessage('启动失败');
End;

Procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
  BufferLength: Word);
Var
  Str: String;
Begin
  SetLength(Str, BufferLength);
  Move(Buffer^, pchar(@Str[1])^, BufferLength);
  Edit2.Text := Str;
End;

Procedure TForm1.Button4Click(Sender: TObject);
Begin
  If Not Comm1.WriteCommData(Char($A1), 1) Then
    showmessage('停止失败');
End;

出0入0汤圆

发表于 2009-11-8 19:52:30 | 显示全部楼层
手中没有spcomm,但是有一点,你单片机发送的数据对于Comm1ReceiveData来说是十六进制的,你用inttostr(rbuf),得到的结果,明显不会是1,2,3,4什么的。
12345678
对应的是 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38
也许你在串口调试助手的hex模式下看到了数字。那个不是你要的字符

出0入0汤圆

 楼主| 发表于 2009-11-8 22:29:31 | 显示全部楼层
现在按照9楼大虾的做法,我已经改了代码。
出现的现象是:按了几次RUN键,再按几次STOP键以后,数值显示框中开始一会儿有显示(显示的乱七八糟的字符),一会没显示。10楼大虾说得对,我是在串口调试助手的hex模式下看到了数字。
请问大虾们,现在应该怎么办?
我现在将我使用的SPCOMM控件传到附件里,大虾们可以下载之后,用此SPCOMM控件帮我想想。
另外,我想问问,我的下位机程序有没有什么问题?不会是下位机出了问题吧?
请大虾们持续关注这个帖子啊!!
小弟谢谢帮助我的大虾们哈!!!
SPCOMM控件ourdev_501255.rar(文件大小:284K) (原文件名:spcommSPComm串口控件及例子程序.rar)

出0入70汤圆

发表于 2009-11-9 00:38:46 | 显示全部楼层
SBUF=send_data/10*16+send_data%10; //将要发送的数据转换成10进制
不要做转换

出0入0汤圆

发表于 2009-11-9 01:28:42 | 显示全部楼层
直接用函数:inttohex( , ) 将接收的数据显示出来。
因为有些数值对应的是无法显示的char

出0入0汤圆

 楼主| 发表于 2009-11-9 11:04:12 | 显示全部楼层
我现在按照12楼和13楼大虾的意见,做了如下改动:
上位机接收代码:
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;  //串口接收循环计数值
  BufferLength: Word);
  var
  viewstring:string;
  rbuf:array of byte;
  i:integer;

begin
    viewstring:='';
    setlength(rbuf,bufferlength);
    move(buffer^,pchar(@rbuf)^,bufferlength);
    sleep(10);//这句要不要加?
    for i:=1 to bufferlength do
    begin
    viewstring:=inttohex(rbuf,2)+'';
    end;
    edit2.Text:=viewstring;
  end;
对于下位机发送函数,我按照12楼大虾的意见已经改成了SBUF=send_data;
但还是有问题存在:连续点点击几次RUN按钮后,数值显示框里的数值才开始有数值,并且乱跳。跳了几次后,弹出第一个错误对话框;点‘确定’后,又跳了几次,弹出第二个错误对话框。然后上位机窗口自动关闭!
请问大虾们,这是怎么回事啊?应该怎么改啊?我想得头都要炸了,烦!

第一个错误对话框 (原文件名:错误.png)


第二个错误对话框 (原文件名:错误1.png)

出0入0汤圆

 楼主| 发表于 2009-11-9 12:17:58 | 显示全部楼层
大虾们回答我的问题哦。

出0入0汤圆

 楼主| 发表于 2009-11-9 21:49:13 | 显示全部楼层
大虾们给点意见哦。我急啊!

出0入0汤圆

 楼主| 发表于 2009-11-10 00:10:47 | 显示全部楼层
快来个高手指点指点我哦。急死我啦!

出0入0汤圆

发表于 2009-11-10 09:59:42 | 显示全部楼层
viewstring:='';
    setlength(rbuf,bufferlength);
    move(buffer^,pchar(@rbuf)^,bufferlength);
    sleep(10);//这句要不要加? //去掉
    for i:=1 to bufferlength do //for i:=0 to bufferlength-1 do
    begin
    viewstring:=inttohex(rbuf,2)+'';
    end;
    edit2.Text:=viewstring;
另外,要学会错误控制
try
do something ....
except
  error code here
end;

出0入0汤圆

发表于 2009-11-10 10:55:17 | 显示全部楼层
刚开始就不要学dlphi了,没落了

出0入0汤圆

发表于 2009-11-10 22:16:29 | 显示全部楼层
主要问题是单片机程序严重错误!
=================================================
void Serial_Send(uchar send_data) //串口发送函数
{
  ES=0;         //// 注意
  SBUF=send_data;
  while(!TI);
  TI=0;
  ES=1;
}
*******************************
发送这里不断禁止了串口中断,计算机来的数据如何接收?
===================================================
void serial_receive() interrupt 4 using 0 //串口中断接收函数
{
  RI=0;  
  receive_data=SBUF;
  switch(receive_data)
  {
    case 0xa0: //CPU收到0A0H就启动定时器0
             timer_start_flag=1;
    break;
    case 0xa1: //CPU收到0A1H就关闭定时器0
            timer_stop_flag=1;
    break;
   }
}
*******************
这样写,说明你对51的串口中断没有读透
========================================

出0入0汤圆

发表于 2009-11-10 22:22:25 | 显示全部楼层
正好在学delphi 看看

出0入0汤圆

 楼主| 发表于 2009-11-10 22:25:21 | 显示全部楼层
单片机程序严重错误?
那为什么此程序和串口调试助手通信没有问题?
疑惑。
我是初学者,请教楼上大虾,程序具体应该如何修改?

出0入0汤圆

发表于 2009-11-11 00:13:04 | 显示全部楼层
void Serial_Send(uchar send_data) //串口发送函数
{
  SBUF=send_data;
  while(!TI);
  TI=0;
}

void serial_receive() interrupt 4 using 0 //串口中断接收函数
{
  if(RI)
  {
    RI=0;  
    receive_data=SBUF;
    switch(receive_data)
    {
      case 0xa0: //CPU收到0A0H就启动定时器0
                timer_start_flag=1;
      break;
      case 0xa1: //CPU收到0A1H就关闭定时器0
                timer_start_flag=0;
      break;
     }
    }
}  

void main()
{
  System_Init();
  while(1)
  {
     if (timer_start_flag==1){TR0=1;} else {TR0=0;}   

     if(timer_1s_flag==1)
     {
         timer_1s_flag=0;
         Serial_Send(num); //发送循环计数值
         num++;
         if(num==60) {num=0;}
     }
  }
}

出0入0汤圆

 楼主| 发表于 2009-11-11 17:27:54 | 显示全部楼层
请教各位大虾:
在我的DELPHI上位机接收部分代码作如下改动:
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;  //串口接收循环计数值
  BufferLength: Word);
  var
  viewstring:string;
  rbuf:array[0..7] of byte;
  i:integer;

begin
    viewstring:='';
    setlength(rbuf,bufferlength);
    move(buffer^,pchar(@rbuf)^,bufferlength);  
    for i:=0 to bufferlength-1 do
    begin
    viewstring:=inttohex(rbuf,2)+'';
    end;
    edit2.Text:=viewstring;
  end;

现象:
数值显示框显示:00 01 02 03.....一直到59,然后又从0开始显示(正常,这正是我想要达到的目的!)。
但现在我的问题是:
既然程序里已经执行这条代码:viewstring:=inttohex(rbuf,2)+'';
viewstring 赋给数值显示框后为什么不是按十六制形式显示,也就是00 01 02 ...09 0a 0b .....一直到3B(也就是十进制的59)?
我很疑惑,希望各位大虾指点迷津!
谢谢!!!

出0入0汤圆

 楼主| 发表于 2009-11-11 22:08:23 | 显示全部楼层
希望大虾们帮我解答下我的疑惑哦。
谢谢

出0入0汤圆

 楼主| 发表于 2009-11-12 11:47:15 | 显示全部楼层
请大虾们快帮帮我哦。
急死我啦。
谢谢。

出0入70汤圆

发表于 2009-11-12 16:16:16 | 显示全部楼层
因为你下位机发过来的数据都不正确
所以你用了inttohex(rbuf,2)+'';也没用

如果不想改下位机了

上位机程序可以这样改viewstring := viewstring + inttohex(strtoint( inttohex(rbuf,2)),2) + ' ';

你的 "+'';" 这些没意义.

出0入0汤圆

 楼主| 发表于 2009-11-12 20:57:45 | 显示全部楼层
请教27楼大虾:
您改的这句代码是什么意思?
为什么最外层还是用inttohex()函数?这样不等于还是将rbuf中的数值转换成十六制形式显示吗?最外层为什么不用inttostr()函数
看不明白。
我是DELPHI初学者。您能详细解释吗?

出0入0汤圆

发表于 2009-11-13 01:55:01 | 显示全部楼层
问题还是你的单片机程序里,看:
==========================================
void Serial_Send(uchar send_data) //串口发送函数
{
ES=0;
SBUF=send_data/10*16+send_data%10; //将要发送的数据转换成10进制   =====》 你的原文,问题所在!分析在下面
// SBUF=send_data;
while(!TI);
TI=0;
ES=1;

}
============================================
以 send_data=59为例,
  send_data/10 *16+send_data %10 = 59 /10 *16 + 59 % 10 =89
  89 的 十六进制 为 $59 ,没错吧?

参考23楼的代码改吧

出0入0汤圆

 楼主| 发表于 2009-11-13 10:49:15 | 显示全部楼层
现在修改好的代码如下:
下位机:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar timer_start_flag;    //定时器0启动标志位
uchar timer_stop_flag; //定时器0停止标志位
uchar num; //循环计数值
uchar receive_data; //接收数据
uchar counter; //定时50毫秒溢出值
uchar timer_1s_flag; //定时1秒溢出标志位

void System_Init() //系统初始化
{
timer_start_flag=0;
timer_stop_flag=0;
timer_1s_flag=0;
num=0;
receive_data=0;
counter=0;
timer_1s_flag=0;

TMOD=0x21; //定时器1 工作方式2 定时器0 工作方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
SCON=0x50; //串口方式1 允许串口接收
TH1=0xfd; //9600波特率
TL1=0xfd;
ET0=1; //开定时器0中断
ET1=1; //开定时器1中断
ES=1; //开串口中断
EA=1; //开总中断
TR0=0; //关闭定时器0
TR1=1; //启动定时器1
}

void Serial_Send(uchar send_data) //串口发送函数
{
ES=0;
SBUF=send_data;
while(!TI);
TI=0;
ES=1;

}

void serial_receive() interrupt 4 using 0 //串口中断接收函数
{
RI=0;
receive_data=SBUF;
switch(receive_data)
{
case 0xa0: //CPU收到0A0H就启动定时器0
timer_start_flag=1;
break;
case 0xa1: //CPU收到0A1H就关闭定时器0
timer_stop_flag=1;
break;


}
}

void timer0() interrupt 1 using 1 //定时0中断函数
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
counter++;
if(counter==20) //定时1秒到了吗?
{
counter=0;
timer_1s_flag=1;
}
}


void main()
{
System_Init();
while(1)
{
if(timer_start_flag==1)
{
timer_start_flag=0;
TR0=1;
}

if(timer_stop_flag==1)
{
timer_stop_flag=0;
TR0=0;
}

if(timer_1s_flag==1)
{
timer_1s_flag=0;
Serial_Send(num); //发送循环计数值
num++;
if(num==60)
{
num=0;
}
}
}

}

上位机代码:
unit Myserial;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, SPComm, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button3: TButton;
    ComboBox1: TComboBox;
    Edit2: TEdit;
    Comm1: TComm;
    Label2: TLabel;
    Button2: TButton;
    Button4: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);   //打开串口
begin
      try
          comm1.CommName:='com'+inttostr(combobox1.ItemIndex);
          comm1.BaudRate:=9600;
          comm1.ParityCheck:=false;
          comm1.ByteSize:=_8;
          comm1.StopBits:=_1;
          comm1.startcomm;
          button1.Enabled:=false;    //串口打开按钮
          button2.Enabled:=true;      // RUN按钮
          button3.Enabled:=true;        //  串口关闭按钮
          button4.Enabled:=true;          // STOP按钮
       except
          showmessage('打开串口错误');
       end;

end;

procedure TForm1.Button2Click(Sender: TObject);       //启动跑马表
if not comm1.WriteCommData(char($a0),1)  then
  showmessage('启动失败');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
    comm1.stopcomm ;
    button1.enabled := true ;
end;

procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;  //串口接收循环计数值
  BufferLength: Word);
  var
  viewstring:string;
  rbuf:array[0..7] of byte;
  i:integer;

begin
  viewstring:='';
    move(buffer^,pchar(@rbuf)^,bufferlength);
    for i:=0 to bufferlength-1 do
    begin
    viewstring:=inttohex(rbuf,2);
    edit2.Text:=viewstring;
    end;
end;

procedure TForm1.Button4Click(Sender: TObject);        //停止跑马表
begin
if not comm1.WriteCommData(char($a1),1)   then
  showmessage('停止失败');
end;

end.


29楼大虾:
在下位机串口发送函数中,我认为在串口发送前需要关闭串口中断ES。否则,单片机发完数据后,会向CPU申请中断,从而进入串口中断接收函数,导致程序出乱。单片机发完数据后,再开串口中断ES。

程序运行后的现象:
数值显示框显示:00 01 02 03.....一直到59,然后又从0开始显示(正常,这正是我想要达到的目的!)。

但我现在有个问题,我是这样想的:
上位机接收到的数据存放到数组rbuf中,那么现在数组rbuf中的数据类型是十进制的byte型还是十六进制的byte型啊?

还有就是上位机接收程序里经执行这条代码:viewstring:=inttohex(rbuf,2);后
viewstring 再赋给数值edit2显示框后为什么不是按十六制形式显示,也就是00 01 02 ...09 0a 0b .....一直到3B(也就是十进制的59)?
难道edit2数值显示框会自动将viewstring中的十六进制字符串转换为十进制字符串显示?

这两个问题令我不解!
请各位大虾帮我解答下,谢谢!

出0入0汤圆

 楼主| 发表于 2009-11-13 21:42:10 | 显示全部楼层
大虾们,给解答下吧。

出0入0汤圆

 楼主| 发表于 2009-11-14 09:02:46 | 显示全部楼层
大虾们,给点解释哟。

出0入0汤圆

发表于 2009-11-14 10:59:44 | 显示全部楼层
有意思
如果直接写
edit2.Text := inttostr(rbuf);  
显示的是啥

出0入0汤圆

 楼主| 发表于 2009-11-14 12:18:19 | 显示全部楼层
呵呵,原先我就想这样写:
edit2.Text := inttostr(rbuf);     
但显示的现象是:0 1 2 ...9 16 17...反正数字就是乱跳,还能跳到80多。
但我这样写后:viewstring:=inttohex(rbuf,2);  
             edit2.Text:=viewstring;
显示就正常。
所以我感觉非常疑惑。
请各位大虾指点。谢谢

出0入0汤圆

发表于 2009-11-14 13:52:05 | 显示全部楼层
把下面这两个变量变为全局变量试试
viewstring:string;
  rbuf:array[0..7] of byte;
另外,有个问题,其实每次读到的bufferlength都是1,有没有那个循环都一样

出0入0汤圆

 楼主| 发表于 2009-11-14 14:41:01 | 显示全部楼层
我想问下大虾:
上位机接收到的数据存放到数组rbuf中后,那么现在数组rbuf中的数据类型是十进制的byte型还是十六进制的byte型啊?为什么?
这点我不太明白。

出0入0汤圆

发表于 2009-11-14 15:55:27 | 显示全部楼层
可以看作int吧,要不
inttohex(rbuf,2);   
怎么不报错呢

我觉得他类似于 unsigned char,取值范围0-255

16进制byte,搞不懂这个类型

在单片机程序里,我们习惯写
uchar v1 = 0xab;
或者写
uchar v1 = 171;
虽然写法不同,但是他们的存储方式一样的
在存储器中都是
B10101011

在delphi里写
var
v1 : byte;
v1 := $ab;

v1:= 171;
也是一样的

出0入0汤圆

 楼主| 发表于 2009-11-14 17:26:25 | 显示全部楼层
请问:
viewstring:=inttohex(rbuf,2); 与edit2.Text := inttostr(rbuf);
有什么不同?不都是转换成字符串吗?
为什么在数值显示框中显示的是不同的值?现象如34楼所述。
是不是数组rbuf中接收到的数据已经是用16进制形式表示的整数了?viewstring:=inttohex(rbuf,2);后也显示的是十六进制吧?为什么以十进制显示?
我是这样想的。

出0入0汤圆

发表于 2009-11-14 17:38:59 | 显示全部楼层
inttohex(rbuf,2); 转成16进制,比如inttohex(128,2)结果显示80; inttostr(128)结果显示128

出0入70汤圆

发表于 2009-11-14 20:13:52 | 显示全部楼层
本来是一个很简单的事情,可楼主的代码改来改去,一段代码用这个人的,另一段代码又用另一个人的,导致至今依然存在问题,必竟每个人的编程思想都有所不同

出0入0汤圆

发表于 2009-11-15 00:34:47 | 显示全部楼层
完整的C51代码:
#include <reg52.h>

#define uchar unsigned char

uchar num; //循环计数值
uchar receive_data; //接收数据
uchar counter; //定时50毫秒溢出值
uchar timer_1s_flag; //定时1秒溢出标志位

void System_Init() //系统初始化
{
  timer_1s_flag=0;
  num=0;
  receive_data=0;
  counter=0;

  TMOD=0x21; //定时器1 工作方式2 定时器0 工作方式1
  TH0=(65536-50000)/256;
  TL0=(65536-50000)%256;
  SCON=0x50; //串口方式1 允许串口接收
  TH1=0xfd; //9600波特率
  TL1=0xfd;
  ET0=1; //开定时器0中断
  ES=1; //开串口中断
  EA=1; //开总中断
  TR0=0; //关闭定时器0
  TR1=1; //启动定时器1
}

void serial() interrupt 4 //串口中断接收函数
{
  if(RI)
  {
    RI=0;
    receive_data=SBUF;
    switch(receive_data)
    {
      case 0x30:             //CPU收到0A0H就启动定时器0,原文用0xa0,为方便调试,改为0x30
                                 // 在proteus 仿真中,直接按键盘的 "0"
                TR0=1;
                break;
      case 0x31:             //CPU收到0A1H就关闭定时器0,原文用0xa1,为方便调试,改为0x31
                                 // 在proteus 仿真中,直接按键盘的 "1"
                TR0=0;
                break;
    }
  }
  else if(TI)
       {
         TI=0;
       }
}

void timer0() interrupt 1 //定时0中断函数
{
  TH0=(65536-50000)/256;
  TL0=(65536-50000)%256;
  counter++;
  if(counter==20) //定时1秒到了吗?
  {
    counter=0;
    timer_1s_flag=1;
  }
}

void main()
{
  System_Init();

  while(1)
  {
    if(timer_1s_flag==1)
    {
      timer_1s_flag=0;
      SBUF=num;
      num++;
      if(num==60)
      {
        num=0;
      }   
    }
  }
}
===========================================================
完整的delphi代码:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, SPComm;

type
  TForm1 = class(TForm)
    Comm161: TComm16;
    Edit1: TEdit;
    Button1: TButton;
    Button2: TButton;
    ComboBox1: TComboBox;
    Button3: TButton;
    Button4: TButton;
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Comm161ReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
   ss:string;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Comm161.CommName:=combobox1.Text;
  comm161.StartComm;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  comm161.StopComm;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ss:=chr($30);
  comm161.WriteCommData(pchar(ss),length(ss));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ss:=chr($31);
  comm161.WriteCommData(pchar(ss),length(ss));
end;

procedure TForm1.Comm161ReceiveData(Sender: TObject; Buffer: Pointer;
  BufferLength: Word);
var
  rbuf:^byte;
begin
  rbuf:=buffer;
  edit1.Text:=inttohex(rbuf^,2);
end;

end.
=========================================================================================================
C51的程序包,源代码+HEX文件ourdev_503280.rar(文件大小:9K) (原文件名:c51.rar)
delphi7.0的程序包,源代码+EXE文件ourdev_503281.rar(文件大小:174K) (原文件名:delphi7_source.rar)
proteus仿真文件,按数字“0”,“1”进行控制ourdev_503282.rar(文件大小:11K) (原文件名:proteus.rar)

=======================================================================================================
另外,“那么现在数组rbuf中的数据类型是十进制的byte型还是十六进制的byte型啊? ”这样的问题,显得无厘头。
在计算机里任何东西都是二进制的。
=======================================================================================================
上面的代码运行得很好,而且已经写得很清楚了,如果还不明白,请买块豆腐,自行了断。

出0入0汤圆

发表于 2009-11-15 13:02:35 | 显示全部楼层
谢谢楼上,我也标记一下。

出0入0汤圆

发表于 2009-11-16 09:13:49 | 显示全部楼层
比较佩服 fs_uncle的耐心~

出0入0汤圆

发表于 2009-11-16 11:10:34 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2009-11-18 19:28:50 | 显示全部楼层
小弟在此一并感谢所有帮助过我的大虾,尤其感谢fs_uncle大虾耐心帮我解答问题!!
谢谢你们!

出0入0汤圆

发表于 2010-4-20 16:22:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-13 21:13:14 | 显示全部楼层
fs_uncle真是神人,耐心又细心,小弟初来咋到,真的很佩服,顶一下。

出0入0汤圆

发表于 2011-9-23 09:04:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-5 16:58:30 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-11-5 20:21:13 | 显示全部楼层
Mark

出0入0汤圆

发表于 2012-8-30 10:33:13 | 显示全部楼层
mark  

出0入0汤圆

发表于 2013-1-3 20:42:26 | 显示全部楼层
SkyGz 发表于 2009-11-7 20:45
发送 和 接收的代码都有问题

发送改为

Delphi的定时器中断,是不是只有设置为125;250等,计时才是准确的?我将timer1.Interval设置为100时,两次时间间隔要是是0.109s,要么就是0.110;但是设置为125的时候,每次的时间间隔都是0.125

出0入0汤圆

发表于 2014-7-13 13:00:28 | 显示全部楼层
mark,我爱阿莫
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-18 15:31

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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