串口接收中断必须以极快的速度完成,否则会出现丢数据的情况

判断缓冲区足够最小值以后才唤醒任务,减少时间消耗
缓冲区里面别用%,那会产生非常耗时的除法运算
在三位触摸开关上测试1M串口通信,收发数据完整
This commit is contained in:
nnhy 2015-09-30 03:09:59 +00:00
parent 2df69092f9
commit f6b5ae1fac
2 changed files with 23 additions and 16 deletions

View File

@ -62,10 +62,10 @@ uint Controller::Dispatch(ITransport* port, ByteArray& bs, void* param, void* pa
Controller* control = (Controller*)param; Controller* control = (Controller*)param;
#if MSG_DEBUG #if MSG_DEBUG
/*msg_printf("TinyNet::Dispatch[%d] ", len); msg_printf("TinyNet::Dispatch[%d] ", len);
// 输出整条信息 // 输出整条信息
Sys.ShowHex(buf, len, '-'); Sys.ShowHex(buf, len, '-');
msg_printf("\r\n");*/ msg_printf("\r\n");
#endif #endif
if(len > control->Port->MaxSize) if(len > control->Port->MaxSize)
{ {

View File

@ -41,7 +41,7 @@ void SerialPort::Init()
Error = 0; Error = 0;
IsRemap = false; IsRemap = false;
MinSize = 1; MinSize = 8;
_taskidRx = 0; _taskidRx = 0;
} }
@ -255,7 +255,7 @@ bool SerialPort::OnWrite(const ByteArray& bs)
//Tx.Write(bs); //Tx.Write(bs);
// 中断发送过于频繁,采用循环阻塞发送。后面考虑独立发送任务 // 中断发送过于频繁,影响了接收中断,采用循环阻塞发送。后面考虑独立发送任务
for(int i=0; i<bs.Length(); i++) for(int i=0; i<bs.Length(); i++)
{ {
SendData(bs[i], 300); SendData(bs[i], 300);
@ -331,12 +331,18 @@ uint SerialPort::OnRead(ByteArray& bs)
void SerialPort::OnRxHandler() void SerialPort::OnRxHandler()
{ {
byte dat = (byte)USART_ReceiveData(_port); // 串口接收中断必须以极快的速度完成,否则会出现丢数据的情况
Rx.Push(dat); // 判断缓冲区足够最小值以后才唤醒任务,减少时间消耗
//debug_printf(" 0x%02X ", dat); // 缓冲区里面别用%,那会产生非常耗时的除法运算
//while(USART_GetITStatus(_port, USART_IT_RXNE) != RESET)
{
byte dat = (byte)USART_ReceiveData(_port);
Rx.Push(dat);
//Sys.Delay(300);
}
// 收到数据开启任务调度。延迟_byteTime可能还有字节到来 // 收到数据开启任务调度。延迟_byteTime可能还有字节到来
if(_taskidRx) Sys.SetTask(_taskidRx, true, _byteTime); if(_taskidRx && Rx.Length() >= MinSize) Sys.SetTask(_taskidRx, true, _byteTime);
//if(!HasHandler()) return; //if(!HasHandler()) return;
@ -373,7 +379,7 @@ void SerialPort::Register(TransportHandler handler, void* param)
if(handler) if(handler)
{ {
// 建立一个未启用的任务,用于定时触发接收数据,收到数据时开启 // 建立一个未启用的任务,用于定时触发接收数据,收到数据时开启
if(!_taskidRx) _taskidRx = Sys.AddTask(ReceiveTask, this, -1, -1, "串口接收"); if(!_taskidRx) _taskidRx = Sys.AddTask(ReceiveTask, this, 1000000, 1000000, "串口接收");
} }
else else
{ {
@ -385,9 +391,9 @@ void SerialPort::Register(TransportHandler handler, void* param)
void SerialPort::OnHandler(ushort num, void* param) void SerialPort::OnHandler(ushort num, void* param)
{ {
SerialPort* sp = (SerialPort*)param; SerialPort* sp = (SerialPort*)param;
assert_param2(sp, "串口参数不能为空 OnHandler"); //assert_param2(sp, "串口参数不能为空 OnHandler");
if(USART_GetITStatus(sp->_port, USART_IT_TXE) != RESET) sp->OnTxHandler(); //if(USART_GetITStatus(sp->_port, USART_IT_TXE) != RESET) sp->OnTxHandler();
// 接收中断 // 接收中断
if(USART_GetITStatus(sp->_port, USART_IT_RXNE) != RESET) sp->OnRxHandler(); if(USART_GetITStatus(sp->_port, USART_IT_RXNE) != RESET) sp->OnRxHandler();
// 溢出 // 溢出
@ -395,7 +401,8 @@ void SerialPort::OnHandler(ushort num, void* param)
{ {
USART_ClearFlag(sp->_port, USART_FLAG_ORE); USART_ClearFlag(sp->_port, USART_FLAG_ORE);
// 读取并扔到错误数据 // 读取并扔到错误数据
USART_ReceiveData(sp->_port); //USART_ReceiveData(sp->_port);
debug_printf("Serial%d 溢出 \r\n", sp->_index + 1);
} }
/*if(USART_GetFlagStatus(sp->_port, USART_FLAG_NE) != RESET) USART_ClearFlag(sp->_port, USART_FLAG_NE); /*if(USART_GetFlagStatus(sp->_port, USART_FLAG_NE) != RESET) USART_ClearFlag(sp->_port, USART_FLAG_NE);
if(USART_GetFlagStatus(sp->_port, USART_FLAG_FE) != RESET) USART_ClearFlag(sp->_port, USART_FLAG_FE); if(USART_GetFlagStatus(sp->_port, USART_FLAG_FE) != RESET) USART_ClearFlag(sp->_port, USART_FLAG_FE);
@ -467,9 +474,9 @@ SerialPort* SerialPort::GetMessagePort()
_printf_sp = new SerialPort(port); _printf_sp = new SerialPort(port);
#if DEBUG #if DEBUG
#ifdef STM32F0 #ifdef STM32F0
_printf_sp->Tx.SetCapacity(256); //_printf_sp->Tx.SetCapacity(256);
#else #else
_printf_sp->Tx.SetCapacity(1024); //_printf_sp->Tx.SetCapacity(1024);
#endif #endif
#endif #endif
_printf_sp->Open(); _printf_sp->Open();