300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 移植Freemodbus到STM32(基于CubeMX HAL库)-避坑篇

移植Freemodbus到STM32(基于CubeMX HAL库)-避坑篇

时间:2020-01-10 02:48:16

相关推荐

移植Freemodbus到STM32(基于CubeMX HAL库)-避坑篇

具体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) 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;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。