收发缓冲区默认256字节,缓冲区满后抛弃新数据而不是覆盖
This commit is contained in:
parent
a669118180
commit
5eb2f08e98
|
@ -1,25 +1,9 @@
|
||||||
#include "Queue.h"
|
#include "_Core.h"
|
||||||
|
#include "Queue.h"
|
||||||
|
|
||||||
extern void EnterCritical();
|
extern void EnterCritical();
|
||||||
extern void ExitCritical();
|
extern void ExitCritical();
|
||||||
|
|
||||||
|
|
||||||
/*// 智能IRQ,初始化时备份,销毁时还原
|
|
||||||
// SmartIRQ相当霸道,它直接关闭所有中断,再也没有别的任务可以跟当前任务争夺MCU
|
|
||||||
class SmartIRQ
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SmartIRQ()
|
|
||||||
{
|
|
||||||
EnterCritical();
|
|
||||||
}
|
|
||||||
|
|
||||||
~SmartIRQ()
|
|
||||||
{
|
|
||||||
ExitCritical();
|
|
||||||
}
|
|
||||||
};*/
|
|
||||||
|
|
||||||
Queue::Queue(uint len) : _s(len)
|
Queue::Queue(uint len) : _s(len)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
@ -46,28 +30,29 @@ void Queue::Clear()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Queue::Push(byte dat)
|
void Queue::Enqueue(byte dat)
|
||||||
{
|
{
|
||||||
|
// 溢出不再接收
|
||||||
|
int total = _s.Capacity();
|
||||||
|
if(_size >= total) return;
|
||||||
|
|
||||||
_s[_head++] = dat;
|
_s[_head++] = dat;
|
||||||
//_head %= _s.Capacity();
|
//_head %= _s.Capacity();
|
||||||
// 除法运算是一个超级大祸害,它浪费了大量时间,导致串口中断接收丢数据
|
// 除法运算是一个超级大祸害,它浪费了大量时间,导致串口中断接收丢数据
|
||||||
if(_head >= _s.Capacity()) _head -= _s.Capacity();
|
if(_head >= total) _head -= total;
|
||||||
|
|
||||||
//SmartIRQ irq;
|
|
||||||
EnterCritical();
|
EnterCritical();
|
||||||
_size++;
|
_size++;
|
||||||
ExitCritical();
|
ExitCritical();
|
||||||
}
|
}
|
||||||
|
|
||||||
byte Queue::Pop()
|
byte Queue::Dequeue()
|
||||||
{
|
{
|
||||||
if(_size == 0) return 0;
|
if(_size == 0) return 0;
|
||||||
{
|
|
||||||
//SmartIRQ irq;
|
EnterCritical();
|
||||||
EnterCritical();
|
_size--;
|
||||||
_size--;
|
ExitCritical();
|
||||||
ExitCritical();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
昨晚发现串口频繁收发一段数据后出现丢数据现象,也即是size为0,然后tail比head小,刚开始小一个字节,然后会逐步拉大。
|
昨晚发现串口频繁收发一段数据后出现丢数据现象,也即是size为0,然后tail比head小,刚开始小一个字节,然后会逐步拉大。
|
||||||
|
@ -76,9 +61,10 @@ byte Queue::Pop()
|
||||||
该问题只能通过关闭中断来解决。为了减少关中断时间以提升性能,增加了专门的Read方法。
|
该问题只能通过关闭中断来解决。为了减少关中断时间以提升性能,增加了专门的Read方法。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int total = _s.Capacity();
|
||||||
byte dat = _s[_tail++];
|
byte dat = _s[_tail++];
|
||||||
//_tail %= _s.Capacity();
|
//_tail %= _s.Capacity();
|
||||||
if(_tail >= _s.Capacity()) _tail -= _s.Capacity();
|
if(_tail >= total) _tail -= total;
|
||||||
|
|
||||||
return dat;
|
return dat;
|
||||||
}
|
}
|
||||||
|
@ -92,6 +78,10 @@ byte Queue::Pop()
|
||||||
#endif
|
#endif
|
||||||
uint Queue::Write(const Buffer& bs)
|
uint Queue::Write(const Buffer& bs)
|
||||||
{
|
{
|
||||||
|
// 溢出不再接收
|
||||||
|
int total = _s.Capacity();
|
||||||
|
if(_size >= total) return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
1,数据写入队列末尾
|
1,数据写入队列末尾
|
||||||
2,如果还剩有数据,则从开头开始写入
|
2,如果还剩有数据,则从开头开始写入
|
||||||
|
@ -99,18 +89,20 @@ uint Queue::Write(const Buffer& bs)
|
||||||
4,如果队列过小,很有可能后来数据会覆盖前面数据
|
4,如果队列过小,很有可能后来数据会覆盖前面数据
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//byte* buf = (byte*)bs.GetBuffer();
|
|
||||||
uint len = bs.Length();
|
uint len = bs.Length();
|
||||||
|
|
||||||
|
// 如果队列满了,不需要覆盖
|
||||||
|
if(_size + len > total)
|
||||||
|
len = total - _size;
|
||||||
|
|
||||||
uint rs = 0;
|
uint rs = 0;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
// 计算这一个循环剩下的位置
|
// 计算这一个循环剩下的位置
|
||||||
uint remain = _s.Length() - _head;
|
uint remain = _s.Capacity() - _head;
|
||||||
// 如果要写入的数据足够存放
|
// 如果要写入的数据足够存放
|
||||||
if(len <= remain)
|
if(len <= remain)
|
||||||
{
|
{
|
||||||
//_s.Copy(buf, len, _head);
|
|
||||||
_s.Copy(_head, bs, rs, len);
|
_s.Copy(_head, bs, rs, len);
|
||||||
rs += len;
|
rs += len;
|
||||||
_head += len;
|
_head += len;
|
||||||
|
@ -120,20 +112,15 @@ uint Queue::Write(const Buffer& bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 否则先写一段,指针回到开头
|
// 否则先写一段,指针回到开头
|
||||||
//_s.Copy(buf, remain, _head);
|
|
||||||
_s.Copy(_head, bs, rs, remain);
|
_s.Copy(_head, bs, rs, remain);
|
||||||
//buf += remain;
|
|
||||||
len -= remain;
|
len -= remain;
|
||||||
rs += remain;
|
rs += remain;
|
||||||
_head = 0;
|
_head = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
EnterCritical();
|
||||||
//SmartIRQ irq;
|
_size += rs;
|
||||||
EnterCritical();
|
ExitCritical();
|
||||||
_size += rs;
|
|
||||||
ExitCritical();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
@ -151,47 +138,38 @@ uint Queue::Read(Buffer& bs)
|
||||||
|
|
||||||
uint len = bs.Length();
|
uint len = bs.Length();
|
||||||
if(!len) return 0;
|
if(!len) return 0;
|
||||||
//byte* buf = (byte*)bs.GetBuffer();
|
|
||||||
|
|
||||||
if(len > _size) len = _size;
|
if(len > _size) len = _size;
|
||||||
|
|
||||||
uint rs = 0;
|
uint rs = 0;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
|
int total = _s.Capacity();
|
||||||
// 计算这一个循环剩下的位置
|
// 计算这一个循环剩下的位置
|
||||||
uint remain = _s.Capacity() - _tail;
|
uint remain = total - _tail;
|
||||||
// 如果要读取的数据都在这里
|
// 如果要读取的数据都在这里
|
||||||
if(len <= remain)
|
if(len <= remain)
|
||||||
{
|
{
|
||||||
//_s.CopyTo(buf, len, _tail);
|
|
||||||
//_s.CopyTo(_tail, bs, rs, len);
|
|
||||||
bs.Copy(rs, _s, _tail, len);
|
bs.Copy(rs, _s, _tail, len);
|
||||||
rs += len;
|
rs += len;
|
||||||
_tail += len;
|
_tail += len;
|
||||||
if(_tail >= _s.Capacity()) _tail -= _s.Capacity();
|
if(_tail >= total) _tail -= total;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 否则先读一段,指针回到开头
|
// 否则先读一段,指针回到开头
|
||||||
//_s.CopyTo(buf, remain, _tail);
|
|
||||||
//_s.CopyTo(_tail, bs, rs, remain);
|
|
||||||
bs.Copy(rs, _s, _tail, remain);
|
bs.Copy(rs, _s, _tail, remain);
|
||||||
//buf += remain;
|
|
||||||
len -= remain;
|
len -= remain;
|
||||||
rs += remain;
|
rs += remain;
|
||||||
_tail = 0;
|
_tail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bs.SetLength(rs, false);
|
bs.SetLength(rs);
|
||||||
|
|
||||||
{
|
EnterCritical();
|
||||||
//SmartIRQ irq;
|
_size -= rs;
|
||||||
EnterCritical();
|
ExitCritical();
|
||||||
_size -= rs;
|
|
||||||
ExitCritical();
|
|
||||||
}
|
|
||||||
//if(_size == 0) _tail = _head;
|
|
||||||
|
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "ByteArray.h"
|
#include "ByteArray.h"
|
||||||
|
|
||||||
// 内存缓冲区
|
// 队列
|
||||||
// 缓冲区内有一个缓冲区,游标位置,数据长度。实际有效数据仅占用缓冲区中间部分,头尾都可能有剩余
|
// 内有一个缓冲区,游标位置,数据长度。实际有效数据仅占用缓冲区中间部分,头尾都可能有剩余
|
||||||
class Queue
|
class Queue
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -24,8 +24,8 @@ public:
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
void Push(byte dat);
|
void Enqueue(byte dat);
|
||||||
byte Pop();
|
byte Dequeue();
|
||||||
|
|
||||||
uint Write(const Buffer& bs); // 批量写入
|
uint Write(const Buffer& bs); // 批量写入
|
||||||
uint Read(Buffer& bs); // 批量读取
|
uint Read(Buffer& bs); // 批量读取
|
||||||
|
|
|
@ -39,6 +39,10 @@ void SerialPort::Init()
|
||||||
Pins[0] = Pins[1] = P0;
|
Pins[0] = Pins[1] = P0;
|
||||||
Ports[0] = Ports[1] = nullptr;
|
Ports[0] = Ports[1] = nullptr;
|
||||||
|
|
||||||
|
_dataBits = 8;
|
||||||
|
_parity = 0;
|
||||||
|
_stopBits = 1;
|
||||||
|
|
||||||
_taskidRx = 0;
|
_taskidRx = 0;
|
||||||
|
|
||||||
OnInit();
|
OnInit();
|
||||||
|
@ -67,10 +71,10 @@ void SerialPort::Set(COM index, int baudRate)
|
||||||
if(OnSet()) Opened = true;
|
if(OnSet()) Opened = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialPort::Set(byte parity, byte dataBits, byte stopBits)
|
void SerialPort::Set(byte dataBits, byte parity, byte stopBits)
|
||||||
{
|
{
|
||||||
_parity = parity;
|
|
||||||
_dataBits = dataBits;
|
_dataBits = dataBits;
|
||||||
|
_parity = parity;
|
||||||
_stopBits = stopBits;
|
_stopBits = stopBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,11 +82,12 @@ void SerialPort::Set(byte parity, byte dataBits, byte stopBits)
|
||||||
bool SerialPort::OnOpen()
|
bool SerialPort::OnOpen()
|
||||||
{
|
{
|
||||||
// 清空缓冲区
|
// 清空缓冲区
|
||||||
|
Tx.SetCapacity(256);
|
||||||
Tx.Clear();
|
Tx.Clear();
|
||||||
Rx.SetCapacity(0x80);
|
Rx.SetCapacity(256);
|
||||||
Rx.Clear();
|
Rx.Clear();
|
||||||
|
|
||||||
debug_printf("Serial%d Open(%d, %d, %d, %d) TX=P%c%d RX=P%c%d\r\n", Index + 1, _baudRate, _parity, _dataBits, _stopBits, _PIN_NAME(Pins[0]), _PIN_NAME(Pins[1]));
|
debug_printf("Serial%d::Open(%d, %d, %d, %d) TX=P%c%d RX=P%c%d Cache(TX=%d, RX=%d)\r\n", Index + 1, _baudRate, _dataBits, _parity, _stopBits, _PIN_NAME(Pins[0]), _PIN_NAME(Pins[1]), Tx.Capacity(), Rx.Capacity());
|
||||||
|
|
||||||
OnOpen2();
|
OnOpen2();
|
||||||
|
|
||||||
|
@ -113,7 +118,7 @@ bool SerialPort::OnWrite(const Buffer& bs)
|
||||||
Set485(false);
|
Set485(false);
|
||||||
#else*/
|
#else*/
|
||||||
// 如果队列已满,则强制刷出
|
// 如果队列已满,则强制刷出
|
||||||
if(Tx.Length() + bs.Length() > Tx.Capacity()) Flush(Sys.Clock / 40000);
|
//if(Tx.Length() + bs.Length() > Tx.Capacity()) Flush(Sys.Clock / 40000);
|
||||||
|
|
||||||
Tx.Write(bs);
|
Tx.Write(bs);
|
||||||
|
|
||||||
|
@ -132,7 +137,7 @@ bool SerialPort::Flush(uint times)
|
||||||
// 打开串口发送
|
// 打开串口发送
|
||||||
Set485(true);
|
Set485(true);
|
||||||
|
|
||||||
while(!Tx.Empty() && times > 0) times = SendData(Tx.Pop(), times);
|
while(!Tx.Empty() && times > 0) times = SendData(Tx.Dequeue(), times);
|
||||||
|
|
||||||
Set485(false);
|
Set485(false);
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,10 @@ class SerialPort : public ITransport, public Power
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
friend class ComProxy;
|
friend class ComProxy;
|
||||||
ushort _parity;
|
|
||||||
ushort _dataBits;
|
|
||||||
ushort _stopBits;
|
|
||||||
int _baudRate;
|
int _baudRate;
|
||||||
|
ushort _dataBits;
|
||||||
|
ushort _parity;
|
||||||
|
ushort _stopBits;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ public:
|
||||||
virtual ~SerialPort();
|
virtual ~SerialPort();
|
||||||
|
|
||||||
void Set(COM index, int baudRate = SERIAL_BAUDRATE);
|
void Set(COM index, int baudRate = SERIAL_BAUDRATE);
|
||||||
void Set(byte parity, byte dataBits, byte stopBits);
|
void Set(byte dataBits, byte parity, byte stopBits);
|
||||||
|
|
||||||
uint SendData(byte data, uint times = 3000);
|
uint SendData(byte data, uint times = 3000);
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,12 @@ extern void SerialPort_GetPins(byte index, byte remap, Pin* txPin, Pin* rxPin);
|
||||||
|
|
||||||
void SerialPort::OnInit()
|
void SerialPort::OnInit()
|
||||||
{
|
{
|
||||||
_parity = USART_Parity_No;
|
/*_parity = USART_Parity_No;
|
||||||
_dataBits = USART_WordLength_8b;
|
_dataBits = USART_WordLength_8b;
|
||||||
_stopBits = USART_StopBits_1;
|
_stopBits = USART_StopBits_1;*/
|
||||||
|
_dataBits = 8;
|
||||||
|
_parity = 0;
|
||||||
|
_stopBits = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SerialPort::OnSet()
|
bool SerialPort::OnSet()
|
||||||
|
@ -45,12 +48,26 @@ void SerialPort::OnOpen2()
|
||||||
|
|
||||||
SerialPort_Opening(*this);
|
SerialPort_Opening(*this);
|
||||||
|
|
||||||
|
const ushort paritys[] = { USART_Parity_No, USART_Parity_Even, USART_Parity_Odd };
|
||||||
|
if(_parity >= ArrayLength(paritys)) _parity = 0;
|
||||||
|
|
||||||
|
const ushort StopBits[] = { 1, USART_StopBits_1, 5, USART_StopBits_0_5, 2, USART_StopBits_2, 15, USART_StopBits_1_5 };
|
||||||
|
ushort stop = StopBits[1];
|
||||||
|
for(int i=0; i<ArrayLength(StopBits); i+=2)
|
||||||
|
{
|
||||||
|
if(StopBits[i] == _stopBits)
|
||||||
|
{
|
||||||
|
stop = StopBits[i+1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
USART_InitTypeDef p;
|
USART_InitTypeDef p;
|
||||||
USART_StructInit(&p);
|
USART_StructInit(&p);
|
||||||
p.USART_BaudRate = _baudRate;
|
p.USART_BaudRate = _baudRate;
|
||||||
p.USART_WordLength = _dataBits;
|
p.USART_WordLength = _dataBits == 8 ? USART_WordLength_8b : USART_WordLength_9b;
|
||||||
p.USART_StopBits = _stopBits;
|
p.USART_StopBits = stop;
|
||||||
p.USART_Parity = _parity;
|
p.USART_Parity = paritys[_parity];
|
||||||
USART_Init(st, &p);
|
USART_Init(st, &p);
|
||||||
|
|
||||||
// 串口接收中断配置,同时会打开过载错误中断
|
// 串口接收中断配置,同时会打开过载错误中断
|
||||||
|
@ -121,7 +138,7 @@ void SerialPort::OnWrite2()
|
||||||
void SerialPort::OnTxHandler()
|
void SerialPort::OnTxHandler()
|
||||||
{
|
{
|
||||||
if(!Tx.Empty())
|
if(!Tx.Empty())
|
||||||
USART_SendData((USART_TypeDef*)State, (ushort)Tx.Pop());
|
USART_SendData((USART_TypeDef*)State, (ushort)Tx.Dequeue());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
USART_ITConfig((USART_TypeDef*)State, USART_IT_TXE, DISABLE);
|
USART_ITConfig((USART_TypeDef*)State, USART_IT_TXE, DISABLE);
|
||||||
|
@ -136,7 +153,7 @@ void SerialPort::OnRxHandler()
|
||||||
// 判断缓冲区足够最小值以后才唤醒任务,减少时间消耗
|
// 判断缓冲区足够最小值以后才唤醒任务,减少时间消耗
|
||||||
// 缓冲区里面别用%,那会产生非常耗时的除法运算
|
// 缓冲区里面别用%,那会产生非常耗时的除法运算
|
||||||
byte dat = (byte)USART_ReceiveData((USART_TypeDef*)State);
|
byte dat = (byte)USART_ReceiveData((USART_TypeDef*)State);
|
||||||
Rx.Push(dat);
|
Rx.Enqueue(dat);
|
||||||
|
|
||||||
// 收到数据,开启任务调度。延迟_byteTime,可能还有字节到来
|
// 收到数据,开启任务调度。延迟_byteTime,可能还有字节到来
|
||||||
//!!! 暂时注释任务唤醒,避免丢数据问题
|
//!!! 暂时注释任务唤醒,避免丢数据问题
|
||||||
|
|
Loading…
Reference in New Issue