收发缓冲区默认256字节,缓冲区满后抛弃新数据而不是覆盖

This commit is contained in:
大石头X2 2017-01-10 15:41:09 +08:00
parent a669118180
commit 5eb2f08e98
5 changed files with 77 additions and 77 deletions

View File

@ -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为0tail比head小 size为0tail比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;
} }

View File

@ -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); // 批量读取

View File

@ -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);

View File

@ -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);

View File

@ -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可能还有字节到来
//!!! 暂时注释任务唤醒,避免丢数据问题 //!!! 暂时注释任务唤醒,避免丢数据问题