久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4677|回復: 0
打印 上一主題 下一主題
收起左側

寢室電量提示系統(1)—上位機的編寫

[復制鏈接]
跳轉到指定樓層
樓主
ID:73735 發表于 2015-2-19 01:12 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本帖最后由 huge 于 2015-2-19 01:14 編輯

本例程的下位機單片機程序和視頻詳見:http://www.zg4o1577.cn/bbs/dpj-31602-1.html      本來這次是想寫一個類似QQ尾巴的程序,不過好像有點難,所以就先緩一緩,做了個這個:寢室電量提示系統。大概流程:使用軟件(上位機)打開一個記錄有寢室電量信息的Access文件,查詢低于一定電量的寢室,再將這些寢室號或時間信息通過RS232接口發送到點陣LED上顯示;不使用時,點陣LED平時當作時鐘使用。

首先是上位機的編寫。和以往一樣,我還是選delphi平臺來編寫。
【程序界面布局



整個程序分為串口和數據庫查詢兩部分。其中通信協議設置(均以十六進制發送、接收):
①PC發送數據包格式:
   (1)  發送顯示的數據組數:BB+AF+發送數據的組數(H)+00+00+00+00+00++00+AF+EE ;
   (2)  發送時間:                  BB+A2+14(20)+0C(12)+0B(11)+0A(10)+0D(13)+0E(14)+0B(11)+A2與月(0B)的異或+EE ;
                                             (即2012-11-10 13:14:11)
   (3)  發送寢室號:              BB+A8+00+03+06+02+03+00+00+A8與“寢室號03620”的“6”(06H)異或+EE ;
②單片機應答數據包格式:   BB+AA+00/01+00+00+00+00+00+00+AA+EE
                                             (其中第三個數據00/01:00表示顯示成功;01表示顯示失敗)
【代碼】

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms,
  Dialogs, ExtCtrls, SPComm, StdCtrls,  sBevel, Grids, DBGrids,
  dbcgrids, DB, ADODB, sSkinManager, SGridFunction, AdoConEd, sLabel,
  ComCtrls,Menus,ScrollText, acTitleBar, ImgList,
  acAlphaImageList, sCheckBox;
type
    TForm1 = class(TForm)
    Ports: TComboBox;
    Baud: TComboBox;
    Parity_bit: TComboBox;
    Data_bits: TComboBox;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Senddisp: TButton;
    Connect: TButton;
    Stop_bit: TComboBox;
    Label6: TLabel;
    Comm1: TComm;
    Image1: TImage;
    Label7: TLabel;
    Label8: TLabel;
    Battery: TEdit;
    Total: TEdit;
    Image2: TImage;
    StringGrid1: TStringGrid;
    ADOQuery1: TADOQuery;
    sSkinManager1: TsSkinManager;
    ADOConnection1: TADOConnection;
    Time: TsLabelFX;
    Timer1: TTimer;
    Time_settle: TsCheckBox;
    MainMenu1: TMainMenu;
    Database_set: TMenuItem;
    Open_database: TMenuItem;
    About: TMenuItem;
    sBevel1: TsBevel;

    Search: TButton;
    Quit: TMenuItem;
    ScrollText1: TScrollText;
    sAlphaImageList1: TsAlphaImageList;
    Timer2: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure PortsChange(Sender: TObject);
    procedure BaudChange(Sender: TObject);
    procedure Parity_bitChange(Sender: TObject);
    procedure Data_bitsChange(Sender: TObject);
    procedure Stop_bitChange(Sender: TObject);
    procedure ConnectClick(Sender: TObject);
    procedure SenddispClick(Sender: TObject);
    procedure BatteryKeyPress(Sender: TObject; var Key: Char);
    procedure Timer1Timer(Sender: TObject);
    procedure Open_databaseClick(Sender: TObject);
    procedure AboutClick(Sender: TObject);
    procedure SearchClick(Sender: TObject);
    procedure QuitClick(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
    procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);
  private
    { Private declarations }
    procedure EnumComPorts(Ports: TStrings);
    procedure SendString(const str:string);
    function StrToHexStr(const S:string):string;
    function HexStrToStr(const S:string):string;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
  SysTime:TSystemTime;
  i,i0:Integer;
implementation

{$R *.dfm}
{ TForm1 }

procedure TForm1.EnumComPorts(Ports: TStrings);       //獲取當前可用的串口
var
  KeyHandle: HKEY;
  ErrCode, Index: Integer;
  ValueName, Data: string;
  ValueLen, DataLen, ValueType: DWORD;
  TmpPorts: TStringList;
  Tmp4,Tmp5:TStringList;
