Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
freemodbus
Modbus
freemodbus主机在freertos的适配,参考rtthread例程
发布于 2024-11-29 11:53:18 浏览:124
订阅该版
port.c ```c /* ----------------------- System includes --------------------------------*/ #include "FreeRTOS.h" #include "semphr.h" #include
/* ----------------------- Modbus includes ----------------------------------*/ #include "port.h" /* ----------------------- Variables ----------------------------------------*/ static SemaphoreHandle_t lock = NULL; static int is_inited = 0; /* ----------------------- Start implementation -----------------------------*/ void EnterCriticalSection(void) { if (!is_inited) { // 创建一个计数信号量,初始值为1,表示最多允许一个任务进入临界区 lock = xSemaphoreCreateCounting(1, 1); // 创建一个计数信号量 CMB_ASSERT(lock != NULL); is_inited = 1; } xSemaphoreTake(lock, portMAX_DELAY); // 阻塞直到信号量被释放 } void ExitCriticalSection(void) { // 释放信号量,其他任务可以获取信号量并进入临界区 CMB_ASSERT(lock != NULL); xSemaphoreGive(lock); } ``` port.h ```c #ifndef _PORT_H #define _PORT_H #include "mbconfig.h" #include "FreeRTOS.h" #include
#define INLINE #define PR_BEGIN_EXTERN_C extern "C" { #define PR_END_EXTERN_C } #define ENTER_CRITICAL_SECTION() EnterCriticalSection() #define EXIT_CRITICAL_SECTION() ExitCriticalSection() typedef uint8_t FMB_BOOL; typedef unsigned char UCHAR; typedef char CHAR; typedef uint16_t USHORT; typedef int16_t SHORT; typedef uint32_t ULONG; typedef int32_t LONG; #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif void EnterCriticalSection(void); void ExitCriticalSection(void); #endif ``` portevent_m.c ```c /* ----------------------- System includes --------------------------------*/ #include "FreeRTOS.h" #include "semphr.h" #include "event_groups.h" #include
/* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mb_m.h" #include "mbport.h" #include "port.h" #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 /* ----------------------- Defines ------------------------------------------*/ /* ----------------------- Variables ----------------------------------------*/ static SemaphoreHandle_t xMasterRunRes; static EventGroupHandle_t xMasterOsEvent; /* ----------------------- Start implementation -----------------------------*/ FMB_BOOL xMBMasterPortEventInit(void) { /* Initialize event group */ xMasterOsEvent = xEventGroupCreate(); CMB_ASSERT(xMasterOsEvent != NULL); return TRUE; } FMB_BOOL xMBMasterPortEventPost(eMBMasterEventType eEvent) { /* Post event to event group */ xEventGroupSetBits(xMasterOsEvent, eEvent); return TRUE; } FMB_BOOL xMBMasterPortEventGet(eMBMasterEventType *eEvent) { EventBits_t uxBits; /* Wait for event forever */ uxBits = xEventGroupWaitBits(xMasterOsEvent, EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE | EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS, pdTRUE, pdFALSE, portMAX_DELAY); /* Check which event occurred */ if (uxBits & EV_MASTER_READY) { *eEvent = EV_MASTER_READY; } else if (uxBits & EV_MASTER_FRAME_RECEIVED) { *eEvent = EV_MASTER_FRAME_RECEIVED; } else if (uxBits & EV_MASTER_EXECUTE) { *eEvent = EV_MASTER_EXECUTE; } else if (uxBits & EV_MASTER_FRAME_SENT) { *eEvent = EV_MASTER_FRAME_SENT; } else if (uxBits & EV_MASTER_ERROR_PROCESS) { *eEvent = EV_MASTER_ERROR_PROCESS; } else { *eEvent = EV_MASTER_FRAME_RECEIVED; } return TRUE; } /** * This function is initialize the OS resource for modbus master. * Note: The resource is defined by OS. If you do not use OS, this function can be empty. * */ void vMBMasterOsResInit(void) { /* Initialize the semaphore for master resource */ xMasterRunRes = xSemaphoreCreateBinary(); CMB_ASSERT(xMasterRunRes != NULL); xSemaphoreGive(xMasterRunRes); // Release the semaphore initially } /** * This function is take Modbus Master running resource. * Note: The resource is defined by Operating System. If you do not use OS, this function can just return TRUE. * * @param lTimeOut the waiting time. * * @return resource taken result */ FMB_BOOL xMBMasterRunResTake(LONG lTimeOut) { /* If waiting time is -1, it will wait forever */ return xSemaphoreTake(xMasterRunRes, pdMS_TO_TICKS(lTimeOut)) == pdTRUE ? TRUE : FALSE; } /** * This function is release Modbus Master running resource. * Note: The resource is defined by Operating System. If you do not use OS, this function can be empty. * */ void vMBMasterRunResRelease(void) { /* Release the semaphore */ xSemaphoreGive(xMasterRunRes); } /** * This is Modbus master respond timeout error process callback function. * @note There functions will block Modbus master poll while executing OS waiting. * So, for real-time of the system, do not execute too much waiting process. * * @param ucDestAddress destination slave address * @param pucPDUData PDU buffer data * @param ucPDULength PDU buffer length * */ void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) { /** * @note This code is use OS's event mechanism for modbus master protocol stack. * If you don't use OS, you can change it. */ xEventGroupSetBits(xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT); /* You can add your custom error handling code here */ } /** * This is Modbus master receive data error process callback function. * @note These functions will block Modbus master poll while executing OS waiting. * So, for real-time of the system, do not execute too much waiting process. * * @param ucDestAddress destination slave address * @param pucPDUData PDU buffer data * @param ucPDULength PDU buffer length * */ void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) { /** * @note This code is use OS's event mechanism for modbus master protocol stack. * If you don't use OS, you can change it. */ xEventGroupSetBits(xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA); /* You can add your custom error handling code here */ } /** * This is Modbus master execute function error process callback function. * @note These functions will block Modbus master poll while executing OS waiting. * So, for real-time of the system, do not execute too much waiting process. * * @param ucDestAddress destination slave address * @param pucPDUData PDU buffer data * @param ucPDULength PDU buffer length * */ void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) { /* Use event mechanism for Modbus master protocol stack */ xEventGroupSetBits(xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION); /* You can add your custom error handling code here */ } /** * This is Modbus master request process success callback function. * @note These functions will block Modbus master poll while executing OS waiting. * So, for real-time of the system, do not execute too much waiting process. * */ void vMBMasterCBRequestScuuess(void) { /* Use event mechanism for Modbus master protocol stack */ xEventGroupSetBits(xMasterOsEvent, EV_MASTER_PROCESS_SUCESS); /* You can add your custom code here */ } /** * This function is wait for Modbus master request finish and return result. * Waiting result includes request process success, request respond timeout, * receive data error and execute function error. You can use the above callback function. * @note If you are using OS, you can use OS's event mechanism. Otherwise, you have to run * much user custom delay for waiting. * * @return request error code */ eMBMasterReqErrCode eMBMasterWaitRequestFinish(void) { eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; EventBits_t uxBits; /* Wait for OS event */ uxBits = xEventGroupWaitBits(xMasterOsEvent, EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT | EV_MASTER_ERROR_RECEIVE_DATA | EV_MASTER_ERROR_EXECUTE_FUNCTION, pdTRUE, pdFALSE, portMAX_DELAY); /* Check which event occurred */ if (uxBits & EV_MASTER_PROCESS_SUCESS) { // Request processed successfully } else if (uxBits & EV_MASTER_ERROR_RESPOND_TIMEOUT) { eErrStatus = MB_MRE_TIMEDOUT; } else if (uxBits & EV_MASTER_ERROR_RECEIVE_DATA) { eErrStatus = MB_MRE_REV_DATA; } else if (uxBits & EV_MASTER_ERROR_EXECUTE_FUNCTION) { eErrStatus = MB_MRE_EXE_FUN; } return eErrStatus; } #endif ``` portserial_m.c ```c /* ----------------------- System includes --------------------------------*/ #include "FreeRTOS.h" #include
#include "task.h" #include "queue.h" #include "event_groups.h" #include "sdk_uart.h" #include "serialZ.h" #include "bll_debug.h" #include "fml_timebase.h" /* ----------------------- Platform includes --------------------------------*/ #include "port.h" /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mbport.h" uint8 serial_soft_rec_enable = 0; #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 /* ----------------------- Static variables ---------------------------------*/ /* software simulation serial transmit IRQ handler task handle */ static TaskHandle_t xSerialSoftTransIrqTaskHandle = NULL; static TaskHandle_t xSerialSoftRecIrqTaskHandle = NULL; /* serial event group */ static EventGroupHandle_t xSerialEventGroup = NULL; /* ----------------------- Defines ------------------------------------------*/ /* serial transmit event */ #define EVENT_SERIAL_TRANS_START (1<<0) /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR(void); static void prvvUARTRxISR(void); ///接收 static void serial_soft_trans_irq_task(void *pvParameters); ///发送中断模拟 static void serial_soft_rec_irq_task(void *pvParameters); /* ----------------------- Start implementation -----------------------------*/ FMB_BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity) { (void)ucPORT; // 忽略端口号,假设只有一个串口 (void)ucDataBits; // 忽略数据位,假设固定为8位 (void)eParity; // 忽略校验位,假设固定为无校验 /* initialize zSerial */ ///sdk_uart3_init(115200); serialZ0_init(ulBaudRate); /* set receive callback function */ serialZ0_setRxCallBack(prvvUARTRxISR); ///接收提醒 /** * set 485 mode receive and transmit control IO * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user */ #if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) /// rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); #endif /* initialize FreeRTOS event group */ xSerialEventGroup = xEventGroupCreate(); CMB_ASSERT(xSerialEventGroup!=0); /* create software simulation serial transmit IRQ handler task */ xTaskCreate(serial_soft_trans_irq_task, "SerialTransIrq", configMINIMAL_STACK_SIZE + 512, NULL, (configMAX_PRIORITIES - 2), &xSerialSoftTransIrqTaskHandle); CMB_ASSERT(xSerialSoftTransIrqTaskHandle!=0); ///启动接收中断线程 if (xTaskCreate(serial_soft_rec_irq_task, "SerialRecIrq", configMINIMAL_STACK_SIZE + 512, NULL, (configMAX_PRIORITIES - 2), &xSerialSoftRecIrqTaskHandle) !=pdPASS) { CMB_ASSERT(0); } return TRUE; } void vMBMasterPortSerialEnable(FMB_BOOL xRxEnable, FMB_BOOL xTxEnable) { if (xRxEnable) { /* enable RX interrupt */ serial_soft_rec_enable = 1; serialZ0_setRxCallBack(prvvUARTRxISR); ///接收提醒 /* switch 485 to receive mode */ #if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW); #endif } else { /* switch 485 to transmit mode */ #if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH); #endif /* disable RX interrupt */ serial_soft_rec_enable = 0; serialZ0_setRxCallBack(NULL); ///接收提醒 } if (xTxEnable) { /* start serial transmit */ xEventGroupSetBits(xSerialEventGroup, EVENT_SERIAL_TRANS_START); } else { /* stop serial transmit */ xEventGroupClearBits(xSerialEventGroup, EVENT_SERIAL_TRANS_START); } } void vMBMasterPortClose(void) { ///serial->parent.close(&(serial->parent)); } FMB_BOOL xMBMasterPortSerialPutByte(CHAR ucByte) { sdk_uart3_putc((uint8)ucByte); ///XPRINTF_NONELINE("%c",ucByte);///串口显示 return TRUE; } FMB_BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) { serialZ0_getc((uint8 *)pucByte); ///XPRINTF_NONELINE("%c",*pucByte);///串口显示 return TRUE; } /* * Create an interrupt handler for the transmit buffer empty interrupt * (or an equivalent) for your target processor. This function should then * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that * a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character. */ void prvvUARTTxReadyISR(void) { pxMBMasterFrameCBTransmitterEmpty(); } /* * Create an interrupt handler for the receive interrupt for your target * processor. This function should then call pxMBFrameCBByteReceived( ). The * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the * character. */ void prvvUARTRxISR(void) { pxMBMasterFrameCBByteReceived(); } /** * Software simulation serial transmit IRQ handler task. * * @param pvParameters parameter */ static void serial_soft_trans_irq_task(void *pvParameters) { (void)pvParameters; while (7) { /* wait for serial transmit start event */ EventBits_t xEventBits = xEventGroupWaitBits(xSerialEventGroup, EVENT_SERIAL_TRANS_START, pdFALSE, pdFALSE, portMAX_DELAY); if ((xEventBits & EVENT_SERIAL_TRANS_START) != 0) { /// 等待串口发送完毕 while (!sdk_uart3_getTCFlag()) /// 底层未就绪 { // 使用FreeRTOS延时,等待一段时间后再次检查 vTaskDelay(pdMS_TO_TICKS(1)); // 延时1毫秒 } /* execute modbus callback */ prvvUARTTxReadyISR(); } } } // 模拟接收线程 static void serial_soft_rec_irq_task(void *pvParameters) { for (;;) { if (serial_soft_rec_enable) { int result = serialZ0_running(); if (result == 0) // 如果返回值为0,则执行延时 { vTaskDelay(pdMS_TO_TICKS(1)); } // 如果返回值非0,则不执行延时,直接进入下一次循环 } else { vTaskDelay(pdMS_TO_TICKS(1)); // 如果 serial_soft_rec_enable 为假,则延时 } } } #endif ``` [port.7z](https://club.rt-thread.org/file_download/48d586ad51588f65)
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
TOM2022
这家伙很懒,什么也没写!
文章
1
回答
3
被采纳
0
关注TA
发私信
相关文章
1
ModbusRTU协议栈漏发送最后一个字节
2
3.0 增加freemodbus,编译不过
3
RT_THREAD上面的串口MODBUSRTU为啥没功能码?
4
关于 freemodbus 里存在的一点问题分享
5
请教如何使用组件里的FreeMODBUS
6
求一个FreeModbus的从机测试程序
7
FreeModbus的从机调试说明(含测试程序)
8
rtt_freemodbus
9
freemodbus怎么配置到uart
10
FreeModeBus从机调试问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
289
次被采纳
张世争
808
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
catcatbing
3
篇文章
4
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部