下面分享一个rs485多线管理的库,
一共分为一下几个部分
1,结构体定义
2,注册
3,发送
4,接收
5,回调
typedef struct
{
uint8_t sendbuff[20];
uint32_t len;
}T_stuRS485SendBuff;
typedef struct
{
revFunc m_rs485RevFunc;
uint8_t m_rs485Address;
uint8_t m_lenIndex;
uint8_t m_lenCount;
uint8_t m_readStatus;
uint8_t m_readCount;
}stuRs485Manage;
其次是注册部分,
注册函数如下
void regRs485Dev(revFunc revDataFunc,uint8_t address,uint8_t index)
{
for(int i = 0 ; i < RS485_COUNT_LEN ; i ++)
{
if(sg_rs485Manage[i].m_readStatus == NONE_RS485)
{
sg_rs485Manage[i].m_rs485RevFunc = revDataFunc;
sg_rs485Manage[i].m_rs485Address = address;
sg_rs485Manage[i].m_lenCount = index;
sg_rs485Manage[i].m_readStatus = INIT_RS485;
break;
}
}
}
注册函数就是初始化一个结构体成员变量,赋值485的地址还有回调函数,等信息。
发送部分:
void loopRs485Sendbuff()
{
static uint32_t timeCount = 0;
if(HAL_GetTick() - timeCount < 100 && sg_rs485SendFlg != 0)
{
return;
}
timeCount = HAL_GetTick();
osEvent evt = osMailGet(mailRs485Manager, 1);
if(evt.status == osEventMail)
{
T_stuRS485SendBuff *rptr;
rptr = evt.value.p;
_rs485SendBuff(rptr->sendbuff,rptr->len);
osMailFree(mailRs485Manager, rptr);
sg_rs485SendFlg = 1;
}
}
void rs485SendBuffFifo(uint8_t *buff,uint32_t len)
{
mRs485Ptr = osMailAlloc(mailRs485Manager, 2); // Allocate memory
if(mRs485Ptr != NULL)
{
memcpy(mRs485Ptr->sendbuff,buff,len);
mRs485Ptr->len = len;
osMailPut(mailRs485Manager, mRs485Ptr);
}
}
void _rs485SendBuff(uint8_t *buff,uint32_t len)
{
RS485_SEND_MODE();
if(sg_flagSw == 0)
{
return;
}
HAL_UART_Transmit(&RS485_USART,buff,len,0Xff);
//osDelay(5);
RS485_REV_MODE();
}
采用的是一个缓冲发送,确保不会导致包错乱。
接受部分
void revRs485Data(uint8_t *buff,int32_t len)
{
static uint8_t address = 0;
if(len > 0)
address = buff[0];
for(int j = 0; j < len ; j ++)
{
for(int i = 0; i < RS485_COUNT_LEN ; i ++)
{
if(sg_rs485Manage[i].m_readStatus == BEGIN_RS485)
{
sg_rs485Manage[i].m_readCount += 1;
if(sg_rs485Manage[i].m_rs485RevFunc != 0)
sg_rs485Manage[i].m_rs485RevFunc(buff + j,1);
else
DEBUG_WARNING("not init rs485 dev,%x\r\n",sg_rs485Manage[i].m_rs485Address);
if(sg_rs485Manage[i].m_readCount >= sg_rs485Manage[i].m_lenCount)
{
sg_rs485Manage[i].m_readStatus = END_RS485;
//DEBUG_NORMAL("RS485 ansy finish %x\r\n",sg_rs485Manage[i].m_rs485Address);
sg_rs485SendFlg = 0;
}
break;
}
else if(address == sg_rs485Manage[i].m_rs485Address && sg_rs485Manage[i].m_readStatus != NONE_RS485)
{
sg_rs485Manage[i].m_readCount = 0;
sg_rs485Manage[i].m_readStatus = BEGIN_RS485;
sg_rs485Manage[i].m_readCount += 1;
if(sg_rs485Manage[i].m_rs485RevFunc != 0)
sg_rs485Manage[i].m_rs485RevFunc(buff + j,1);
else
DEBUG_WARNING("not init rs485 dev\r\n");
//DEBUG_WARNING("read len = %d\r\n,read count = %d\r\n",sg_rs485Manage[i].m_lenCount,sg_rs485Manage[i].m_readCount);
if(sg_rs485Manage[i].m_readCount >= sg_rs485Manage[i].m_lenCount)
{
sg_rs485Manage[i].m_readStatus = END_RS485;
}
break;
}
}
}
}
首先遍历接收到的数据,
然后进行地址匹配,匹配成功,就开始接受数据,
解析部分为回调函数,我是实现了一个状态机,一个字节一个字节的解析数据。