找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2895|回复: 2
收起左侧

MATLAB实现串口调试助手源程序

[复制链接]
wang20052531 发表于 2019-4-23 12:44 | 显示全部楼层 |阅读模式
程序在压缩包内
0.png

MATLAB源程序如下:
  1. function varargout = serial_communication(varargin)
  2. %   作者:罗
  3. %   功能;串口收发
  4. %   版本:20101103 V2.0
  5. gui_Singleton = 1;
  6. gui_State = struct('gui_Name',       mfilename, ...
  7.                    'gui_Singleton',  gui_Singleton, ...
  8.                    'gui_OpeningFcn', @serial_communication_OpeningFcn, ...
  9.                    'gui_OutputFcn',  @serial_communication_OutputFcn, ...
  10.                    'gui_LayoutFcn',  [] , ...
  11.                    'gui_Callback',   []);
  12. if nargin && ischar(varargin{1})
  13.     gui_State.gui_Callback = str2func(varargin{1});
  14. end

  15. if nargout
  16.     [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
  17. else
  18.     gui_mainfcn(gui_State, varargin{:});
  19. end

  20. function serial_communication_OpeningFcn(hObject, eventdata, handles, varargin)
  21. handles.output = hObject;
  22. warning off all;
  23. %% 改变窗口左上角的图标为icon.jpg
  24. javaFrame = get(hObject, 'JavaFrame');
  25. javaFrame.setFigureIcon(javax.swing.ImageIcon('icon.jpg'));
  26. %% 初始化参数
  27. hasData = false;         %表征串口是否接收到数据
  28. isShow = false;          %表征是否正在进行数据显示,即是否正在执行函数dataDisp
  29. isStopDisp = false;          %表征是否按下了【停止显示】按钮
  30. isHexDisp = false;           %表征是否勾选了【十六进制显示】
  31. isHexSend = false;        %表征是否勾选了【十六进制发送】
  32. numRec = 0;            %接收字符计数
  33. numSend = 0;           %发送字符计数
  34. strRec = '';                   %已接收的字符串
  35. %读取图片数据,只在第一次运行时读取
  36. pathstr = fileparts(which(mfilename));
  37. if exist([pathstr '\lamb.mat'], 'file') == 2
  38.     load([pathstr '\lamb.mat']);
  39. else
  40.     openData = imread('green.jpg');
  41.     closedData = imread('red.jpg');
  42.     save lamb.mat openData closedData;
  43. end
  44. %% 将上述参数作为应用数据,存入窗口对象内
  45. setappdata(hObject, 'hasData', hasData);
  46. setappdata(hObject, 'strRec', strRec);
  47. setappdata(hObject, 'numRec', numRec);
  48. setappdata(hObject, 'numSend', numSend);
  49. setappdata(hObject, 'isShow', isShow);
  50. setappdata(hObject, 'isStopDisp', isStopDisp);
  51. setappdata(hObject, 'isHexDisp', isHexDisp);
  52. setappdata(hObject, 'isHexSend', isHexSend);
  53. setappdata(hObject, 'openData', openData);
  54. setappdata(hObject, 'closedData', closedData);
  55. %初始化串口状态指示灯,串口灯默认为关闭状态
  56. set(handles.lamb, 'cdata', closedData);

  57. guidata(hObject, handles);

  58. function varargout = serial_communication_OutputFcn(hObject, eventdata, handles)
  59. varargout{1} = handles.output;

  60. function com_Callback(hObject, ~, handles)

  61. function com_CreateFcn(hObject, eventdata, handles)
  62. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  63.     set(hObject,'BackgroundColor','white');
  64. end

  65. function rate_Callback(hObject, eventdata, handles)

  66. function rate_CreateFcn(hObject, eventdata, handles)
  67. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  68.     set(hObject,'BackgroundColor','white');
  69. end

  70. function jiaoyan_Callback(hObject, eventdata, handles)

  71. function jiaoyan_CreateFcn(hObject, eventdata, handles)
  72. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  73.     set(hObject,'BackgroundColor','white');
  74. end

  75. function data_bits_Callback(hObject, eventdata, handles)

  76. function data_bits_CreateFcn(hObject, eventdata, handles)
  77. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  78.     set(hObject,'BackgroundColor','white');
  79. end

  80. function stop_bits_Callback(hObject, eventdata, handles)

  81. function stop_bits_CreateFcn(hObject, eventdata, handles)
  82. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  83.     set(hObject,'BackgroundColor','white');
  84. end

  85. function start_serial_Callback(hObject, eventdata, handles)
  86. %   【打开/关闭串口】按钮的回调函数
  87. %    打开串口,并初始化相关参数
  88. %% 若按下【打开串口】按钮,打开串口
  89. if get(hObject, 'value')
  90.     %% 获取串口的端口名
  91.     com_n = sprintf('com%d', get(handles.com, 'value'));
  92.     %% 获取波特率
  93.     rates = [300 600 1200 2400 4800 9600 19200 38400 43000 56000 57600 115200];
  94.     baud_rate = rates(get(handles.rate, 'value'));
  95.     %% 获取校验位设置
  96.     switch get(handles.jiaoyan, 'value')
  97.         case 1
  98.             jiaoyan = 'none';
  99.         case 2
  100.             jiaoyan = 'odd';
  101.         case 3
  102.             jiaoyan = 'even';
  103.     end
  104.     %% 获取数据位个数
  105.     data_bits = 5 + get(handles.data_bits, 'value');
  106.     %% 获取停止位个数
  107.     stop_bits = get(handles.stop_bits, 'value');
  108.     %% 创建串口对象
  109.     scom = serial(com_n);
  110.     %% 配置串口属性,指定其回调函数
  111.     set(scom, 'BaudRate', baud_rate, 'Parity', jiaoyan, 'DataBits',...
  112.         data_bits, 'StopBits', stop_bits, 'BytesAvailableFcnCount', 10,...
  113.         'BytesAvailableFcnMode', 'byte', 'BytesAvailableFcn', {@bytes, handles},...
  114.         'TimerPeriod', 0.05, 'timerfcn', {@dataDisp, handles});
  115.     %% 将串口对象的句柄作为用户数据,存入窗口对象
  116.     set(handles.figure1, 'UserData', scom);
  117.     %% 尝试打开串口
  118.     try
  119.         fopen(scom);  %打开串口
  120.     catch   % 若串口打开失败,提示“串口不可获得!”
  121.         msgbox('串口不可获得!');
  122.         set(hObject, 'value', 0);  %弹起本按钮
  123.         return;
  124.     end
  125.     %% 打开串口后,允许串口发送数据,清空接收显示区,点亮串口状态指示灯,
  126.     %% 并更改本按钮文本为“关闭串口”
  127.     set(handles.period_send, 'Enable', 'on');          %启用【自动发送】按钮
  128.     set(handles.manual_send, 'Enable', 'on');  %启用【手动发送】按钮
  129.     set(handles.xianshi, 'string', '');                         %清空接收显示区
  130.     set(handles.lamb, 'cdata', getappdata('openData')); %点亮串口状态指示灯
  131.     set(hObject, 'String', '关闭串口');                  %设置本按钮文本为“关闭串口”
  132. else  %若关闭串口
  133.     %% 停止并删除定时器
  134.     t = timerfind;
  135.     if ~isempty(t)
  136.         stop(t);
  137.         delete(t);
  138.     end
  139.     %% 停止并删除串口对象
  140.     scoms = instrfind;
  141.     stopasync(scoms);
  142.     fclose(scoms);
  143.     delete(scoms);
  144.     %% 禁用【自动发送】和【手动发送】按钮,熄灭串口状态指示灯
  145.     set(handles.period_send, 'Enable', 'off', 'value', 0); %禁用【自动发送】按钮
  146.     set(handles.manual_send, 'Enable', 'off');  %禁用【手动发送】按钮
  147.     set(handles.lamb, 'cdata', getappdata('closedData')); %熄灭串口状态指示灯
  148.     set(hObject, 'String', '打开串口');                  %设置本按钮文本为“打开串口”
  149. end

  150. function dataDisp(obj, event, handles)
  151. %        串口的TimerFcn回调函数
  152. %   串口数据显示
  153. %% 获取参数
  154. hasData = getappdata(handles.figure1, 'hasData'); %串口是否收到数据
  155. strRec = getappdata(handles.figure1, 'strRec');   %串口数据的字符串形式,定时显示该数据
  156. numRec = getappdata(handles.figure1, 'numRec');   %串口接收到的数据个数
  157. %% 若串口没有接收到数据,先尝试接收串口数据
  158. if ~hasData
  159.     bytes(obj, event, handles);
  160. end
  161. %% 若串口有数据,显示串口数据
  162. if hasData
  163.     %% 给数据显示模块加互斥锁
  164.     %% 在执行显示数据模块时,不接受串口数据,即不执行BytesAvailableFcn回调函数
  165.     setappdata(handles.figure1, 'isShow', true);
  166.     %% 若要显示的字符串长度超过10000,清空显示区
  167.     if length(strRec) > 10000
  168.         strRec = '';
  169.         setappdata(handles.figure1, 'strRec', strRec);
  170.     end
  171.     %% 显示数据
  172.     set(handles.xianshi, 'string', strRec);
  173.     %% 更新接收计数
  174.     set(handles.rec,'string', numRec);
  175.     %% 更新hasData标志,表明串口数据已经显示
  176.     setappdata(handles.figure1, 'hasData', false);
  177.     %% 给数据显示模块解锁
  178.     setappdata(handles.figure1, 'isShow', false);
  179. end

  180. function bytes(obj, ~, handles)
  181. %   串口的BytesAvailableFcn回调函数
  182. %   串口接收数据
  183. %% 获取参数
  184. strRec = getappdata(handles.figure1, 'strRec'); %获取串口要显示的数据
  185. numRec = getappdata(handles.figure1, 'numRec'); %获取串口已接收数据的个数
  186. isStopDisp = getappdata(handles.figure1, 'isStopDisp'); %是否按下了【停止显示】按钮
  187. isHexDisp = getappdata(handles.figure1, 'isHexDisp'); %是否十六进制显示
  188. isShow = getappdata(handles.figure1, 'isShow');  %是否正在执行显示数据操作
  189. %% 若正在执行数据显示操作,暂不接收串口数据
  190. if isShow
  191.     return;
  192. end
  193. %% 获取串口可获取的数据个数
  194. n = get(obj, 'BytesAvailable');
  195. %% 若串口有数据,接收所有数据
  196. if n
  197.     %% 更新hasData参数,表明串口有数据需要显示
  198.     setappdata(handles.figure1, 'hasData', true);
  199.     %% 读取串口数据
  200.     a = fread(obj, n, 'uchar');
  201.     %% 若没有停止显示,将接收到的数据解算出来,准备显示
  202.     if ~isStopDisp
  203.         %% 根据进制显示的状态,解析数据为要显示的字符串
  204.         if ~isHexDisp
  205.             c = char(a');
  206.         else
  207.             strHex = dec2hex(a')';
  208.             strHex2 = [strHex; blanks(size(a, 1))];
  209.             c = strHex2(:)';
  210.         end
  211.         %% 更新已接收的数据个数
  212.         numRec = numRec + size(a, 1);
  213.         %% 更新要显示的字符串
  214.         strRec = [strRec c];
  215.     end
  216.     %% 更新参数
  217.     setappdata(handles.figure1, 'numRec', numRec); %更新已接收的数据个数
  218.     setappdata(handles.figure1, 'strRec', strRec); %更新要显示的字符串
  219. end


  220. function qingkong_Callback(hObject, eventdata, handles)
  221. %% 清空要显示的字符串
  222. setappdata(handles.figure1, 'strRec', '');
  223. %% 清空显示
  224. set(handles.xianshi, 'String', '');

  225. function stop_disp_Callback(hObject, eventdata, handles)
  226. %% 根据【停止显示】按钮的状态,更新isStopDisp参数
  227. if get(hObject, 'Value')
  228.     isStopDisp = true;
  229. else
  230.     isStopDisp = false;
  231. end
  232. setappdata(handles.figure1, 'isStopDisp', isStopDisp);

  233. function radiobutton1_Callback(hObject, eventdata, handles)

  234. function radiobutton2_Callback(hObject, eventdata, handles)

  235. function togglebutton4_Callback(hObject, eventdata, handles)

  236. function hex_disp_Callback(hObject, eventdata, handles)
  237. %% 根据【十六进制显示】复选框的状态,更新isHexDisp参数
  238. if get(hObject, 'Value')
  239.     isHexDisp = true;
  240. else
  241.     isHexDisp = false;
  242. end
  243. setappdata(handles.figure1, 'isHexDisp', isHexDisp);

  244. function manual_send_Callback(hObject, eventdata, handles)
  245. scom = get(handles.figure1, 'UserData');
  246. numSend = getappdata(handles.figure1, 'numSend');
  247. val = get(handles.sends, 'UserData');
  248. numSend = numSend + length(val);
  249. set(handles.trans, 'string', num2str(numSend));
  250. setappdata(handles.figure1, 'numSend', numSend);
  251. %% 若要发送的数据不为空,发送数据
  252. if ~isempty(val)
  253.     %% 设置倒计数的初值
  254.     n = 1000;
  255.     while n
  256.         %% 获取串口的传输状态,若串口没有正在写数据,写入数据
  257.         str = get(scom, 'TransferStatus');
  258.         if ~(strcmp(str, 'write') || strcmp(str, 'read&write'))
  259.             fwrite(scom, val, 'uint8', 'async'); %数据写入串口
  260.             break;
  261.         end
  262.         n = n - 1; %倒计数
  263.     end
  264. end


  265. function clear_send_Callback(hObject, eventdata, handles)
  266. %% 清空发送区
  267. set(handles.sends, 'string', '')
  268. %% 更新要发送的数据
  269. set(handles.sends, 'UserData', []);

  270. function checkbox2_Callback(hObject, eventdata, handles)


  271. function period_send_Callback(hObject, eventdata, handles)
  272. %   【自动发送】按钮的Callback回调函数
  273. %% 若按下【自动发送】按钮,启动定时器;否则,停止并删除定时器
  274. if get(hObject, 'value')
  275.     t1 = 0.001 * str2double(get(handles.period1, 'string'));%获取定时器周期
  276.     t = timer('ExecutionMode','fixedrate', 'Period', t1, 'TimerFcn',...
  277.         {@manual_send_Callback, handles}); %创建定时器
  278.     set(handles.period1, 'Enable', 'off'); %禁用设置定时器周期的Edit Text对象
  279.     set(handles.sends, 'Enable', 'inactive'); %禁用数据发送编辑区
  280.     start(t);  %启动定时器
  281. else
  282.     set(handles.period1, 'Enable', 'on'); %启用设置定时器周期的Edit Text对象
  283.     set(handles.sends, 'Enable', 'on');   %启用数据发送编辑区
  284.     t = timerfind; %查找定时器
  285.     stop(t); %停止定时器
  286.     delete(t); %删除定时器
  287. end

  288. function period1_Callback(hObject, eventdata, handles)

  289. function period1_CreateFcn(hObject, eventdata, handles)
  290. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  291.     set(hObject,'BackgroundColor','white');
  292. end

  293. function clear_count_Callback(hObject, eventdata, handles)
  294. %% 计数清零,并更新参数numRec和numSend
  295. set([handles.rec, handles.trans], 'string', '0')
  296. setappdata(handles.figure1, 'numRec', 0);
  297. setappdata(handles.figure1, 'numSend', 0);

  298. function copy_data_Callback(hObject, eventdata, handles)
  299. %% 设置是否允许复制接收数据显示区内的数据
  300. if get(hObject,'value')
  301.     set(handles.xianshi, 'enable', 'on');
  302. else
  303.     set(handles.xianshi, 'enable', 'inactive');
  304. end

  305. function figure1_CloseRequestFcn(hObject, eventdata, handles)
  306. %   关闭窗口时,检查定时器和串口是否已关闭
  307. %   若没有关闭,则先关闭
  308. %% 查找定时器
  309. t = timerfind;
  310. %% 若存在定时器对象,停止并关闭
  311. if ~isempty(t)
  312.     stop(t);  %若定时器没有停止,则停止定时器
  313.     delete(t);
  314. end
  315. %% 查找串口对象
  316. scoms = instrfind;
  317. %% 尝试停止、关闭删除串口对象
  318. try
  319.     stopasync(scoms);
  320.     fclose(scoms);
  321.     delete(scoms);
  322. end
  323. %% 关闭窗口
  324. delete(hObject);

  325. function hex_send_Callback(hObject, eventdata, handles)
  326. %% 根据【十六进制发送】复选框的状态,更新isHexSend参数
  327. if get(hObject,'value')
  328.     isHexSend = true;
  329. else
  330.     isHexSend = false;
  331. end
  332. setappdata(handles.figure1, 'isHexSend', isHexSend);
  333. %% 更新要发送的数据
  334. sends_Callback(handles.sends, eventdata, handles);


  335. function sends_Callback(hObject, eventdata, handles)
  336. %   数据发送编辑区的Callback回调函数
  337. %   更新要发送的数据
  338. %% 获取数据发送编辑区的字符串
  339. str = get(hObject, 'string');
  340. %% 获取参数isHexSend的值
  341. isHexSend = getappdata(handles.figure1, 'isHexSend');
  342. if ~isHexSend %若为ASCII值形式发送,直接将字符串转化为对应的数值
  343.     val = double(str);
  344. else  %若为十六进制发送,获取要发送的数据
  345.     n = find(str == ' ');   %查找空格
  346.     n =[0 n length(str)+1]; %空格的索引值
  347.     %% 每两个相邻空格之间的字符串为数值的十六进制形式,将其转化为数值
  348.     for i = 1 : length(n)-1
  349.         temp = str(n(i)+1 : n(i+1)-1);  %获得每段数据的长度,为数据转换为十进制做准备
  350.         if ~rem(length(temp), 2)
  351.             b{i} = reshape(temp, 2, [])'; %将每段十六进制字符串转化为单元数组
  352.         else
  353.             break;
  354.         end
  355.     end
  356.     val = hex2dec(b)';     %将十六进制字符串转化为十进制数,等待写入串口
  357. end
  358. %% 更新要显示的数据
  359. set(hObject, 'UserData', val);


  360. function lamb_Callback(hObject, eventdata, handles)
复制代码

所有资料51hei提供下载:
serial_communication.rar (34.92 KB, 下载次数: 111)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

hongyPCB 发表于 2020-1-6 21:52 | 显示全部楼层
非常给力!
回复

使用道具 举报

cainiao125 发表于 2020-11-24 18:13 | 显示全部楼层
请问野人串口调试助手的数据指定文件存储是怎么实现呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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