begin
  ErrCode:= RegOpenKeyEx(HKEY_LOCAL_MACHINE,'HARDWARE\DEVICEMAP\SERIALCOMM',0,KEY_READ,KeyHandle);  if ErrCode <> ERROR_SUCCESS then
    ShowMessage('打開串口列表的注冊表項出錯');
  TmpPorts := TStringList.Create;
  Tmp4:= TStringList.Create;
  Tmp5 := TstringList.Create;
  try
    Index := 0;
    repeat
      ValueLen := 256;
      DataLen := 256;
      SetLength(ValueName, ValueLen);
      SetLength(Data, DataLen);
      ErrCode := RegEnumValue(KeyHandle, Index, PChar(ValueName),
        Cardinal(ValueLen), nil, @ValueType, PByte(PChar(Data)), @DataLen);
      if ErrCode = ERROR_SUCCESS then
      begin
        SetLength(Data, DataLen);
        TmpPorts.Add(Trim(Data));
        Inc(Index);
      end
      else if ErrCode <> ERROR_NO_MORE_ITEMS then
        ShowMessage('打開串口列表的注冊表項出錯');
    until (ErrCode <> ERROR_SUCCESS);
    TmpPorts.Sort;
    For Index:=0 To TmpPorts.Count-1 do
       begin
       if Length(TmpPorts[Index])<=4 then  // 'COM3'
          Tmp4.Add(TmpPorts[Index])
         else Tmp5.Add(TmpPorts[Index]);
       end;
    Tmp4.AddStrings(Tmp5);
    //Ports.Assign(TmpPorts);
    Ports.Assign(Tmp4);
  finally
    RegCloseKey(KeyHandle);
    TmpPorts.Free;
    Tmp4.Free;
    Tmp5.Free;
  end;
end;

function TForm1.HexStrToStr(const S: string): string;      //16進制字符串轉換成字符串
var
  t:Integer;
  ts:string;
  M,Code:Integer;
begin
  t:=1;
  Result:='';
  while t<=Length(S) do
  begin
    while (t<=Length(S)) and (not (S[t] in ['0'..'9','A'..'F','a'..'f'])) do
      inc(t);
    if (t+1>Length(S))or(not (S[t+1] in ['0'..'9','A'..'F','a'..'f'])) then
      ts:='$'+S[t]
    else
      ts:='$'+S[t]+S[t+1];
    Val(ts,M,Code);
    if Code=0 then
      Result:=Result+Chr(M);
    inc(t,2);
  end;
end;

procedure TForm1.SendString(const str: string);
begin
  Comm1.WriteCommData(Pchar(str),Length(str));
end;

function TForm1.StrToHexStr(const S: string): string;          //字符串轉換成16進制字符串
var
  I:Integer;
begin
  for I:=1 to Length(S) do
  begin
    if I=1 then
      Result:=IntToHex(StrToInt(S[1]),2)
    else Result:=Result+' '+IntToHex(StrToInt(S[I]),2);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);//初始化窗口
begin
  Self.DoubleBuffered:= True;
  ScrollText1.ScrollText:='------歡迎使用寢室電量提示系統 O(∩_∩)O~';
  StringGrid1.Cells[0, 0]:='序號';
  StringGrid1.Cells[1, 0]:='缺電寢室號';
  StringGrid1.Cells[2, 0]:='剩余電量(度)';
  EnumComPorts(Ports.Items);
  Ports.ItemIndex:=0;
  Comm1.CommName:=Ports.Text;
  Baud.ItemIndex:=5;
  Comm1.BaudRate:=StrToIntDef(Baud.Text,Comm1.BaudRate);
  Parity_bit.ItemIndex:=2;
  Comm1.Parity:=None;
  Data_bits.ItemIndex:=3;
  Comm1.ByteSize:=_8;
  Stop_bit.ItemIndex:=0;
  Comm1.StopBits:=_1;
end;

procedure TForm1.PortsChange(Sender: TObject);           //端口選項
begin
  Comm1.CommName:=Ports.Text;
end;

procedure TForm1.BaudChange(Sender: TObject);           //波特率選項
begin
  Comm1.BaudRate:=StrToIntDef(Baud.Text,Comm1.BaudRate)
end;

procedure TForm1.Parity_bitChange(Sender: TObject);       //校驗位選項
begin
  case Parity_bit.ItemIndex of
    0:Comm1.Parity:=Even;
    1:Comm1.Parity:=Mark;
    2:Comm1.Parity:=None;
    3:Comm1.Parity:=Odd;
    4:Comm1.Parity:=Space;
  end;
