程序在壓縮包內
MATLAB源程序如下:
- function varargout = serial_communication(varargin)
- % 作者:羅
- % 功能;串口收發
- % 版本:20101103 V2.0
- gui_Singleton = 1;
- gui_State = struct('gui_Name', mfilename, ...
- 'gui_Singleton', gui_Singleton, ...
- 'gui_OpeningFcn', @serial_communication_OpeningFcn, ...
- 'gui_OutputFcn', @serial_communication_OutputFcn, ...
- 'gui_LayoutFcn', [] , ...
- 'gui_Callback', []);
- if nargin && ischar(varargin{1})
- gui_State.gui_Callback = str2func(varargin{1});
- end
- if nargout
- [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
- else
- gui_mainfcn(gui_State, varargin{:});
- end
- function serial_communication_OpeningFcn(hObject, eventdata, handles, varargin)
- handles.output = hObject;
- warning off all;
- %% 改變窗口左上角的圖標為icon.jpg
- javaFrame = get(hObject, 'JavaFrame');
- javaFrame.setFigureIcon(javax.swing.ImageIcon('icon.jpg'));
- %% 初始化參數
- hasData = false; %表征串口是否接收到數據
- isShow = false; %表征是否正在進行數據顯示,即是否正在執行函數dataDisp
- isStopDisp = false; %表征是否按下了【停止顯示】按鈕
- isHexDisp = false; %表征是否勾選了【十六進制顯示】
- isHexSend = false; %表征是否勾選了【十六進制發送】
- numRec = 0; %接收字符計數
- numSend = 0; %發送字符計數
- strRec = ''; %已接收的字符串
- %讀取圖片數據,只在第一次運行時讀取
- pathstr = fileparts(which(mfilename));
- if exist([pathstr '\lamb.mat'], 'file') == 2
- load([pathstr '\lamb.mat']);
- else
- openData = imread('green.jpg');
- closedData = imread('red.jpg');
- save lamb.mat openData closedData;
- end
- %% 將上述參數作為應用數據,存入窗口對象內
- setappdata(hObject, 'hasData', hasData);
- setappdata(hObject, 'strRec', strRec);
- setappdata(hObject, 'numRec', numRec);
- setappdata(hObject, 'numSend', numSend);
- setappdata(hObject, 'isShow', isShow);
- setappdata(hObject, 'isStopDisp', isStopDisp);
- setappdata(hObject, 'isHexDisp', isHexDisp);
- setappdata(hObject, 'isHexSend', isHexSend);
- setappdata(hObject, 'openData', openData);
- setappdata(hObject, 'closedData', closedData);
- %初始化串口狀態指示燈,串口燈默認為關閉狀態
- set(handles.lamb, 'cdata', closedData);
- guidata(hObject, handles);
- function varargout = serial_communication_OutputFcn(hObject, eventdata, handles)
- varargout{1} = handles.output;
- function com_Callback(hObject, ~, handles)
- function com_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function rate_Callback(hObject, eventdata, handles)
- function rate_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function jiaoyan_Callback(hObject, eventdata, handles)
- function jiaoyan_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function data_bits_Callback(hObject, eventdata, handles)
- function data_bits_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function stop_bits_Callback(hObject, eventdata, handles)
- function stop_bits_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function start_serial_Callback(hObject, eventdata, handles)
- % 【打開/關閉串口】按鈕的回調函數
- % 打開串口,并初始化相關參數
- %% 若按下【打開串口】按鈕,打開串口
- if get(hObject, 'value')
- %% 獲取串口的端口名
- com_n = sprintf('com%d', get(handles.com, 'value'));
- %% 獲取波特率
- rates = [300 600 1200 2400 4800 9600 19200 38400 43000 56000 57600 115200];
- baud_rate = rates(get(handles.rate, 'value'));
- %% 獲取校驗位設置
- switch get(handles.jiaoyan, 'value')
- case 1
- jiaoyan = 'none';
- case 2
- jiaoyan = 'odd';
- case 3
- jiaoyan = 'even';
- end
- %% 獲取數據位個數
- data_bits = 5 + get(handles.data_bits, 'value');
- %% 獲取停止位個數
- stop_bits = get(handles.stop_bits, 'value');
- %% 創建串口對象
- scom = serial(com_n);
- %% 配置串口屬性,指定其回調函數
- set(scom, 'BaudRate', baud_rate, 'Parity', jiaoyan, 'DataBits',...
- data_bits, 'StopBits', stop_bits, 'BytesAvailableFcnCount', 10,...
- 'BytesAvailableFcnMode', 'byte', 'BytesAvailableFcn', {@bytes, handles},...
- 'TimerPeriod', 0.05, 'timerfcn', {@dataDisp, handles});
- %% 將串口對象的句柄作為用戶數據,存入窗口對象
- set(handles.figure1, 'UserData', scom);
- %% 嘗試打開串口
- try
- fopen(scom); %打開串口
- catch % 若串口打開失敗,提示“串口不可獲得!”
- msgbox('串口不可獲得!');
- set(hObject, 'value', 0); %彈起本按鈕
- return;
- end
- %% 打開串口后,允許串口發送數據,清空接收顯示區,點亮串口狀態指示燈,
- %% 并更改本按鈕文本為“關閉串口”
- set(handles.period_send, 'Enable', 'on'); %啟用【自動發送】按鈕
- set(handles.manual_send, 'Enable', 'on'); %啟用【手動發送】按鈕
- set(handles.xianshi, 'string', ''); %清空接收顯示區
- set(handles.lamb, 'cdata', getappdata('openData')); %點亮串口狀態指示燈
- set(hObject, 'String', '關閉串口'); %設置本按鈕文本為“關閉串口”
- else %若關閉串口
- %% 停止并刪除定時器
- t = timerfind;
- if ~isempty(t)
- stop(t);
- delete(t);
- end
- %% 停止并刪除串口對象
- scoms = instrfind;
- stopasync(scoms);
- fclose(scoms);
- delete(scoms);
- %% 禁用【自動發送】和【手動發送】按鈕,熄滅串口狀態指示燈
- set(handles.period_send, 'Enable', 'off', 'value', 0); %禁用【自動發送】按鈕
- set(handles.manual_send, 'Enable', 'off'); %禁用【手動發送】按鈕
- set(handles.lamb, 'cdata', getappdata('closedData')); %熄滅串口狀態指示燈
- set(hObject, 'String', '打開串口'); %設置本按鈕文本為“打開串口”
- end
- function dataDisp(obj, event, handles)
- % 串口的TimerFcn回調函數
- % 串口數據顯示
- %% 獲取參數
- hasData = getappdata(handles.figure1, 'hasData'); %串口是否收到數據
- strRec = getappdata(handles.figure1, 'strRec'); %串口數據的字符串形式,定時顯示該數據
- numRec = getappdata(handles.figure1, 'numRec'); %串口接收到的數據個數
- %% 若串口沒有接收到數據,先嘗試接收串口數據
- if ~hasData
- bytes(obj, event, handles);
- end
- %% 若串口有數據,顯示串口數據
- if hasData
- %% 給數據顯示模塊加互斥鎖
- %% 在執行顯示數據模塊時,不接受串口數據,即不執行BytesAvailableFcn回調函數
- setappdata(handles.figure1, 'isShow', true);
- %% 若要顯示的字符串長度超過10000,清空顯示區
- if length(strRec) > 10000
- strRec = '';
- setappdata(handles.figure1, 'strRec', strRec);
- end
- %% 顯示數據
- set(handles.xianshi, 'string', strRec);
- %% 更新接收計數
- set(handles.rec,'string', numRec);
- %% 更新hasData標志,表明串口數據已經顯示
- setappdata(handles.figure1, 'hasData', false);
- %% 給數據顯示模塊解鎖
- setappdata(handles.figure1, 'isShow', false);
- end
-
- function bytes(obj, ~, handles)
- % 串口的BytesAvailableFcn回調函數
- % 串口接收數據
- %% 獲取參數
- strRec = getappdata(handles.figure1, 'strRec'); %獲取串口要顯示的數據
- numRec = getappdata(handles.figure1, 'numRec'); %獲取串口已接收數據的個數
- isStopDisp = getappdata(handles.figure1, 'isStopDisp'); %是否按下了【停止顯示】按鈕
- isHexDisp = getappdata(handles.figure1, 'isHexDisp'); %是否十六進制顯示
- isShow = getappdata(handles.figure1, 'isShow'); %是否正在執行顯示數據操作
- %% 若正在執行數據顯示操作,暫不接收串口數據
- if isShow
- return;
- end
- %% 獲取串口可獲取的數據個數
- n = get(obj, 'BytesAvailable');
- %% 若串口有數據,接收所有數據
- if n
- %% 更新hasData參數,表明串口有數據需要顯示
- setappdata(handles.figure1, 'hasData', true);
- %% 讀取串口數據
- a = fread(obj, n, 'uchar');
- %% 若沒有停止顯示,將接收到的數據解算出來,準備顯示
- if ~isStopDisp
- %% 根據進制顯示的狀態,解析數據為要顯示的字符串
- if ~isHexDisp
- c = char(a');
- else
- strHex = dec2hex(a')';
- strHex2 = [strHex; blanks(size(a, 1))];
- c = strHex2(:)';
- end
- %% 更新已接收的數據個數
- numRec = numRec + size(a, 1);
- %% 更新要顯示的字符串
- strRec = [strRec c];
- end
- %% 更新參數
- setappdata(handles.figure1, 'numRec', numRec); %更新已接收的數據個數
- setappdata(handles.figure1, 'strRec', strRec); %更新要顯示的字符串
- end
- function qingkong_Callback(hObject, eventdata, handles)
- %% 清空要顯示的字符串
- setappdata(handles.figure1, 'strRec', '');
- %% 清空顯示
- set(handles.xianshi, 'String', '');
- function stop_disp_Callback(hObject, eventdata, handles)
- %% 根據【停止顯示】按鈕的狀態,更新isStopDisp參數
- if get(hObject, 'Value')
- isStopDisp = true;
- else
- isStopDisp = false;
- end
- setappdata(handles.figure1, 'isStopDisp', isStopDisp);
- function radiobutton1_Callback(hObject, eventdata, handles)
- function radiobutton2_Callback(hObject, eventdata, handles)
- function togglebutton4_Callback(hObject, eventdata, handles)
- function hex_disp_Callback(hObject, eventdata, handles)
- %% 根據【十六進制顯示】復選框的狀態,更新isHexDisp參數
- if get(hObject, 'Value')
- isHexDisp = true;
- else
- isHexDisp = false;
- end
- setappdata(handles.figure1, 'isHexDisp', isHexDisp);
- function manual_send_Callback(hObject, eventdata, handles)
- scom = get(handles.figure1, 'UserData');
- numSend = getappdata(handles.figure1, 'numSend');
- val = get(handles.sends, 'UserData');
- numSend = numSend + length(val);
- set(handles.trans, 'string', num2str(numSend));
- setappdata(handles.figure1, 'numSend', numSend);
- %% 若要發送的數據不為空,發送數據
- if ~isempty(val)
- %% 設置倒計數的初值
- n = 1000;
- while n
- %% 獲取串口的傳輸狀態,若串口沒有正在寫數據,寫入數據
- str = get(scom, 'TransferStatus');
- if ~(strcmp(str, 'write') || strcmp(str, 'read&write'))
- fwrite(scom, val, 'uint8', 'async'); %數據寫入串口
- break;
- end
- n = n - 1; %倒計數
- end
- end
- function clear_send_Callback(hObject, eventdata, handles)
- %% 清空發送區
- set(handles.sends, 'string', '')
- %% 更新要發送的數據
- set(handles.sends, 'UserData', []);
- function checkbox2_Callback(hObject, eventdata, handles)
- function period_send_Callback(hObject, eventdata, handles)
- % 【自動發送】按鈕的Callback回調函數
- %% 若按下【自動發送】按鈕,啟動定時器;否則,停止并刪除定時器
- if get(hObject, 'value')
- t1 = 0.001 * str2double(get(handles.period1, 'string'));%獲取定時器周期
- t = timer('ExecutionMode','fixedrate', 'Period', t1, 'TimerFcn',...
- {@manual_send_Callback, handles}); %創建定時器
- set(handles.period1, 'Enable', 'off'); %禁用設置定時器周期的Edit Text對象
- set(handles.sends, 'Enable', 'inactive'); %禁用數據發送編輯區
- start(t); %啟動定時器
- else
- set(handles.period1, 'Enable', 'on'); %啟用設置定時器周期的Edit Text對象
- set(handles.sends, 'Enable', 'on'); %啟用數據發送編輯區
- t = timerfind; %查找定時器
- stop(t); %停止定時器
- delete(t); %刪除定時器
- end
- function period1_Callback(hObject, eventdata, handles)
- function period1_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function clear_count_Callback(hObject, eventdata, handles)
- %% 計數清零,并更新參數numRec和numSend
- set([handles.rec, handles.trans], 'string', '0')
- setappdata(handles.figure1, 'numRec', 0);
- setappdata(handles.figure1, 'numSend', 0);
- function copy_data_Callback(hObject, eventdata, handles)
- %% 設置是否允許復制接收數據顯示區內的數據
- if get(hObject,'value')
- set(handles.xianshi, 'enable', 'on');
- else
- set(handles.xianshi, 'enable', 'inactive');
- end
- function figure1_CloseRequestFcn(hObject, eventdata, handles)
- % 關閉窗口時,檢查定時器和串口是否已關閉
- % 若沒有關閉,則先關閉
- %% 查找定時器
- t = timerfind;
- %% 若存在定時器對象,停止并關閉
- if ~isempty(t)
- stop(t); %若定時器沒有停止,則停止定時器
- delete(t);
- end
- %% 查找串口對象
- scoms = instrfind;
- %% 嘗試停止、關閉刪除串口對象
- try
- stopasync(scoms);
- fclose(scoms);
- delete(scoms);
- end
- %% 關閉窗口
- delete(hObject);
- function hex_send_Callback(hObject, eventdata, handles)
- %% 根據【十六進制發送】復選框的狀態,更新isHexSend參數
- if get(hObject,'value')
- isHexSend = true;
- else
- isHexSend = false;
- end
- setappdata(handles.figure1, 'isHexSend', isHexSend);
- %% 更新要發送的數據
- sends_Callback(handles.sends, eventdata, handles);
- function sends_Callback(hObject, eventdata, handles)
- % 數據發送編輯區的Callback回調函數
- % 更新要發送的數據
- %% 獲取數據發送編輯區的字符串
- str = get(hObject, 'string');
- %% 獲取參數isHexSend的值
- isHexSend = getappdata(handles.figure1, 'isHexSend');
- if ~isHexSend %若為ASCII值形式發送,直接將字符串轉化為對應的數值
- val = double(str);
- else %若為十六進制發送,獲取要發送的數據
- n = find(str == ' '); %查找空格
- n =[0 n length(str)+1]; %空格的索引值
- %% 每兩個相鄰空格之間的字符串為數值的十六進制形式,將其轉化為數值
- for i = 1 : length(n)-1
- temp = str(n(i)+1 : n(i+1)-1); %獲得每段數據的長度,為數據轉換為十進制做準備
- if ~rem(length(temp), 2)
- b{i} = reshape(temp, 2, [])'; %將每段十六進制字符串轉化為單元數組
- else
- break;
- end
- end
- val = hex2dec(b)'; %將十六進制字符串轉化為十進制數,等待寫入串口
- end
- %% 更新要顯示的數據
- set(hObject, 'UserData', val);
- function lamb_Callback(hObject, eventdata, handles)
復制代碼
所有資料51hei提供下載:
serial_communication.rar
(34.92 KB, 下載次數: 214)
2019-4-23 12:43 上傳
點擊文件名下載附件
|