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