收发缓冲区默认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 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为0tail比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;
}

View File

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

View File

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

View File

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

View File

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