end;

procedure TForm1.Data_bitsChange(Sender: TObject);     //數據位選項
begin
  case Data_bits.ItemIndex of
    0:Comm1.ByteSize:=_5;
    1:Comm1.ByteSize:=_6;
    2:Comm1.ByteSize:=_7;
    3:Comm1.ByteSize:=_8;
  end;
end;

procedure TForm1.Stop_bitChange(Sender: TObject);      //停止位選項
begin
  case Stop_bit.ItemIndex of
    0:Comm1.StopBits:=_1;
    1:Comm1.StopBits:=_1_5;
    2:Comm1.StopBits:=_2;
  end;
end;

procedure TForm1.ConnectClick(Sender: TObject);       //連接串口按鈕事件
begin
  if Connect.Caption='連接串口' then
    begin
      Comm1.StartComm;
      Connect.Caption:='關閉串口';
      Image1.Visible:=false;
      Image2.Visible:=true;
      Ports.Enabled:=false;
      Baud.Enabled:=false;
      Parity_bit.Enabled:=false;
      Data_bits.Enabled:=false;
      Stop_bit.Enabled:=false;
      Senddisp.Enabled:=true;
    end
  else
    begin
      Comm1.StopComm;
      Connect.Caption:='連接串口';
      Image1.Visible:=true;
      Image2.Visible:=false;
      Ports.Enabled:=true;
      Baud.Enabled:=true;
      Parity_bit.Enabled:=true;
      Data_bits.Enabled:=true;
      Stop_bit.Enabled:=true;
      Senddisp.Enabled:=false;
    end;
end;

procedure TForm1.SenddispClick(Sender: TObject);
var
  strdata,stryear1,stryear0,strmonth,strday,strhour,strminute,strsecond:string;
begin
  if Time_settle.Checked=true then
    begin
      stryear1:=IntToHex(StrToInt(copy(IntToStr(SysTime.wYear),1,2)),2);
      stryear0:=IntToHex(StrToInt(copy(IntToStr(SysTime.wYear),3,2)),2);
      strmonth:=IntToHex(SysTime.wMonth,2);
      strday:=IntToHex(SysTime.wDay,2);
      strhour:=IntToHex(SysTime.wHour,2);
      strminute:=IntToHex(SysTime.wMinute,2);
      strsecond:=IntToHex(SysTime.wSecond,2);
      strdata:=HexStrToStr('BBA2'+stryear1+stryear0+strmonth+strday+strhour+strminute+strsecond+IntToHex(SysTime.wMonth Xor $A2,2)+'EE');
      if (trim(Total.Text) = '') or (trim(Total.Text) = '0') then
        begin
          SendString(HexStrToStr('BBAF01000000000000AFEE'));
            //格式 BB+AF+發送數據的組數(H)+00+00+00+00+00++00+AF+EE
          sleep(200);
          SendString(strdata);
            //格式 BB+A2+20+12+11+10+13+14+11+A2與月的異或+EE
          Timer2.Enabled:=false;
        end
      else
        begin
          i0:=StrToInt(Total.Text);
          SendString(HexStrToStr('BBAF'+IntToHex(i0+1,2)+'000000000000AFEE'));
            //格式 BB+AF+發送數據的組數(H)+00+00+00+00+00++00+AF+EE
          i:=1;
          sleep(200);
          SendString(strdata);
            //格式 BB+A2+14(20)+0C(12)+0B(11)+0A(10)+0D(13)+0E(14)+0B(11)+A2與月(0B)的異或+EE
          sleep(200);
          Timer2.Enabled:=true;
        end;
    end
  else
    begin
      if (trim(Total.Text) = '') or (trim(Total.Text) = '0') then
        Application.MessageBox('數據無效,無法發送!','警告',MB_ICONWARNING)
      else
        begin
          i0:=StrToInt(Total.Text);
          SendString(HexStrToStr('BBAF'+IntToHex(i0,2)+'000000000000AFEE'));
            //格式 BB+AF+發送數據的組數(H)+00+00+00+00+00++00+AF+EE
          i:=1;
          sleep(200);
          Timer2.Enabled:=true;
        end;
    end;
end;

