调整串口默认波特率为115200,主频>=36M时1024000,主频>=72M时2048000。
同时缩小默认收发缓冲区大小,并在用到时才分配。 提升速度,降低缓冲区要求,减少内存占用。
This commit is contained in:
parent
cf0a6fe21b
commit
2a06ec612e
|
@ -28,66 +28,79 @@ SerialPort::~SerialPort()
|
|||
|
||||
void SerialPort::Init()
|
||||
{
|
||||
Index = COM_NONE;
|
||||
RS485 = nullptr;
|
||||
Error = 0;
|
||||
State = nullptr;
|
||||
Index = COM_NONE;
|
||||
RS485 = nullptr;
|
||||
Error = 0;
|
||||
State = nullptr;
|
||||
|
||||
Remap = 0;
|
||||
MinSize = 1;
|
||||
Remap = 0;
|
||||
MinSize = 1;
|
||||
|
||||
Pins[0] = Pins[1] = P0;
|
||||
Ports[0] = Ports[1] = nullptr;
|
||||
Pins[0] = Pins[1] = P0;
|
||||
Ports[0] = Ports[1] = nullptr;
|
||||
|
||||
_dataBits = 8;
|
||||
_parity = 0;
|
||||
_stopBits = 1;
|
||||
_dataBits = 8;
|
||||
_parity = 0;
|
||||
_stopBits = 1;
|
||||
|
||||
_taskidRx = 0;
|
||||
_taskidRx = 0;
|
||||
|
||||
OnInit();
|
||||
}
|
||||
|
||||
void SerialPort::Set(COM index, int baudRate)
|
||||
{
|
||||
Index = index;
|
||||
_baudRate = baudRate;
|
||||
Index = index;
|
||||
_baudRate = baudRate;
|
||||
|
||||
// 根据系统时钟自动计算默认波特率
|
||||
if (_baudRate <= 0)
|
||||
{
|
||||
int clock = Sys.Clock;
|
||||
if (clock >= 72)
|
||||
_baudRate = 2048000;
|
||||
else if (clock >= 36)
|
||||
_baudRate = 1024000;
|
||||
else
|
||||
_baudRate = 1152000;
|
||||
}
|
||||
|
||||
// 计算字节间隔。字节速度一般是波特率转为字节后再除以2
|
||||
//ByteTime = 15000000 / baudRate; // (1000000 /(baudRate/10)) * 1.5
|
||||
//ByteTime = 1000000 / (baudRate >> 3 >> 1);
|
||||
//ByteTime <<= 1;
|
||||
if(baudRate > 9600)
|
||||
ByteTime = 1;
|
||||
if (baudRate > 9600)
|
||||
ByteTime = 1;
|
||||
else
|
||||
ByteTime = 1000 / (baudRate / 10) + 1; // 小数部分忽略,直接加一
|
||||
ByteTime = 1000 / (baudRate / 10) + 1; // 小数部分忽略,直接加一
|
||||
|
||||
// 设置名称
|
||||
Buffer(Name, 4) = "COMx";
|
||||
Buffer(Name, 4) = "COMx";
|
||||
Name[3] = '0' + Index + 1;
|
||||
Name[4] = 0;
|
||||
|
||||
// 根据端口实际情况决定打开状态
|
||||
if(OnSet()) Opened = true;
|
||||
if (OnSet()) Opened = true;
|
||||
}
|
||||
|
||||
void SerialPort::Set(byte dataBits, byte parity, byte stopBits)
|
||||
{
|
||||
_dataBits = dataBits;
|
||||
_parity = parity;
|
||||
_stopBits = stopBits;
|
||||
_dataBits = dataBits;
|
||||
_parity = parity;
|
||||
_stopBits = stopBits;
|
||||
}
|
||||
|
||||
// 打开串口
|
||||
bool SerialPort::OnOpen()
|
||||
{
|
||||
// 需要是才申请缓冲区
|
||||
//if (Tx.Capacity() == 0) Tx.SetCapacity(64);
|
||||
if (Rx.Capacity() == 0 && HasHandler()) Rx.SetCapacity(64);
|
||||
// 清空缓冲区
|
||||
if(Tx.Capacity() == 0) Tx.SetCapacity(256);
|
||||
if(Rx.Capacity() == 0) Rx.SetCapacity(256);
|
||||
Tx.Clear();
|
||||
Rx.Clear();
|
||||
|
||||
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());
|
||||
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();
|
||||
|
||||
|
@ -99,7 +112,7 @@ bool SerialPort::OnOpen()
|
|||
// 关闭端口
|
||||
void SerialPort::OnClose()
|
||||
{
|
||||
debug_printf("~Serial%d Close\r\n", Index + 1);
|
||||
debug_printf("~Serial%d Close\r\n", Index + 1);
|
||||
|
||||
OnClose2();
|
||||
}
|
||||
|
@ -107,26 +120,33 @@ void SerialPort::OnClose()
|
|||
// 向某个端口写入数据。如果size为0,则把data当作字符串,一直发送直到遇到\0为止
|
||||
bool SerialPort::OnWrite(const Buffer& bs)
|
||||
{
|
||||
if(!Opened || !bs.Length()) return true;
|
||||
/*#if defined(STM32F0) || defined(GD32F150)
|
||||
Set485(true);
|
||||
// 中断发送过于频繁,影响了接收中断,采用循环阻塞发送。后面考虑独立发送任务
|
||||
for(int i=0; i<bs.Length(); i++)
|
||||
{
|
||||
SendData(bs[i], 3000);
|
||||
}
|
||||
Set485(false);
|
||||
#else*/
|
||||
if (!Opened || !bs.Length()) return true;
|
||||
/*#if defined(STM32F0) || defined(GD32F150)
|
||||
Set485(true);
|
||||
// 中断发送过于频繁,影响了接收中断,采用循环阻塞发送。后面考虑独立发送任务
|
||||
for(int i=0; i<bs.Length(); i++)
|
||||
{
|
||||
SendData(bs[i], 3000);
|
||||
}
|
||||
Set485(false);
|
||||
#else*/
|
||||
// 如果队列已满,则强制刷出
|
||||
//if(Tx.Length() + bs.Length() > Tx.Capacity()) Flush(Sys.Clock / 40000);
|
||||
|
||||
// 用到时才初始化缓冲区
|
||||
if (Tx.Capacity() == 0)
|
||||
{
|
||||
int size = 64;
|
||||
while (size < bs.Length() && size < 1024) size <<= 1;
|
||||
Tx.SetCapacity(size);
|
||||
}
|
||||
Tx.Write(bs);
|
||||
|
||||
// 打开串口发送
|
||||
Set485(true);
|
||||
//USART_ITConfig((USART_TypeDef*)State, USART_IT_TXE, ENABLE);
|
||||
OnWrite2();
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -137,7 +157,7 @@ bool SerialPort::Flush(int times)
|
|||
// 打开串口发送
|
||||
Set485(true);
|
||||
|
||||
while(!Tx.Empty() && times > 0) times = SendData(Tx.Dequeue(), times);
|
||||
while (!Tx.Empty() && times > 0) times = SendData(Tx.Dequeue(), times);
|
||||
|
||||
Set485(false);
|
||||
|
||||
|
@ -150,7 +170,7 @@ uint SerialPort::OnRead(Buffer& bs)
|
|||
int count = 0;
|
||||
int len = Rx.Length();
|
||||
// 如果没有数据,立刻返回,不要等待浪费时间
|
||||
if(!len)
|
||||
if (!len)
|
||||
{
|
||||
bs.SetLength(0);
|
||||
|
||||
|
@ -158,7 +178,7 @@ uint SerialPort::OnRead(Buffer& bs)
|
|||
}
|
||||
|
||||
// 如果有数据变化,等一会
|
||||
while(len != count && len < bs.Length())
|
||||
while (len != count && len < bs.Length())
|
||||
{
|
||||
count = len;
|
||||
// 按照115200波特率计算,传输7200字节每秒,每个毫秒7个字节,大概150微秒差不多可以接收一个新字节
|
||||
|
@ -167,7 +187,7 @@ uint SerialPort::OnRead(Buffer& bs)
|
|||
len = Rx.Length();
|
||||
}
|
||||
// 如果数据大小不足,等下次吧
|
||||
if(len < MinSize)
|
||||
if (len < MinSize)
|
||||
{
|
||||
bs.SetLength(0);
|
||||
|
||||
|
@ -179,68 +199,68 @@ uint SerialPort::OnRead(Buffer& bs)
|
|||
bs.SetLength(count);
|
||||
|
||||
// 如果还有数据,打开任务
|
||||
if(!Rx.Empty()) Sys.SetTask(_taskidRx, true, 0);
|
||||
if (!Rx.Empty()) Sys.SetTask(_taskidRx, true, 0);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void SerialPort::ReceiveTask()
|
||||
{
|
||||
auto sp = this;
|
||||
auto sp = this;
|
||||
|
||||
//!!! 只要注释这一行,四位触摸开关就不会有串口溢出错误
|
||||
if(sp->Rx.Length() == 0) return;
|
||||
if (sp->Rx.Length() == 0) return;
|
||||
|
||||
// 从栈分配,节省内存
|
||||
byte buf[0x200];
|
||||
Buffer bs(buf, ArrayLength(buf));
|
||||
int mx = sp->MaxSize;
|
||||
if(mx > 0 && mx > bs.Length()) bs.SetLength(mx);
|
||||
int mx = sp->MaxSize;
|
||||
if (mx > 0 && mx > bs.Length()) bs.SetLength(mx);
|
||||
|
||||
uint len = sp->Read(bs);
|
||||
if(len)
|
||||
if (len)
|
||||
{
|
||||
len = sp->OnReceive(bs, nullptr);
|
||||
// 如果有数据,则反馈回去
|
||||
if(len) sp->Write(bs);
|
||||
if (len) sp->Write(bs);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialPort::SetBaudRate(int baudRate)
|
||||
{
|
||||
Set((COM)Index, baudRate);
|
||||
Set((COM)Index, baudRate);
|
||||
}
|
||||
|
||||
void SerialPort::ChangePower(int level)
|
||||
{
|
||||
// 串口进入低功耗时,直接关闭
|
||||
if(level) Close();
|
||||
if (level) Close();
|
||||
}
|
||||
|
||||
void SerialPort::Register(TransportHandler handler, void* param)
|
||||
{
|
||||
ITransport::Register(handler, param);
|
||||
|
||||
if(handler)
|
||||
if (handler)
|
||||
{
|
||||
// 建立一个未启用的任务,用于定时触发接收数据,收到数据时开启
|
||||
if(!_taskidRx)
|
||||
if (!_taskidRx)
|
||||
{
|
||||
//_taskidRx = Sys.AddTask([](void* p){ ((SerialPort*)p)->ReceiveTask(); }, this, -1, -1, "串口接收");
|
||||
_taskidRx = Sys.AddTask(&SerialPort::ReceiveTask, this, -1, -1, "串口接收");
|
||||
auto tsk = Task::Get(_taskidRx);
|
||||
// 串口任务深度设为2,允许重入,解决接收任务内部调用发送然后又等待接收匹配的问题
|
||||
//tsk->MaxDeepth = 2;
|
||||
_task = tsk;
|
||||
_task = tsk;
|
||||
}
|
||||
/*#if defined(STM32F0) || defined(GD32F150)
|
||||
// 打开中断
|
||||
byte irq = uart_irqs[Index];
|
||||
Interrupt.SetPriority(irq, 0);
|
||||
Interrupt.Activate(irq, OnHandler, this);
|
||||
#endif*/
|
||||
/*#if defined(STM32F0) || defined(GD32F150)
|
||||
// 打开中断
|
||||
byte irq = uart_irqs[Index];
|
||||
Interrupt.SetPriority(irq, 0);
|
||||
Interrupt.Activate(irq, OnHandler, this);
|
||||
#endif*/
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
Sys.RemoveTask(_taskidRx);
|
||||
}
|
||||
|
@ -248,45 +268,45 @@ void SerialPort::Register(TransportHandler handler, void* param)
|
|||
|
||||
extern "C"
|
||||
{
|
||||
static SerialPort* _printf_sp;
|
||||
static SerialPort* _printf_sp;
|
||||
static bool isInFPutc;
|
||||
}
|
||||
|
||||
SerialPort* SerialPort::GetMessagePort()
|
||||
{
|
||||
auto sp = _printf_sp;
|
||||
auto sp = _printf_sp;
|
||||
// 支持中途改变调试口
|
||||
if(sp && Sys.MessagePort != sp->Index)
|
||||
if (sp && Sys.MessagePort != sp->Index)
|
||||
{
|
||||
delete sp;
|
||||
_printf_sp = nullptr;
|
||||
_printf_sp = nullptr;
|
||||
}
|
||||
|
||||
if(!sp)
|
||||
if (!sp)
|
||||
{
|
||||
auto idx = (COM)Sys.MessagePort;
|
||||
if(idx == COM_NONE) return nullptr;
|
||||
auto idx = (COM)Sys.MessagePort;
|
||||
if (idx == COM_NONE) return nullptr;
|
||||
|
||||
if(isInFPutc) return nullptr;
|
||||
isInFPutc = true;
|
||||
if (isInFPutc) return nullptr;
|
||||
isInFPutc = true;
|
||||
|
||||
// 打开日志输出口,需要较大发送缓冲区
|
||||
sp = _printf_sp = new SerialPort(idx);
|
||||
sp->Tx.SetCapacity(512);
|
||||
sp->Tx.SetCapacity(256);
|
||||
sp->Open();
|
||||
|
||||
isInFPutc = false;
|
||||
isInFPutc = false;
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
void SerialPort::Set485(bool flag)
|
||||
{
|
||||
if(RS485)
|
||||
if (RS485)
|
||||
{
|
||||
if(!flag) Sys.Sleep(1);
|
||||
*RS485 = flag;
|
||||
if(flag) Sys.Sleep(1);
|
||||
if (!flag) Sys.Sleep(1);
|
||||
*RS485 = flag;
|
||||
if (flag) Sys.Sleep(1);
|
||||
/*if(flag)
|
||||
debug_printf("485 高\r\n");
|
||||
else
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
#include "Power.h"
|
||||
#include "Net\ITransport.h"
|
||||
|
||||
#define SERIAL_BAUDRATE 1024000
|
||||
|
||||
// 串口类
|
||||
class SerialPort : public ITransport, public Power
|
||||
{
|
||||
|
@ -37,19 +35,19 @@ public:
|
|||
Queue Rx;
|
||||
|
||||
SerialPort();
|
||||
SerialPort(COM index, int baudRate = SERIAL_BAUDRATE);
|
||||
SerialPort(COM index, int baudRate = 0);
|
||||
|
||||
// 析构时自动关闭
|
||||
virtual ~SerialPort();
|
||||
|
||||
void Set(COM index, int baudRate = SERIAL_BAUDRATE);
|
||||
void Set(COM index, int baudRate = 0);
|
||||
void Set(byte dataBits, byte parity, byte stopBits);
|
||||
|
||||
int SendData(byte data, int times = 3000);
|
||||
|
||||
bool Flush(int times = 3000);
|
||||
|
||||
void SetBaudRate(int baudRate = SERIAL_BAUDRATE);
|
||||
void SetBaudRate(int baudRate = 0);
|
||||
|
||||
virtual void Register(TransportHandler handler, void* param = nullptr);
|
||||
|
||||
|
|
|
@ -38,17 +38,10 @@ public:
|
|||
bool Write(const Buffer& bs, const void* opt);
|
||||
// 接收数据
|
||||
uint Read(Buffer& bs);
|
||||
//Buffer Read();
|
||||
|
||||
// 注册回调函数
|
||||
virtual void Register(TransportHandler handler, void* param = nullptr);
|
||||
|
||||
#if DEBUG
|
||||
//virtual const String ToString() const { return String("ITransport"); }
|
||||
#else
|
||||
//virtual const String ToString() const { return String(""); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual bool OnOpen() { return true; }
|
||||
virtual void OnClose() { }
|
||||
|
|
Loading…
Reference in New Issue