具体Freemodbus移植到STM32步骤参考:
STMC2CubeMX | STM32 HAL库移植FreeModbus详细步骤
基于STM32HAL库移植FreeModbus
FreeModbus+STM32 +HAL库 无 *** 作系统移植 (已在正点原子阿波罗F429开发板上移植成功)
移植过程各路网站上都比较多,具体可参考以上链接内容。
把思路和步骤记录一下:
①下载复制Freemodbus库;
② 使用CubeMX生成工程,需要注意配置串口、timer,NVIC优先级串口高于timer,需要用到中断,但不需要生成IRQHandle(移植中有手动添加)
③添加Freemodbus中相关.c.h文件到工程,设置中配置c++ include目录
④移植的核心在于port.c,portserial.c,porttimer.c,portevent.c 四个文件的修改与配置;其中配置serial与time是关键,需修改portserial.c与porttimer.c, *** 作时,只需要修改为需要的串口和timer即可,其他内容不需要动。
⑤如果用到485收发芯片,需要添加收发控制端代码(具体可以参考下边问题1种内容)
⑥根据需要配置port.c文件,如果初步测试,不用修改
⑦编译下载,然后就可以测试了
(1)Freemodbus移植到TTL的USART1可行,但改为485的USART2不行整个移植过程其实不是太复杂(站在前人基础上),但还是容易出现一些问题,在此仅个人移植存在的问题,踩过的坑在这里记录一下
具体和端口没关系,主要问题是端口使用到485芯片,需要有收发控制端的配置,并在适当时候打开即可;
这个问题具体 *** 作是修改portserial.c文件中 vMBPortSerialEnable函数内容,添加打开接收或者打开发送控制端,具体需要根据芯片及接法有关。
/* ------------- Start implementation -------------------------*/
void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{
if(xRxEnable)
{
__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);// 使能接收非空中断
HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_RESET); //MAX485 *** 作 低电平为接收模式
}
else
{
__HAL_UART_DISABLE_IT(&huart2, UART_IT_RXNE);// 禁能接收非空中断
}
if(xTxEnable)
{
HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET); //MAX485 *** 作 高电平为发送模式
__HAL_UART_ENABLE_IT(&huart2, UART_IT_TXE); // 使能发送为空中断
}
else
{
__HAL_UART_DISABLE_IT(&huart2, UART_IT_TXE); // 禁能发送为空中断
}
}
(2)485-Modbus 通讯 Timeout,数据发送不全或者结尾总是0xFF
这个问题的在不使用485芯片上一般不出现,在使用到485芯片的时候就比较明显,根源在于收发过程切换。
仔细调试发现,MCU已经将数据传输出去,TTL口数据已经正常,但到485芯片后就出错,主要是MCU从发送到接收的转换太快,数据还没发送完全就将485的收发端口从发送转换为接收,造成最后一个字节数据没有从485芯片传输出去,造成出错。
修改也比较简单,在切换之前进行适当延时,确保数据发送完成后在进行切换收发使能端口状态,即可解决。
通过多方测试,感觉加到
cBOOL xMBRTUTransmitFSM( void )
比较合适:增加语句【while(i
关于RS485_swtict_delay 设置多大合适呢
经测试的波特率115200时,1000左右即可;波特率9600时,13000左右;这个延时时间与芯片延时有关系,具体以测试为准。
BOOL xMBRTUTransmitFSM( void )
{
BOOL xNeedPoll = FALSE;
uint16_t i = 0;
assert( eRcvState == STATE_RX_IDLE );
switch ( eSndState )
{
/* We should not get a transmitter event if the transmitter is in
* idle state. */
case STATE_TX_IDLE:
/* enable receiver/disable transmitter. */
vMBPortSerialEnable( TRUE, FALSE );
break;
case STATE_TX_XMIT:
/* check if we are finished. */
if( usSndBufferCount != 0 )
{
xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur );
pucSndBufferCur++; /* next byte in sendbuffer. */
usSndBufferCount--;
}
else
{
xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
/* Disable transmitter. This prevents another transmit buffer
* empty interrupt. */
*
// ********看这里***** ↓ 边是重点
while(i<RS485_swtict_delay) i++; //补充延时
// ********看这里***** ↑ 边是重点
vMBPortSerialEnable( TRUE, FALSE );
eSndState = STATE_TX_IDLE;
}
break;
}
return xNeedPoll;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)