procedure TForm1.BatteryKeyPress(Sender: TObject; var Key: Char);
begin
  if not (Key in ['0'..'9',#8]) then Key:=#0;
end;

procedure TForm1.Timer1Timer(Sender: TObject); //顯示當前時間,每隔1s更新一次
begin
  GetLocalTime(SysTime);
  Time.Caption:=IntToStr(SysTime.wYear)+'年'+Format('%.2d',[SysTime.wMonth])+'月'+Format('%.2d',[SysTime.wDay])+'日  '+Format('%.2d',[SysTime.wHour])+':'+Format('%.2d',[SysTime.wMinute])+':'+Format('%.2d',[SysTime.wSecond]);
end;

procedure TForm1.Open_databaseClick(Sender: TObject);
var
  constr: string;
begin
  if ( constr <> '') then
    ADOConnection1.ConnectionString := constr;
  if (EditConnectionString(ADOConnection1)) then//調用數據源窗口,判斷是否連接成功
    begin
      ADOConnection1.Connected:=False;
      ADOConnection1.Connected:=True;
      constr := ADOConnection1.ConnectionString;
      Search.Enabled:=true;
    end
  else
    begin
      constr := ADOConnection1.ConnectionString;
      ADOConnection1.ConnectionString := '';
    end;
end;


procedure TForm1.AboutClick(Sender: TObject);
begin
  Application.MessageBox('       ☆     寢室電量提示系統     ☆'+#13#13+
  '             Agent CopyRight@2012    '+#13+
  '                        by hun       ','關于',MB_OK);
end;

procedure TForm1.SearchClick(Sender: TObject);
begin
  ADOConnection1.Connected:=true;
  with ADOQuery1 do
  begin
    Close;
    SQL.Clear;
    SQL.Add('SELECT * FROM Sheet1  WHERE Battery <='+Battery.Text);  // 查詢數據庫
    Open;
  end;
  ShowQueryData(StringGrid1,ADOQuery1,0,1);
  if HaveData(StringGrid1, 1, 1)=false then
    Total.Text:='0'
  else
  Total.Text:=SetNumberFields(StringGrid1,0,1);
  ADOConnection1.Connected:=false;
end;

procedure TForm1.QuitClick(Sender: TObject);
begin
  if Application.MessageBox('您確定要退出嗎?','警告',MB_YESNO or MB_DEFBUTTON1)=IDYES then
    begin
      Application.Terminate;
    end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);

begin
  SendString(HexStrToStr('BBA8'+StrToHexStr(Format('%.5d',[StrToInt(StringGrid1.Cells[1, i])]))+'0000'+IntToHex(StrToInt('$'+StrToHexStr(copy(StringGrid1.Cells[1, i],Length(StringGrid1.Cells[1, i])-2,1))) Xor $A8,2)+'EE'));
    //格式 BB+A8+00+03+06+02+03+00+00+A8與03620的06h異或+EE
  i:=i+1;
  if i>i0 then
    Timer2.Enabled:=false;
end;

procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
  BufferLength: Word);
var
  rbuf:array[0..10] of Byte;
begin
  move(Buffer^,pchar(@rbuf)^,BufferLength);
  if (rbuf[1]<>rbuf[9]) or (inttohex(rbuf[2],2)='01') then
    Application.MessageBox('顯示失敗!','提示信息',MB_OK)
  else
    begin
      if inttohex(rbuf[2],2)='00' then
        Application.MessageBox('顯示成功!','提示信息',MB_OK)
      else
        Application.MessageBox('顯示失敗!','提示信息',MB_OK);
    end;
end;

end.

【查詢效果】

在編寫下位機的過程中,發現端口的設置有點多余,所以又重新布局,于是誕生了精簡版:











分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 激情欧美一区二区三区中文字幕 | 欧美亚洲视频在线观看 | 在线午夜 | 国产在线对白 | 99精品视频在线 | 在线免费观看黄a | 天天操 天天操 | 亚洲黄色成人网 | 国产激情一区二区三区 | 亚洲第一区国产精品 | 五月激情综合 | 国产极品车模吞精高潮呻吟 | 久久一二区 | 国产成人精品久久久 | 精品国产免费一区二区三区五区 | 在线观看视频亚洲 | 二区高清| 成人欧美一区二区三区在线观看 | 欧洲成人 | 免费成人av | 99re在线免费视频 | 中文字幕视频在线看 | 99精品网| 久久99精品久久久久久国产越南 | 国产精品1区2区3区 男女啪啪高潮无遮挡免费动态 | 亚洲一二三区不卡 | 国产日韩精品视频 | 九九伦理电影 | 亚洲精品99 | 成人精品国产一区二区4080 | 久99久视频| 亚洲一二三视频 | 天天天操操操 | 精品一区在线 | 欧美日韩一区二区三区不卡视频 | 欧美日韩亚洲国产综合 | 免费骚视频 | av在线成人 | 成人超碰| 亚洲精品www. | 日日夜夜草 |