将ardunio相关的serial等函数使用自己的代码实现,serial函数其实就是硬件层接口的函数封装,这也是移植到其他平台必须要根据自身平台做相应的改变。
(1). 在ModbusMasterTransaction函数中涉及到_serial->read()、_serial->write()、_serial->flush()、_serial->available()、millis()、bitWrite()、bitRead()、word()几种函数,从名字中我们就可以知道什么意思,故我们需要在我们的系统中重新实现这几个函数。
(2). 我们底层串口的设计思路如下,数据发送采用数据的发送直接采用循环发送,而STM32cube库已经将这个功能封装好API接口,我们再封装一层即可,如下所示
/**
* @brief 将数据包发送出去
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint8_t Modbus_Master_Write(uint8_t *buf,uint8_t length)
{
if(HAL_UART_Transmit(&huart2 ,(uint8_t *)buf,length,0xff))
{
return HAL_ERROR;
}
else
{
return HAL_OK;
}
}
这句函数就相当于_serial->write()的实现。
(3). 串口数据的接收:我们采用中断接收的方式,并且在中断处理函数中将接收到的字节采用循环队压人缓冲区,这样子就能实现ardunio的功能代码。
跟底层相关的移植代码可到我的工程 Modbus_Master--trans_recieve_buff_control.c .h文件查看。
_serial->read()的变体为:
/**
* @brief 读出缓冲区的数据
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint8_t Modbus_Master_Read(void)
{
uint8_t cur =0xff;
if( !rbIsEmpty(&m_Modbus_Master_RX_RingBuff))
{
cur = rbPop(&m_Modbus_Master_RX_RingBuff);
}
return cur;
}
_serial->flush()的变体为:
/**
* @brief 清除环形队列
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint8_t Modbus_Master_Rece_Flush(void)
{
rbClear(&m_Modbus_Master_RX_RingBuff);
}
_serial->available()的变体为:
/**
* @brief 判断ringbuffer里面是否有尚未处理的字节
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint8_t Modbus_Master_Rece_Available(void)
{
/*如果数据包buffer里面溢出了,则清零,重新计数*/
if(m_Modbus_Master_RX_RingBuff.flagOverflow==1)
{
rbClear(&m_Modbus_Master_RX_RingBuff);
}
return !rbIsEmpty(&m_Modbus_Master_RX_RingBuff);
}
millis()的变体为:
/**
* @brief 1ms周期的定时器
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint32_t Modbus_Master_Millis(void)
{
return HAL_GetTick();
}
其余几个函数的变体如下:
/*模拟ardunio函数*************************************************/
static inline uint8_t lowByte(uint16_t ww)
{
return (uint8_t) ((ww) & 0x00FF);
}
static inline uint8_t highByte(uint16_t ww)
{
return (uint8_t) ((ww) >> 8);
}
static inline uint16_t word(uint8_t H_Byte,uint8_t L_Byte)
{
uint16_t word;
word = (uint16_t)(H_Byte<<8);
word = word + L_Byte;
return word;
}
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
(4).剩下的就是串口的一些硬件初始化,如波特率等,这些配置由于我是用CUBEMX配置直接生成的代码,这里不做过多阐述。