串口通信,一般是指RS232、RS422之间的通信。matlab中有专门的serial函数来创建串口对象。设串口ID号为COM1,则创建方法为:
复制内容到剪贴板
代码:
>>scom= serial('com1');
创建完串口对象后,一般需要设置串口对象的属性,否则,串口不会相互通信。
复制内容到剪贴板
代码:
>> get(scom)
ByteOrder = littleEndian
BytesAvailable = 0
BytesAvailableFcn =
BytesAvailableFcnCount = 48
BytesAvailableFcnMode = terminator
BytesToOutput = 0
ErrorFcn =
InputBufferSize = 512
Name= Serial-COM1
ObjectVisibility = on
OutputBufferSize = 512
OutputEmptyFcn =
RecordDetail = compact
RecordMode = overwrite
RecordName = record.txt
RecordStatus = off
Status = closed
Tag=
Timeout = 10
TimerFcn =
TimerPeriod = 1
TransferStatus = idle
Type= serial
UserData = []
ValuesReceived = 0
ValuesSent = 0
SERIAL specific properties:
BaudRate= 9600
BreakInterruptFcn =
DataBits = 8
DataTerminalReady = on
FlowControl = none
Parity = none
PinStatus = [1x1 struct]
PinStatusFcn =
Port= COM1
ReadAsyncMode = continuous
RequestToSend = off
StopBits = 1
Terminator = LF
这些属性中,要使串口真正通信,一般要设置这几个属性:
BaudRate:波特率;
Parity:奇偶校验类型;
DataBits:数据位,一般为8,不用设置;
StopBits:停止位,一般为1,不用设置;
TimerFcn :定时回调函数;
TimerPeriod:定时周期;
BytesAvailableFcn:字节计数回调函数
BytesAvailableFcnCount:字节计数
BytesAvailableFcnMode:一般设置为字节模式,即byte
串口通信时,数据一般按帧传送,有的数据量比较大,会将帧打包后发送。这里仅讨论下数据按帧发送的情况。
假设,计算机与单片机由串口相连,单片机每50ms会通过串口向计算机发送一帧数据,数据格式如下:
帧数据 = 帧头 + 数据 + 帧计数 + 校验和,共9个字节。
帧头:两字节 0X55、0XAA
数据:5字节 dat1 dat2 dat3 dat4 dat5
帧计数:1字节 0到255,加1循环(相当于给每帧做一个标记,以防丢帧)
校验和:1字节 数据求和,然后对256求余;仅作为校验之用。
假设,串口波特率115200,偶校验,其他属性为默认值。我们可以设置TimerPeriod = 0.05,TimerFcn = {@data_rec, handles}。属性设置语句为:
set(scom, 'Parity', 'even', 'BaudRate', 115200, 'TimerPeriod', 'TimerFcn', {@data_rec, handles})
回调函数可以这么写:
function data_rec(obj, event,handles)
n_bytes = get(obj, 'BytesAvailable');
if n_tytes == 9
flag =fread(obj, n_bytes, 'uint8');
%以下进行数据处理
elseif rem(n_tytes, 9)==0
flags =fread(obj, n_bytes, 'uint8');
%以下进行数据处理
else
%若连续四次rem(n_tytes, 9)~=0,将数据全部读出,解算出正确的帧,舍弃错误的帧。
end
这样的思路经实践证明是可以的。如果计算机同时要回传数据给单片机,可以在回调函数中的if语句前或后加上fwrite语句写数据到串口。例如,若每个200ms回传一次数据,则可以在回调函数中设定一个全局变量:
复制内容到剪贴板
代码:
freq_split =uint8(0);
每进一次回调函数,
复制内容到剪贴板
代码:
freq_split =freq_split + 1;
if freq_split >=5
freq_split = 0;
%写数据到串口
end
这里提一下,一般写数据到串口时,要设置为异步写,具体语句为:
复制内容到剪贴板
代码:
fwrite(obj,datas, 'uint8','async');
具体工程中,问题要复杂的多,读者遇到问题时还是要自己先仔细琢磨下。
《matlab GUI设计学习手记》中对串口编程进行了较为基础而完整的介绍,关键还在于回调函数的编写。
另外,书中也提到,如果要兼顾系统的稳定性和实时性,可以考虑用定时器来代替串口对象的TimerFcn,因为Timer似乎更强大,因为,Timer的执行模式若为FixedSpacing时,串口回调函数是顺序执行的,一个回调函数未执行完,才开始计时50ms,而不是不管你前一个回调运行完没,就开始计时。