原创 STM32F103、FreeModbus从站设计(6)-让串口和Modbus初始化的参数同步起来

2021-3-18 21:34 2584 27 4 分类: MCU/ 嵌入式
FreeModbus从站设计(6)-让串口和Modbus初始化的参数同步起来
关键词:Modbus FreeModbus STM32F103C8T6 CubeMX 移植
 
1.基本原理
在这一篇文章中,孔丙火(微信公众号:孔丙火)主要介绍协议栈初始化,以及与串口相关的代码修改。串口的初始化函数是CubeMx自动生成的,其波特率等参数最好与freemodbus协议栈初始化参数保持一致,这样方便程序的维护和功能扩展,例如,当需要修改通信的波特率的时候,只需要修改一处就可以了,不用先修改串口的初始化参数,再修改协议栈的参数,这是一个实战例程与纯教程的区别。
本文的总体思路:创建一些全局变量,用于存储通信参数,串口、定时器、Freemodbus协议栈的初始化,都采用这些变量,需要更改的时候,只需改变这些变量的值即可。另外,这些通信参数后续计划存储在flash里面,定时器的参数会随波特率的不同而改变,这些在后续的文章中会阐述。
2.代码修改
2.1关于assert的说明
在Freemodbus的协议栈中,很多地方使用了assert,因此,在Cube生成工程的时候,孔丙火(微信公众号:孔丙火)认为,最好使能enable assert选项,如果没有使能,编译的时候可能出错,这个时候可以勾掉MicroLIB,因为MicroLIB不支持assert。
2.2宏的修改
(1)MB_RTU_ENABLED、MB_ASCII_ENABLED、MB_TCP_ENABLED
这里我们实现的是RTU,只需将MB_RTU_ENABLED定义为1即可。孔丙火(微信公众号:孔丙火)顺便说一句,在基于串口的Modbus中,RTU是必选项,ASCII是可选项,也就是说RTU是必须要实现的。
(2)ENTER_CRITICAL_SECTION( )和EXIT_CRITICAL_SECTION( )
这两个函数是进入和退出关键进程,这里定义为__disable_irq()和__enable_irq(),后边两个函数是ARM内核函数,作用是禁止中断和使能中断。
#define ENTER_CRITICAL_SECTION( ) __disable_irq()  
#define EXIT_CRITICAL_SECTION( )  __enable_irq()
2.3协议栈初始化
在main.c文件中的while(1)之前,调用eMBInit(  )完成协议栈的初始化,然后调用eMBEnable(  )使能协议栈。eMBInit(  )的定义如下:eMBErrorCode
eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ),共5个参数,eMode模式:RTU或ASCII,ucSlaveAddress从站地址,ucPort单片机的串口号,ulBaudRate波特率,eParity校验方式,我们这里串口参数是在Cube生产的函数里初始化的,而且串口接收或发送的数据HAL库函数已经处理好了,因此,孔丙火(微信公众号:孔丙火)认为,有用的参数只有eMode,ucSlaveAddress,ulBaudRate,其余两个设错了,其实也没影响(仅限于本文的实现方法)。
在modbus_app.c中定义如下全局变量:
uint8_t ucUsrSlaveAddress;//从站地址
uint32_t ulUsrBaudRate;//波特率
eMBParity eUsrParity;//校验方式
uint8_t ucUsrStopBits;//停止位
新建modbus_app.h,在其中进行extern定义,一般在其他c文件中使用。
最终,在main.c中做如下调用:
eMBInit( MB_RTU, ucUsrSlaveAddress, 1, ulUsrBaudRate, eUsrParity );
2.4串口参数初始化
在MX_USART2_UART_Init()中修改,此函数是Cube自动生成的,在usart.c中。
最终函数如下:
huart2.Instance = USART2;
  huart2.Init.BaudRate = ulUsrBaudRate;
  if(eUsrParity == MB_PAR_NONE)huart2.Init.WordLength = UART_WORDLENGTH_8B;
  else huart2.Init.WordLength = UART_WORDLENGTH_9B;
  if(ucUsrStopBits == 1)huart2.Init.StopBits = UART_STOPBITS_1;
  else if(ucUsrStopBits == 2)huart2.Init.StopBits = UART_STOPBITS_2;
  if(eUsrParity == MB_PAR_NONE)huart2.Init.Parity = UART_PARITY_NONE;
  else if(eUsrParity == MB_PAR_EVEN)huart2.Init.Parity = UART_PARITY_EVEN;
  else if(eUsrParity == MB_PAR_ODD)huart2.Init.Parity = UART_PARITY_ODD;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
波特率使用了全局变量,单片机的数据位个数和停止位根据全局变量确定。
3.总结
这种方法让让串口和Modbus初始化的参数同步起来了,也方便通信参数的在线修改,更接近实战。————————————————
文章在微信公众号同步推出:孔丙火,关注欣赏更多系列文章。-----单片机、ARM、现场总线、PLC、嵌入式软硬件的设计经验分享,秉承“点点滴滴皆智慧”的理念,以实际项目为单元阐述知识点,一起分享,共同交流。 




PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

yzw92 2021-3-20 08:14

感谢楼主分享!
相关推荐阅读
孔丙火 2021-07-09 21:10
Modbus的通信参数存在flash中,如果改乱了,该怎么办--FreeModbus从站设计(12)
FreeModbus从站设计(12)-Modbus的通信参数存在flash中,如果改乱了,该怎么办关键词:FreeModbus 复位默认参数 HAL库 flash STM32在上一篇文章中,介绍了如何...
孔丙火 2021-07-09 15:21
如何把Modbus的通信参数存在单片机的flash中-FreeModbus从站设计(11)
FreeModbus从站设计(11)-把Modbus的通信参数存在单片机的flash中关键词:FreeModbus CubeMX HAL库 flash 通信参数作为从站,Modbus-RTU通信的参数...
孔丙火 2021-06-19 22:31
单片机程序中,Modbus功能码的回调函数如何编写--FreeModbus从站设计(10)
FreeModbus从站设计(10)-Modbus功能码的回调函数如何编写 关键词:FreeModbus CubeMX HAL库 串口 功能码   此系列的前面几篇文章,主要是阐述...
孔丙火 2021-05-19 15:51
为什么有的PLC需要上电停止功能,能防止PLC变砖
关键词:PLC可编程控制器 上电停止 串口通信 梯形图 摘要:PLC(可编程控制器)在工业控制中使用非常广泛,型号很多,有一部分PLC有上电停止的功能,它们为什么需要这个功能呢?孔丙火(微信公众号:...
孔丙火 2021-05-06 22:57
不要小瞧TVS管哦,否则要吃大亏
摘要:TVS管是常用的保护器件,但在平时正常环境的测试中,并不能明显地感觉到它的存在,好像有没有TVS管,都一个样。TVS管表示很委屈。TVS管本身就是为了在意外情况(比如瞬间高压串扰)保护电路的...
孔丙火 2021-04-20 13:07
当RS485隔离遇见Freemodbus,你碰到问题了吗?
摘要: 基于RS485物理接口的Modbus总线在工业控制中广泛应用。Freemodbus是一个免费的实用的协议栈,孔丙火(微信公众号:孔丙火)用它实现了一个从站。串口收发信号和RS485芯片的收发使...
EE直播间
更多
我要评论
1
27
关闭 站长推荐上一条 /3 下一条