diff --git a/.gitignore b/.gitignore index 4cd487f..791d435 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ TrainCamp_zhangcheng_PLSR/.vscode TrainCamp_zhangcheng_PLSR/iar/Debug TrainCamp_zhangcheng_PLSR/iar/settings TrainCamp_zhangcheng_PLSR/iar/PLSR.dep -TrainCamp_zhangcheng_PLSR/iar/PLSR.ewt \ No newline at end of file +TrainCamp_zhangcheng_PLSR/iar/PLSR.ewt +.TMP \ No newline at end of file diff --git a/TrainCamp_zhangcheng_PLSR/app/inc/plsr.h b/TrainCamp_zhangcheng_PLSR/app/inc/plsr.h new file mode 100644 index 0000000..b0d5a5a --- /dev/null +++ b/TrainCamp_zhangcheng_PLSR/app/inc/plsr.h @@ -0,0 +1,182 @@ +/** + * @file plsr.h + * @author zhangcheng + * @brief PLSR指令功能接口文件 + * @version v0.1 + * @date 2025-08-06 + * + * @copyright Copyright (c) 2025 + */ + + +#include "../../modbus/inc/modbus.h" + + +/** + * @brief 最大支持脉冲段 + * @details + * @note + * @attention + */ +#define PLSR_PULSE_MAX_SEGMENT_NUM 10 + + +/** + * @brief 系统参数块 + * @details + * @note + * @attention + */ +typedef enum { + SYSTEM_PARAM_BLOCK_0 = 0, ///< 系统参数块0,默认参数块,不可修改 + SYSTEM_PARAM_BLOCK_1, ///< 系统参数块1 + SYSTEM_PARAM_BLOCK_2, ///< 系统参数块2 + SYSTEM_PARAM_BLOCK_3, ///< 系统参数块3 + SYSTEM_PARAM_BLOCK_4 ///< 系统参数块4 +} PLSR_SYSTEM_PARAM_BLOCK; + + + +/** + * @brief 输出端口 + * @details + * @note + * @attention + */ +typedef enum { + OUTPUT_PORT_Y0 = 0, ///< 输出端子Y0 + OUTPUT_PORT_Y1, ///< 输出端子Y1 + OUTPUT_PORT_Y2, ///< 输出端子Y2 + OUTPUT_PORT_Y3 ///< 输出端子Y3 +} PLSR_OUTPUT_PORT; + + +/** + * @brief 输出方向端口 + * @details + * @note + * @attention + */ +typedef enum { + OUTPUT_DIR_PORT_Y12 = 0, ///< 输出方向端子Y12 + OUTPUT_DIR_PORT_Y13, ///< 输出方向端子Y13 + OUTPUT_DIR_PORT_Y14, ///< 输出方向端子Y14 + OUTPUT_DIR_PORT_Y15 ///< 输出方向端子Y15 +} PLSR_OUTPUT_DIR_PORT; + + +/** + * @brief 方向端子方向逻辑 + * @details + * @note + * @attention + */ +typedef enum { + OUTPUT_DIR_CORRECT = 0, ///< 正逻辑 + OUTPUT_DIR_NEGATIVE, ///< 负逻辑 +} PLSR_OUTPUT_DIR_PORT_LOGIC; + + +/** + * @brief 输入信号端口 + * @details + * @note + * @attention + */ +typedef enum { + INPUT_EXT_PORT_X4 = 0, ///< 输入端子X4 + INPUT_EXT_PORT_X5, ///< 输入端子X5 +} PLSR_INPUT_EXT_PORT; + + +/** + * @brief 加减速模式模式 + * @details + * @note + * @attention + */ +typedef enum { + STRAIGHT_LINE_MODE = 0, ///< 直线加减速模式 + S_CURVE_MODE, ///< S曲线加减速模式 + SINE_CURVE_MODE ///< 正弦曲线加减速模式 +} PLSR_ACC_DEC_SPEED_MODE; + + +/** + * @brief 输出模式 + * @details + * @note + * @attention + */ +typedef enum { + RELATIVE_MODE = 0, ///< 相对模式 + ABSOLUTE_MODE ///< 绝对模式 +} PLSR_OUTPUT_MODE; + + +/** + * @brief 参数错误类型 + * @details + * @note + * @attention + */ +typedef enum { + PLSR_ERROR_NONE = 0, ///< 无错误 + PLSR_FREQ_EXCE_MAX_VALUE ///< 超过最大输出频率 +} PLSR_ERROR_TYPE; + + +/** + * @brief PLSR脉冲段 + * @details + * @note + * @attention + */ +typedef struct +{ + int32_t pulseFreq; + int32_t pulseNumber; + int16_t waitType; + int16_t jumpNumber; +} PLSR_SEGMENT; + + +/** + * @brief PLSR指令结构类型 + * @details + * @note + * @attention + */ +typedef struct +{ + PLSR_OUTPUT_PORT outputPort; ///< 输出端子 + PLSR_OUTPUT_DIR_PORT dirPort; ///< 输出方向端子 + PLSR_INPUT_EXT_PORT extPort; ///< 输入端子 + PLSR_OUTPUT_DIR_PORT_LOGIC dirLogic; ///< 输出方向端子逻辑 + PLSR_ACC_DEC_SPEED_MODE accDecSpeedMode; ///< 加减速模式 + PLSR_OUTPUT_MODE outMode; ///< 输出模式 + uint16_t dirDelayTime; ///< 方向延时时间 + uint16_t segmentAllNum; ///< 总段数 + uint16_t startRunSegment; ///< 起始执行段编号 + uint16_t previouSegment; ///< 上一段编号 + uint16_t currentSegment; ///< 当前执行段编号 + uint32_t defaultSpeed; ///< 默认速度 + uint16_t defaultAccSpeedTime; ///< 默认加速时间 + uint16_t defaultDecSpeedTime; ///< 默认减速时间 + int32_t monitorPulseNum; ///< 监控脉冲数量 + uint16_t sendEnableState; ///< 脉冲发送使能 + PLSR_SEGMENT segment[PLSR_PULSE_MAX_SEGMENT_NUM]; ///< 各段数参数 +} PLSR; + + +/** + * @brief PLSR功能初始化 + * @details + * + * @param[in] 无 + * + * @return RESUIL 初始化结果 + * @retval MODBUS_TURE 成功 + * @retval MODBUS_FALSE 失败 + */ +RESUIL PLSRInit(void); diff --git a/TrainCamp_zhangcheng_PLSR/app/src/main.c b/TrainCamp_zhangcheng_PLSR/app/src/main.c index c48b8e7..084f181 100644 --- a/TrainCamp_zhangcheng_PLSR/app/src/main.c +++ b/TrainCamp_zhangcheng_PLSR/app/src/main.c @@ -4,37 +4,7 @@ #include "../modbus/inc/modbus_operate_module.h" #include "../modbus/inc/modbus_ack_module.h" #include "../modbus/inc/modbus_link_check_module.h" - - -// PVD初始化函数,设置PVD阈值和中断模式 -void PVD_Init(void) -{ - // 使能PWR时钟 - RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); - - // 设置PVD阈值为2.9V,可以根据你的电源电压选择其他值 - PWR_PVDLevelConfig(PWR_PVDLevel_7); - - // 使能PVD - PWR_PVDCmd(ENABLE); - - // 使能PVD外部中断线 - EXTI_ClearITPendingBit(EXTI_Line16); // 清除中断标志位 - EXTI_InitTypeDef EXTI_InitStructure; // 定义外部中断结构体 - EXTI_InitStructure.EXTI_Line = EXTI_Line16; // PVD连接到外部中断线16 - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 设置为中断模式 - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 设置为上升沿触发,即电压低于阈值时触发 - EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能外部中断线 - EXTI_Init(&EXTI_InitStructure); // 初始化外部中断 - - // 设置PVD中断优先级和使能 - NVIC_InitTypeDef NVIC_InitStructure; // 定义中断控制器结构体 - NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn; // PVD中断通道 - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6; // 抢占优先级为0 - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级为0 - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道 - NVIC_Init(&NVIC_InitStructure); // 初始化中断控制器 -} +#include "../inc/plsr.h" int main(void) @@ -60,6 +30,7 @@ int main(void) OperateProcModuleInit(); AckProcModuleInit(); linkCheckModuleInit(); + PLSRInit(); OSStart(); } diff --git a/TrainCamp_zhangcheng_PLSR/app/src/plsr.c b/TrainCamp_zhangcheng_PLSR/app/src/plsr.c new file mode 100644 index 0000000..74fd0bb --- /dev/null +++ b/TrainCamp_zhangcheng_PLSR/app/src/plsr.c @@ -0,0 +1,621 @@ +/** + * @file plsr.c + * @author zhangcheng + * @brief PLSR指令功能源文件 + * @version v0.1 + * @date 2025-08-06 + * + * @copyright Copyright (c) 2025 + */ + +#include "../../system/inc/system.h" +#include "../../bsp/inc/time.h" +#include "../inc/plsr.h" +#include "../../bsp/inc/gpio.h" +#include "../../system/inc/usart.h" + +/* 速度波形发送任务使能 */ +#define SPEED_SEND_TASK 0 + +#if (SPEED_SEND_TASK) +#define SPEED_SEND_MODULE_PRIO 20 +#define SPEED_SEND_MODULE_STACK_SIZE 200 +static OS_STK SpeedSendModuleStack[SPEED_SEND_MODULE_STACK_SIZE]; +static void SpeedSendModuleTask(void * pArg); +void UsartSend(uint32_t data) +{ + extern usart_obj_t *usart1; + uint8_t buff[4]; + buff[0] = (uint8_t)((data) >> 24); + buff[1] = (uint8_t)((data) >> 16); + buff[2] = (uint8_t)((data) >> 8); + buff[3] = (uint8_t)((data)); + for (uint8_t i = 0; i < 4; i++) + { + USART_SendData(USART1, buff[i]);//发送一个字节 + while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) != SET); + } +} +#define USART_SEND_SPEED(x) UsartSend(x) +#endif + + +/* 求x绝对值 */ +#define ABS(x) do { \ + if ((x) < 0) \ + ((x) = 0 - (x)); \ + } while(0) + +typedef struct { + int32_t inc; + int32_t dec; + int32_t currentSpeed; + uint8_t currentState; ///< 0:无操作 1:匀速 2:加速 3:减速 + uint8_t currentPart; + int32_t firstPartNum; + int32_t secondPartNum; + int32_t thirdPartNum; +} SEGMENT_PART; + + +#define PLSR_MODULE_PRIO 5 +#define PLSR_MODULE_STACK_SIZE 1024 +static OS_STK PlsrModuleStack[PLSR_MODULE_STACK_SIZE]; +static void PlsrModuleTask(void * pArg); + +static void TimCallBack(void *pArg); +static void Tim2CntCallBack(void *pArg); +static void ReadRegisterParam(PLSR *plsr); +static void configPulsePort(PLSR *plsr); +static void ComputePartNum(PLSR *plsr, SEGMENT_PART *segmentPart); +static void StartPulseOutput(void); +static void StopPulseOutput(void); + +/** + * @brief PLSR功能初始化 + * @details + * + * @param[in] 无 + * + * @return RESUIL 初始化结果 + * @retval MODBUS_TURE 成功 + * @retval MODBUS_FALSE 失败 + */ +RESUIL PLSRInit(void) +{ + INT8U err; + + OS_CPU_SR cpu_sr; + OS_ENTER_CRITICAL(); + + err = OSTaskCreate( + PlsrModuleTask, + NULL, + &PlsrModuleStack[PLSR_MODULE_STACK_SIZE - 1], + PLSR_MODULE_PRIO); + + if(err != OS_ERR_NONE) + { + MODBUS_LOG("PlsrcModule init fail\r\n"); + OS_EXIT_CRITICAL(); + return MODBUS_FALSE; + } + +#if (SPEED_SEND_TASK) + err = OSTaskCreate( + SpeedSendModuleTask, + NULL, + &SpeedSendModuleStack[SPEED_SEND_MODULE_STACK_SIZE - 1], + SPEED_SEND_MODULE_PRIO); + + if(err != OS_ERR_NONE) + { + MODBUS_LOG("SpeedSendModule init fail\r\n"); + OS_EXIT_CRITICAL(); + return MODBUS_FALSE; + } +#endif + + OS_EXIT_CRITICAL(); + + return MODBUS_TURE; +} + + +/** + * @brief PLSR处理任务 + * @details + * + * @param[in] *pArg 任务参数 + * + * @return RESUIL 初始化结果 + * @retval MODBUS_TURE 成功 + * @retval MODBUS_FALSE 失败 + */ +TIM_OBJ tim2; +int32_t tim2OverCnt = 0; +int32_t CumulativePulseCount = 0; +TIM_OBJ tim10; +int32_t accSpeedSlope = 0; +int32_t decSpeedSlope = 0; +int32_t accTime = 0; +int32_t decTime = 0; +int32_t accPulse = 0; +int32_t decPulse = 0; +int32_t uniformTime = 0; +int32_t uniformPulse = 0; +uint8_t currentSegment = 0; +uint8_t currentSegmentID = 0; +uint32_t currentSpeed = 0; +uint8_t RunFlag = 0; + +int32_t pulseFreq = 168 - 1; +uint32_t pulseReload = 20; + +SEGMENT_PART currentSeg = { + .currentState = 2, + .currentPart = 1 + }; +PLSR plsr = { + .segmentAllNum = 4, + .defaultSpeed = 1000, + .defaultAccSpeedTime = 5, + .defaultDecSpeedTime = 10, + .segment[0].pulseFreq = 2000, + .segment[0].pulseNumber = 1000, + .segment[0].jumpNumber = 0, + .segment[1].pulseFreq = 1000, + .segment[1].pulseNumber = 2000, + .segment[1].jumpNumber = 0, + .segment[2].pulseFreq = 6000, + .segment[2].pulseNumber = 3000, + .segment[2].jumpNumber = 0, + .segment[3].pulseFreq = 6000, + .segment[3].pulseNumber = 100000, + .segment[3].jumpNumber = 0, + .startRunSegment = 1, + .outMode = ABSOLUTE_MODE, + .accDecSpeedMode = STRAIGHT_LINE_MODE, + .sendEnableState = 1 +}; + +static void PlsrModuleTask(void *pArg) +{ + //ReadRegisterParam(&plsr); + + GetTimObj("tim2", &tim2); + GetTimObj("tim10", &tim10); + + tim2.init(&tim2, 0, 50000 - 1); + tim2.open(&tim2); + tim2.registerIrq(&tim2, Tim2CntCallBack, NULL); + tim2.openIrq(&tim2); + + tim10.init(&tim10, 168 - 1, 65535); + tim10.registerIrq(&tim10, TimCallBack, ¤tSeg); + tim10.pwmInit(&tim10); + tim10.pwmSetPulse(&tim10, TIM10->ARR); + + currentSegmentID = plsr.startRunSegment; + currentSegment = currentSegmentID - 1; + + int tmpTIMARR = 0; + while (1) + { +// ReadRegisterParam(&plsr); + tmpTIMARR = TIM2->ARR + 1; + CumulativePulseCount = tim2OverCnt * tmpTIMARR + TIM2->CNT; + plsr.monitorPulseNum = CumulativePulseCount; + + if (plsr.segment[currentSegment].pulseFreq <= 1000) + pulseFreq = 2625 - 1; + else if ((plsr.segment[currentSegment].pulseFreq > 1000) + && (plsr.segment[currentSegment].pulseFreq <= 100000)) + pulseFreq = 4 - 1; + else + continue; + + /* 配置输入输出相关端子 */ + if ((plsr.sendEnableState != 1) || (RunFlag == 1)) + { + continue; + } + + if (plsr.outMode == ABSOLUTE_MODE) + { + if (plsr.monitorPulseNum + == plsr.segment[currentSegment].pulseNumber) + { + plsr.sendEnableState = 0; + StopPulseOutput(); + continue; + } + } + + if ((plsr.accDecSpeedMode == STRAIGHT_LINE_MODE) && (RunFlag == 0)) + { + RunFlag = 1; + + configPulsePort(&plsr); + ComputePartNum(&plsr, ¤tSeg); + StartPulseOutput(); + } + } +} + +static void SpeedSendModuleTask(void * pArg) +{ + while(1) + { +#if (SPEED_SEND_TASK) + if (plsr.sendEnableState == 1) + USART_SEND_SPEED(currentSpeed); +#endif + } + +} +//1HZ +//psc 1680 一次10us +//per 50000 +//5KHZ +//psc 1680 +//per 10 +//100KHZ +//psc 168 一次0.5us +//per 10 +//定时器3 外部输入时钟源ETR引脚PB4,定时器11输出 +//定时器4 外部输入时钟源ETR引脚PB6,定时器14输出 +//定时器9 内部输入时钟源ITx主从模式定时器10 +//定时器12 内部输入时钟源ITx主从模式定时器13 + +static void Tim2CntCallBack(void *pArg) +{ + tim2OverCnt++; +} + +static void TimCallBack(void *pArg) +{ + uint16_t reloadValue = 0; + static int32_t pulseCount = 0; + static int32_t allcount = 0; + + if (currentSeg.currentPart == 1) + { + switch (currentSeg.currentState) + { + case 2: ///< 加速 + { + if ((currentSpeed + currentSeg.inc) >= plsr.segment[currentSegment].pulseFreq) + { + currentSpeed = plsr.segment[currentSegment].pulseFreq; + + currentSeg.currentPart = 2; + } + else + currentSpeed += currentSeg.inc; + + if (currentSpeed <= 1000) + tim10.setPsc(&tim10, 2625 - 1); + else + tim10.setPsc(&tim10, 3 - 1); + + reloadValue = 168000000 / (TIM10->PSC + 1) / (currentSpeed); + tim10.setPer(&tim10, reloadValue - 1); + tim10.pwmSetPulse(&tim10, TIM10->ARR / 2 + 1); + allcount++; + pulseCount++; + + if (pulseCount > currentSeg.firstPartNum - 1) + { + pulseCount = 0; +// currentSeg.currentPart = 2; + } + + break; + } + case 3: ///< 减速 + { + if ((currentSpeed - currentSeg.dec) < plsr.segment[currentSegment].pulseFreq) + { + currentSpeed = plsr.segment[currentSegment].pulseFreq; + + currentSeg.currentPart = 2; + } + else + currentSpeed -= currentSeg.dec; + + if (currentSpeed <= 1000) + tim10.setPsc(&tim10, 2625 - 1); + else + tim10.setPsc(&tim10, 3 - 1); + + reloadValue = 168000000 / (TIM10->PSC + 1) / (currentSpeed); + tim10.setPer(&tim10, reloadValue - 1); + tim10.pwmSetPulse(&tim10, TIM10->ARR / 2 + 1); + allcount++; + pulseCount++; + + if (pulseCount > currentSeg.firstPartNum - 1) + { + pulseCount = 0; +// currentSeg.currentPart = 2; + } + + break; + } + default: + { + break; + } + } + } + else if (currentSeg.currentPart == 2) + { + if (pulseCount > currentSeg.secondPartNum - 1) + { + if ((currentSegmentID == (plsr.segmentAllNum)) + && (plsr.segment[currentSegment].jumpNumber == 0)) + { + currentSeg.currentPart = 3; + pulseCount = 0; + currentSeg.dec = currentSpeed / currentSeg.thirdPartNum; + return; + } + + currentSeg.currentPart = 1; + pulseCount = 0; + RunFlag = 0; + + if (plsr.segment[currentSegment].jumpNumber == 0) + currentSegment++; + else + currentSegment = plsr.segment[currentSegment].jumpNumber - 1; + + currentSegmentID = currentSegment + 1; + } + allcount++; + pulseCount++; + } + else if (currentSeg.currentPart == 3) + { + if (((currentSpeed - currentSeg.dec) <= 0) + || (pulseCount > currentSeg.thirdPartNum - 2)) + { + currentSpeed = 0; + pulseCount = 0; + currentSeg.currentPart = 1; + + StopPulseOutput(); + + allcount++; + plsr.sendEnableState = 0; + return; + } + currentSpeed -= currentSeg.dec; + + if (currentSpeed <= 1000) + tim10.setPsc(&tim10, 2625 - 1); + else + tim10.setPsc(&tim10, 3 - 1); + + reloadValue = 168000000 / (TIM10->PSC + 1) / (currentSpeed); + tim10.setPer(&tim10, reloadValue - 1); + tim10.pwmSetPulse(&tim10, TIM10->ARR / 2 + 1); + allcount++; + pulseCount++; + } +} + + +static void ReadRegisterParam(PLSR *plsr) +{ + int16_t *pDataRegister = (int16_t *)(DATA_REGISTER_ADRR + 0x1000); + + plsr->outputPort = (PLSR_OUTPUT_PORT)pDataRegister[0]; + plsr->dirPort = (PLSR_OUTPUT_DIR_PORT)pDataRegister[1]; + plsr->extPort = (PLSR_INPUT_EXT_PORT)pDataRegister[2]; + plsr->dirDelayTime = pDataRegister[3]; + plsr->dirLogic = (PLSR_OUTPUT_DIR_PORT_LOGIC)pDataRegister[4]; + plsr->accDecSpeedMode = (PLSR_ACC_DEC_SPEED_MODE)pDataRegister[5]; + plsr->outMode = (PLSR_OUTPUT_MODE)pDataRegister[6]; + plsr->segmentAllNum = pDataRegister[7]; + plsr->startRunSegment = pDataRegister[8]; + plsr->defaultSpeed = *((uint32_t *)pDataRegister[9]); + plsr->defaultAccSpeedTime = pDataRegister[11]; + plsr->defaultDecSpeedTime = pDataRegister[12]; + plsr->monitorPulseNum = *((int32_t *)(pDataRegister + 0x1000)); + plsr->sendEnableState = *(pDataRegister + 0x2000); + + pDataRegister += 0x100; + for (uint8_t i = 0; i < PLSR_PULSE_MAX_SEGMENT_NUM; i++) + { + plsr->segment[i].pulseFreq = *((uint32_t *)pDataRegister[i]); + plsr->segment[i].pulseNumber = *((int32_t *)pDataRegister[i + 2]); + plsr->segment[i].waitType = pDataRegister[i + 4]; + plsr->segment[i].jumpNumber = pDataRegister[i + 5]; + + pDataRegister += 0x10; + } +} + + +static void configPulsePort(PLSR *plsr) +{ + uint8_t pulseDir = 1; + gpio_obj_t *outDirPort = NULL; + + outDirPort = get_gpio_obj("gpio_h"); + + if ((outDirPort == NULL) || (plsr == NULL)) + return; + + if (plsr->segment[currentSegment].pulseNumber >= 0) + pulseDir = 1; + else + pulseDir = 0; + + switch (plsr->dirPort) + { + case OUTPUT_DIR_PORT_Y12: + { + outDirPort->gpio_init(outDirPort, gpio_pin_9, "OUT_PP", "UP"); + break; + } + case OUTPUT_DIR_PORT_Y13: + { + outDirPort->gpio_init(outDirPort, gpio_pin_8, "OUT_PP", "UP"); + break; + } + case OUTPUT_DIR_PORT_Y14: + { + outDirPort->gpio_init(outDirPort, gpio_pin_7, "OUT_PP", "UP"); + break; + } + case OUTPUT_DIR_PORT_Y15: + { + outDirPort->gpio_init(outDirPort, gpio_pin_6, "OUT_PP", "UP"); + break; + } + default: + { + break; + } + } + outDirPort->gpio_set_output(outDirPort, outDirPort->gpio_pin, + plsr->dirLogic ^ pulseDir); + if (currentSegment == plsr->startRunSegment) + return; + + if (((plsr->segment[currentSegment].pulseNumber >= 0) + && (plsr->segment[plsr->previouSegment].pulseNumber >= 0))) + return; + + if ((plsr->segment[currentSegment].pulseNumber < 0) + && (plsr->segment[plsr->previouSegment].pulseNumber < 0)) + return; + +// tim10.pwmSetPulse(&tim10, 65535); + OSTimeDly(plsr->dirDelayTime); +} + + +static void ComputePartNum(PLSR *plsr, SEGMENT_PART *segmentPart) +{ + int32_t targetFreq = plsr->segment[currentSegment].pulseFreq; + int32_t targetPulseCount = plsr->segment[currentSegment].pulseNumber; + + if (plsr->outMode == ABSOLUTE_MODE) + targetPulseCount -= plsr->monitorPulseNum; + + ABS(targetPulseCount); + + accSpeedSlope = plsr->defaultSpeed / plsr->defaultAccSpeedTime; + decSpeedSlope = plsr->defaultSpeed / plsr->defaultDecSpeedTime; + + /* 计算每段脉冲三个部分脉冲数量 */ + /* 最后一段 */ + if ((currentSegmentID == (plsr->segmentAllNum)) + && (plsr->segment[currentSegment].jumpNumber == 0)) + { + decTime = targetFreq / decSpeedSlope; + segmentPart->thirdPartNum = targetFreq / 2 * decTime / 1000; + + if (segmentPart->thirdPartNum > targetPulseCount) + { + segmentPart->thirdPartNum = targetPulseCount; + } + } + else + { + segmentPart->thirdPartNum = 0; + } + + if (currentSpeed < targetFreq) + { + accTime = (targetFreq - currentSpeed) / accSpeedSlope; + segmentPart->firstPartNum = (targetFreq + currentSpeed) / 2 * accTime / 1000; + } + else if (currentSpeed > targetFreq) + { + decTime = (currentSpeed - targetFreq) / decSpeedSlope; + segmentPart->firstPartNum = (targetFreq + currentSpeed) / 2 * decTime / 1000; + } + else + { + segmentPart->firstPartNum = 0; + } + + if ((segmentPart->firstPartNum + segmentPart->thirdPartNum) + >= (targetPulseCount )) + segmentPart->firstPartNum = targetPulseCount - segmentPart->thirdPartNum; + + segmentPart->secondPartNum = targetPulseCount + - segmentPart->firstPartNum + - segmentPart->thirdPartNum; + + if (currentSpeed == plsr->segment[currentSegment].pulseFreq) + segmentPart->currentState = 1; + else if ((currentSpeed < plsr->segment[currentSegment].pulseFreq)) + segmentPart->currentState = 2; + else + segmentPart->currentState = 3; + + /* 计算每个脉冲的频率增量 */ + switch (segmentPart->currentState) + { + /* 匀速处理 */ + case 1 : + { + segmentPart->currentPart = 2; + break; + } + /* 加速处理 */ + case 2 : + { + segmentPart->inc = ((targetFreq - currentSpeed) / accSpeedSlope) + * ((targetFreq + currentSpeed) / 2) / 1000; + segmentPart->inc = (targetFreq - currentSpeed) / segmentPart->inc; + + break; + } + /* 减速处理 */ + case 3 : + { + segmentPart->dec = ((currentSpeed - targetFreq) / decSpeedSlope) + * ((currentSpeed + targetFreq) / 2) / 1000; + segmentPart->dec = (currentSpeed - targetFreq) / segmentPart->dec; + + break; + } + } +} + + +static void StartPulseOutput(void) +{ + if (currentSpeed <= 1000) + { + tim10.setPsc(&tim10, 2625 - 1); + } + else + { + tim10.setPsc(&tim10, 3 - 1); + } + if (currentSpeed != 0) + tim10.setPer(&tim10, 168000000 / (TIM10->PSC + 1) / currentSpeed); + else + tim10.setPer(&tim10, 1000); + tim10.registerIrq(&tim10, TimCallBack, ¤tSeg.currentPart); + tim10.open(&tim10); + tim10.openIrq(&tim10); +} + + +static void StopPulseOutput(void) +{ + currentSpeed = 0; + tim10.setPer(&tim10, 10); + tim10.pwmSetPulse(&tim10, 65535); + tim10.close(&tim10); + tim10.openIrq(&tim10); +} diff --git a/TrainCamp_zhangcheng_PLSR/bsp/inc/time.h b/TrainCamp_zhangcheng_PLSR/bsp/inc/time.h new file mode 100644 index 0000000..109197e --- /dev/null +++ b/TrainCamp_zhangcheng_PLSR/bsp/inc/time.h @@ -0,0 +1,60 @@ +/** + * @file time.h + * @author zhangcheng + * @brief 定时器及PWM输出接口文件 + * @version v0.1 + * @date 2025-08-06 + * + * @copyright Copyright (c) 2025 + */ + + +#ifndef _time_H +#define _time_H + +#include "stm32f4xx.h" + + +/** + * @brief 定时器数据结构 + * @details + * @note + * @attention + */ +typedef struct TIM +{ + TIM_TypeDef *TIM; + int8_t (*init)(struct TIM *tim, uint16_t psc, uint32_t per); + void (*deInit)(struct TIM *tim); + void (*setPsc)(struct TIM *tim, uint16_t psc); + void (*setPer)(struct TIM *tim, uint32_t per); + void (*open)(struct TIM *tim); + void (*close)(struct TIM *tim); + void (*openIrq)(struct TIM *tim); + void (*closeIrq)(struct TIM *tim); + void (*registerIrq)(struct TIM *tim, void (*registerFunc)(void *pArg), + void *pArg); + void (*pwmInit)(struct TIM *tim); + void (*pwmDeInit)(struct TIM *tim); + void (*pwmSetPulse)(struct TIM *tim, uint32_t pulse); +} TIM_OBJ; + + +/** + * @brief 获取定时器 + * @details + * + * @param[in] *timName 定时器名称 + * + * @param[out] *timObj 接收定时器参数地址 + * + * @return int8_t 返回结果 + * @retval 0 成功 + * @retval -1 失败 + * + * @note *timName "timx" x : 10、11、13、14 + */ +int8_t GetTimObj(char *timName, TIM_OBJ *timObj); + +#endif + diff --git a/TrainCamp_zhangcheng_PLSR/bsp/src/gpio.c b/TrainCamp_zhangcheng_PLSR/bsp/src/gpio.c index 2c8fbf3..a1c19d4 100644 --- a/TrainCamp_zhangcheng_PLSR/bsp/src/gpio.c +++ b/TrainCamp_zhangcheng_PLSR/bsp/src/gpio.c @@ -187,6 +187,30 @@ static gpio_obj_t g_stm32f103_gpio_g = { &g_stm32f103_gpio_g_priv }; + +/* GPIOH˽ */ +static gpio_priv_obj_t g_stm32f103_gpio_h_priv = { + GPIOH, + GPIO_Mode_IN, + (GPIOOType_TypeDef)0, + (GPIOPuPd_TypeDef)0, + RCC_AHB1Periph_GPIOH +}; +/* GPIOHṹ */ +static gpio_obj_t g_stm32f103_gpio_h = { + "gpio_h", + 0, + "gpio_mode", + gpio_init, + gpio_deinit, + gpio_set_output, + gpio_read_output, + gpio_read_input, + gpio_open_irq, + gpio_close_irq, + &g_stm32f103_gpio_h_priv +}; + /* GPIOб */ static gpio_obj_t *g_gpio_devs[] = { &g_stm32f103_gpio_a, @@ -195,7 +219,8 @@ static gpio_obj_t *g_gpio_devs[] = { &g_stm32f103_gpio_d, &g_stm32f103_gpio_e, &g_stm32f103_gpio_f, - &g_stm32f103_gpio_g + &g_stm32f103_gpio_g, + &g_stm32f103_gpio_h }; /* GPIOģʽ˽б */ diff --git a/TrainCamp_zhangcheng_PLSR/bsp/src/time.c b/TrainCamp_zhangcheng_PLSR/bsp/src/time.c new file mode 100644 index 0000000..db1ad86 --- /dev/null +++ b/TrainCamp_zhangcheng_PLSR/bsp/src/time.c @@ -0,0 +1,438 @@ +/** + * @file time.h + * @author zhangcheng + * @brief 定时器及PWM输出接口文件 + * @version v0.1 + * @date 2025-08-06 + * + * @copyright Copyright (c) 2025 + */ + + +#include "../../system/inc/system.h" +#include "../inc/time.h" + + +/* 中断注册回调函数类型 */ +typedef void (*Func)(void *pArg); + +/* 中断注册回调函数列表 */ +static Func CallBackFuncList[] = +{ + NULL, ///< TIM2 + NULL ///< TIM10 +}; + +/* 中断注册回调参数列表 */ +static void *ArgList[] = +{ + NULL, ///< TIM2 + NULL ///< TIM10 +}; + +/* 可用定时器列表 */ +static char *TimNameList[] = +{ + "tim2", ///< TIM2 + "tim10", ///< TIM10 + "tim11", ///< TIM11 + "tim13", ///< TIM13 + "tim14" ///< TIM14 +}; + +/* 可用定时器列表参数 */ +static TIM_TypeDef *TimType[] = +{ + TIM2, ///< TIM2 + TIM10, ///< TIM10 + TIM11, ///< TIM11 + TIM13, ///< TIM13 + TIM14 ///< TIM14 +}; + + +/** + * @brief 定时器初始化 + * @details + * + * @param[in] *tim 定时器结构体指针 + * @param[in] psc 定时器预分频系数 + * @param[in] per 定时器重装载值 + * + * @return int8_t 返回结果 + * @retval 0 成功 + * @retval -1 失败 +*/ +int8_t TimInit(TIM_OBJ *tim, uint16_t psc, uint32_t per) +{ + TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; + + if (tim->TIM == TIM2) + { + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + + TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_TIM2); + + TIM_SelectInputTrigger(tim->TIM, TIM_TS_ETRF); + TIM_ETRClockMode2Config(tim->TIM, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0); + } + + else if (tim->TIM == TIM10) + { + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10,ENABLE); + TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; + } + + else if (tim->TIM == TIM11) + { + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11,ENABLE); + TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; + } + + else if (tim->TIM == TIM13) + { + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13,ENABLE); + TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; + } + + else if (tim->TIM == TIM14) + { + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); + TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; + } + else + return -1; + + if (tim->TIM != TIM2) + TIM_InternalClockConfig(tim->TIM); + + TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; + TIM_TimeBaseInitStructure.TIM_Period=per; + TIM_TimeBaseInitStructure.TIM_Prescaler=psc; + TIM_TimeBaseInit(tim->TIM, &TIM_TimeBaseInitStructure); + +// TIM_GenerateEvent(tim->TIM, TIM_EventSource_Update); + TIM_ClearITPendingBit(tim->TIM, TIM_IT_Update); + + return 0; +} + + +/** + * @brief 定时器复位 + * @details + * + * @param[in] *tim 定时器结构体指针 + * + * @return 无 +*/ +void TimDeInit(TIM_OBJ *tim) +{ + if (tim->TIM == TIM2) + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,DISABLE); + else if (tim->TIM == TIM10) + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10,DISABLE); + else if (tim->TIM == TIM11) + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11,DISABLE); + else if (tim->TIM == TIM13) + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13,DISABLE); + else if (tim->TIM == TIM14) + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,DISABLE); + else + return; + + TIM_Cmd(tim->TIM, DISABLE); + TIM_DeInit(tim->TIM); +} + + +/** + * @brief 设置定时器预分频 + * @details + * + * @param[in] *tim 定时器结构体指针 + * @param[in] psc 定时器预分频系数 + * + * @return 无 +*/ +void TimSetPsc(TIM_OBJ *tim, uint16_t psc) +{ + TIM_ITConfig(tim->TIM, TIM_IT_Update, DISABLE); + TIM_PrescalerConfig(tim->TIM, psc, TIM_PSCReloadMode_Immediate); + TIM_ClearITPendingBit(tim->TIM, TIM_IT_Update); + TIM_ITConfig(tim->TIM, TIM_IT_Update, ENABLE); +} + + +/** + * @brief 设置定时器重载值 + * @details + * + * @param[in] *tim 定时器结构体指针 + * @param[in] per 定时器重装载值 + * + * @return 无 +*/ +void TimSetPer(TIM_OBJ *tim, uint32_t per) +{ + TIM_SetAutoreload(tim->TIM, per); +} + + +/** + * @brief 开启定时器 + * @details + * + * @param[in] *tim 定时器结构体指针 + * + * @return 无 +*/ +void TimOpen(TIM_OBJ *tim) +{ + TIM_Cmd(tim->TIM, ENABLE); +} + + +/** + * @brief 关闭定时器 + * @details + * + * @param[in] *tim 定时器结构体指针 + * + * @return 无 +*/ +void TimClose(TIM_OBJ *tim) +{ + TIM_Cmd(tim->TIM, DISABLE); +} + + +/** + * @brief 开启定时器更新中断 + * @details + * + * @param[in] *tim 定时器结构体指针 + * + * @return 无 +*/ +void TimOpenIrq(TIM_OBJ *tim) +{ + NVIC_InitTypeDef NVIC_InitStructure; + + TIM_ITConfig(tim->TIM, TIM_IT_Update, ENABLE); + TIM_ClearITPendingBit(tim->TIM, TIM_IT_Update); + + if (tim->TIM == TIM2) + NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; + else if(tim->TIM == TIM10) + NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_TIM10_IRQn; + else + return; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=7; + NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; + NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; + NVIC_Init(&NVIC_InitStructure); +} + + +/** + * @brief 关闭定时器更新中断 + * @details + * + * @param[in] *tim 定时器结构体指针 + * + * @return 无 +*/ +void TimCloseIrq(TIM_OBJ *tim) +{ + TIM_ITConfig(tim->TIM, TIM_IT_Update, DISABLE); + TIM_ClearITPendingBit(tim->TIM, TIM_IT_Update); +} + + +/** + * @brief 注册定时器中断回调函数 + * @details + * + * @param[in] *tim 定时器结构体指针 + * @param[in] registerFunc 回调函数地址 + * @note 回调函数格式 void (*registerFunc)(void *pArg) + * + * @return 无 +*/ +void TimRegisterIrq(TIM_OBJ *tim, void (*registerFunc)(void *pArg), void *pArg) +{ + if (tim->TIM == TIM2) + { + CallBackFuncList[0] = registerFunc; + ArgList[0] = pArg; + } + else if (tim->TIM == TIM10) + { + CallBackFuncList[1] = registerFunc; + ArgList[1] = pArg; + } + else + return; +} + + +/** + * @brief PWM初始化 + * @details + * + * @param[in] *tim 定时器结构体指针 + * @param[in] pulse 脉冲宽度 + * + * @return 无 +*/ +void PwmInit(TIM_OBJ *tim) +{ + TIM_OCInitTypeDef TIM_OCInitStructure; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_TIM10); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOF,&GPIO_InitStructure); + + TIM_OCStructInit(&TIM_OCInitStructure); + TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OCInitStructure.TIM_OutputState = ENABLE; + TIM_OCInitStructure.TIM_Pulse = 0; + TIM_OC1Init(tim->TIM, &TIM_OCInitStructure); +} + + + +/** + * @brief PWM复位 + * @details + * + * @param[in] *tim 定时器结构体指针 + * + * @return 无 +*/ +void PwmDeInit(TIM_OBJ *tim) +{ + TIM_OCInitTypeDef TIM_OCInitStructure; + TIM_OCInitStructure.TIM_OutputState = DISABLE; + TIM_OCInitStructure.TIM_Pulse = 0; + TIM_OC1Init(tim->TIM, &TIM_OCInitStructure); +} + + +/** + * @brief 设置PWM脉冲宽度 + * @details + * + * @param[in] *tim 定时器结构体指针 + * @param[in] pulse PWM脉冲宽度 + * + * @return 无 +*/ +void PwmSetPulse(TIM_OBJ *tim, uint32_t pulse) +{ + TIM_SetCompare1(tim->TIM, pulse); +} + + +/** + * @brief 定时器2更新中断服务函数 + * @details + * + * @param[in] 无 + * + * @return 无 +*/ +void TIM2_IRQHandler(void) +{ + if (TIM_GetITStatus(TIM2,TIM_IT_Update) == SET) + { + if (CallBackFuncList[0] != NULL) + CallBackFuncList[0](ArgList[0]); + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + } +} + + +/** + * @brief 定时器13更新中断服务函数 + * @details + * + * @param[in] 无 + * + * @return 无 +*/ +void TIM1_UP_TIM10_IRQHandler(void) +{ + if (TIM_GetITStatus(TIM10,TIM_IT_Update) == SET) + { + if (ArgList[1] != NULL) + CallBackFuncList[1](ArgList[1]); + TIM_ClearITPendingBit(TIM10, TIM_IT_Update); + } +} + + +/** + * @brief 获取定时器 + * @details + * + * @param[in] *timName 定时器名称 + * @note "timx" x : 10、11、13、14 + * @param[out] *timObj 接收定时器参数地址 + * + * @return int8_t 返回结果 + * @retval 0 成功 + * @retval -1 失败 + */ +int8_t GetTimObj(char *timName, TIM_OBJ *timObj) +{ + uint8_t getTimFlag = 0; + + if (!timObj) + return -1; + + for (uint8_t i = 0; i < sizeof(TimNameList) / sizeof(TimNameList[0]); i++) + { + if (strcmp(timName, TimNameList[i]) == 0) + { + timObj->TIM = TimType[i]; + getTimFlag = 1; + break; + } + } + + if (!getTimFlag) + return -1; + + timObj->init = &TimInit; + timObj->deInit = &TimDeInit; + timObj->setPsc = &TimSetPsc; + timObj->setPer = &TimSetPer; + timObj->open = &TimOpen; + timObj->close = &TimClose; + timObj->openIrq = &TimOpenIrq; + timObj->closeIrq = &TimCloseIrq; + timObj->registerIrq = &TimRegisterIrq; + timObj->pwmInit = &PwmInit; + timObj->pwmDeInit = &PwmDeInit; + timObj->pwmSetPulse = &PwmSetPulse; + + return 0; +} diff --git a/TrainCamp_zhangcheng_PLSR/iar/PLSR.ewp b/TrainCamp_zhangcheng_PLSR/iar/PLSR.ewp index 53a6d96..8e18fe1 100644 --- a/TrainCamp_zhangcheng_PLSR/iar/PLSR.ewp +++ b/TrainCamp_zhangcheng_PLSR/iar/PLSR.ewp @@ -2122,6 +2122,9 @@ $PROJ_DIR$\..\app\src\main.c + + $PROJ_DIR$\..\app\src\plsr.c + BSP @@ -2131,6 +2134,9 @@ $PROJ_DIR$\..\bsp\src\led.c + + $PROJ_DIR$\..\bsp\src\time.c + CMSIS diff --git a/TrainCamp_zhangcheng_PLSR/modbus/inc/modbus.h b/TrainCamp_zhangcheng_PLSR/modbus/inc/modbus.h index 7a60e30..70353d1 100644 --- a/TrainCamp_zhangcheng_PLSR/modbus/inc/modbus.h +++ b/TrainCamp_zhangcheng_PLSR/modbus/inc/modbus.h @@ -8,17 +8,6 @@ * @copyright Copyright (c) 2025 */ - - /** - * @file modbus.h - * @author zhangcheng - * @brief modbus相关数据结构文件 - * @version v0.1 - * @date 2025-07-25 - * - * @copyright Copyright (c) 2025 - */ - #ifndef _MODBUS_H #define _MODBUS_H diff --git a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_ack_module.c b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_ack_module.c index eef1ff6..a3f54e7 100644 --- a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_ack_module.c +++ b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_ack_module.c @@ -76,9 +76,7 @@ RESUIL AckProcModuleInit(void) * * @param[in] *pArg 任务参数 * - * @return RESUIL 初始化结果 - * @retval MODBUS_TURE 成功 - * @retval MODBUS_FALSE 失败 + * @return 无 */ static void AckProcModuleTask(void *pArg) { diff --git a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_link_check_module.c b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_link_check_module.c index 808fcb7..1c1e831 100644 --- a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_link_check_module.c +++ b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_link_check_module.c @@ -76,9 +76,7 @@ RESUIL linkCheckModuleInit(void) * * @param[in] *pArg 任务参数 * - * @return RESUIL 初始化结果 - * @retval MODBUS_TURE 成功 - * @retval MODBUS_FALSE 失败 + * @return 无 */ static void LinkCheckModuleTask(void *pArg) { diff --git a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_operate_module.c b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_operate_module.c index b6051ca..4dd964a 100644 --- a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_operate_module.c +++ b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_operate_module.c @@ -77,9 +77,7 @@ RESUIL OperateProcModuleInit(void) * * @param[in] *pArg 任务参数 * - * @return RESUIL 初始化结果 - * @retval MODBUS_TURE 成功 - * @retval MODBUS_FALSE 失败 + * @return 无 */ static void OperateProcModuleTask(void *pArg) { diff --git a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_operate_module.c~RF1ad0af.TMP b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_operate_module.c~RF1ad0af.TMP deleted file mode 100644 index f51a70e..0000000 --- a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_operate_module.c~RF1ad0af.TMP +++ /dev/null @@ -1,350 +0,0 @@ -/** - * @file modbus_operate_module.c - * @author zhangcheng - * @brief modbus请求操作处理模块源文件 - * @version v0.1 - * @date 2025-07-25 - * - * @copyright Copyright (c) 2025 - */ - - -#include "../../SYSTEM/inc/system.h" -#include "../inc/modbus_operate_module.h" -#include "../inc/modbus_request_module.h" -#include "../inc/modbus_ack_module.h" -#include "../inc/CRC16.h" - -#define OPERATE_PROC_MODULE_PRIO 3 -#define OPERATE_PROC_MODULE_STACK_SIZE 1024 -static CPU_STK OperateProcModuleStack[OPERATE_PROC_MODULE_STACK_SIZE]; -static OS_TCB OperateProcModuleTcb; -static OS_Q AckQueue; -static void OperateProcModuleTask(void * pArg); - -static uint16_t FlashBuffer[10000]; - -/** - * @brief 操作处理模块初始化 - * @details - * - * @param[in] 无 - * - * @return RESUIL 初始化结果 - * @retval MODBUS_TURE 成功 - * @retval MODBUS_FALSE 失败 - */ -RESUIL OperateProcModuleInit(void) -{ - OS_ERR err; - - CPU_SR_ALLOC(); - CPU_CRITICAL_ENTER(); - - OSTaskCreate( (OS_TCB * )&OperateProcModuleTcb, - (CPU_CHAR * )"OperateProcModule", - (OS_TASK_PTR )OperateProcModuleTask, - (void * )0, - (OS_PRIO )OPERATE_PROC_MODULE_PRIO, - (CPU_STK * )OperateProcModuleStack, - (CPU_STK_SIZE )OPERATE_PROC_MODULE_STACK_SIZE / 10, - (CPU_STK_SIZE )OPERATE_PROC_MODULE_STACK_SIZE, - (OS_MSG_QTY )0, - (OS_TICK )0, - (void * )0, - (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), - (OS_ERR * )&err); - if(err != OS_ERR_NONE) - { - MODBUS_LOG("OperateProcModule init fail\r\n"); - return MODBUS_FALSE; - } - - OSQCreate(&AckQueue, "AckQueue", 1, &err); - if(err != OS_ERR_NONE) - { - MODBUS_LOG("OperateProcModule data queue create fail\r\n"); - OSTaskDel(&OperateProcModuleTcb, &err); - return MODBUS_FALSE; - } - - CPU_CRITICAL_EXIT(); - - return MODBUS_TURE; -} - - - -/** - * @brief 请求帧处理模块 - * @details - * - * @param[in] *pArg 任务参数 - * - * @return RESUIL 初始化结果 - * @retval MODBUS_TURE 成功 - * @retval MODBUS_FALSE 失败 - */ -static void OperateProcModuleTask(void *pArg) -{ - OS_ERR err = OS_ERR_NONE; - - REQUEST_FRAME requestFrame; - ACK_FRAME ackFrame; - RESUIL res; - - uint8_t *pCoil = (uint8_t *)COIL_REGISTER_ADRR; - uint16_t *pDataRegister = (uint16_t *)DATA_REGISTER_ADRR; - uint16_t *pKeepRegister = (uint16_t *)KEEP_REGISTER_ADRR; - - while(1) - { - /* 阻塞式接收请求数据帧 */ - res = RequestOperateDataRead(&requestFrame, 0); - - if (res != MODBUS_TURE) - { - continue; - } - - ackFrame.deviceNumber = requestFrame.deviceNumber; - ackFrame.functionCode = requestFrame.functionCode; - - switch (requestFrame.functionCode) - { - case READ_COIL: - { - ackFrame.operateType = OPERATE_READ; - ackFrame.operateObjType = OPERATE_COIL; - ackFrame.format = MODBUS_STANDARD; - ackFrame.returnByteCount = requestFrame.readCount / 8; - ackFrame.data = pCoil + (requestFrame.memoryAddr / 8); - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - break; - } - case READ_KEEP_REGISTER: - { - ackFrame.operateType = OPERATE_READ; - ackFrame.operateObjType = OPERATE_REGISTER; - ackFrame.format = MODBUS_STANDARD; - ackFrame.returnByteCount = requestFrame.readCount * 2; - - if ( requestFrame.memoryAddr < 0x270F) - { - ackFrame.data = (uint8_t *)(pDataRegister + requestFrame.memoryAddr); - } - else - { - requestFrame.memoryAddr -= 0xA080; - //ackFrame.data = (uint8_t *)(pKeepRegister + requestFrame.memoryAddr); - ackFrame.data = (uint8_t *)(FlashBuffer + requestFrame.memoryAddr); - } - - //ackFrame.data = (uint8_t *)(pKeepRegister + requestFrame.memoryAddr); - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - break; - } - case WRITE_ONE_COIL: - { - ackFrame.operateType = OPERATE_WRITE; - ackFrame.operateObjType = OPERATE_COIL; - ackFrame.format = MODBUS_STANDARD; - ackFrame.returnByteCount = requestFrame.readCount; - ackFrame.memoryAddr = requestFrame.memoryAddr; - ackFrame.data = pCoil + (requestFrame.memoryAddr / 8); - - if (requestFrame.data[0] == 0xFF) - { - *ackFrame.data |= (0x01 << (requestFrame.memoryAddr % 8)); - } - else - { - *ackFrame.data &= ~(0x01 << (requestFrame.memoryAddr % 8)); - } - - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - - break; - } - case WRITE_COIL: - { - ackFrame.operateType = OPERATE_WRITE; - ackFrame.operateObjType = OPERATE_COIL; - ackFrame.format = MODBUS_STANDARD; - ackFrame.returnByteCount = requestFrame.writeCount; - ackFrame.memoryAddr = requestFrame.memoryAddr; - ackFrame.data = pCoil + (requestFrame.memoryAddr / 8); - - uint8_t offset = requestFrame.memoryAddr % 8; - - for (uint16_t i = 0; i < requestFrame.writeByteLenght; i++) - { - for (uint8_t j = 0; j < 8; j++) - { - if (*requestFrame.data & (0x01 << j)) - { - *ackFrame.data |= (1 << offset); - } - else - { - *ackFrame.data &= ~(1 << offset); - } - offset++; - if (offset == 8) - { - offset = 0; - ackFrame.data++; - } - } - requestFrame.data++; - } - - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - break; - } - case WRITE_KEEP_REGISTER: - { - ackFrame.operateType = OPERATE_WRITE; - ackFrame.operateObjType = OPERATE_REGISTER; - ackFrame.format = MODBUS_STANDARD; - ackFrame.returnByteCount = requestFrame.writeCount; - ackFrame.memoryAddr = requestFrame.memoryAddr; - - if ( requestFrame.memoryAddr < 0x270F) - { - ackFrame.data = (uint8_t *)(pDataRegister + requestFrame.memoryAddr); - - for (uint16_t i = 0; i < requestFrame.writeCount; i++) - { - ((uint16_t *)ackFrame.data)[i] = (requestFrame.data[2*i] << 8) | requestFrame.data[2*i+1]; - } - - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - - } - else - { - requestFrame.memoryAddr -= 0xA080; - //ackFrame.data = (uint8_t *)(pKeepRegister + requestFrame.memoryAddr); - ackFrame.data = (uint8_t *)(FlashBuffer + requestFrame.memoryAddr); - } - - - FLASH_Unlock(); - FLASH_DataCacheCmd(ENABLE); - - memcpy((void *)FlashBuffer, (void *)KEEP_REGISTER_ADRR, KEEP_REGISTER_SIZE); - - while (FLASH_GetStatus() != FLASH_COMPLETE); - - for (uint16_t i = 0; i < requestFrame.writeCount; i++) - { - FlashBuffer[requestFrame.memoryAddr + i] = (requestFrame.data[2*i] << 8) | requestFrame.data[2*i+1]; - } - - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - -// FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3); - for (uint16_t i = 0; i < KEEP_REGISTER_SIZE / 2; i++) - { -// FLASH_ProgramHalfWord((uint32_t)KEEP_REGISTER_ADRR + 2 * i, FlashBuffer[i]); - while (FLASH_GetStatus() != FLASH_COMPLETE); - } - - FLASH_DataCacheCmd(ENABLE); - FLASH_Lock(); - - break; - } - case READ_OUT_SCOPE_REGISTER: //0x10000 ~ 0x1A000 40KB - { - ackFrame.operateType = OPERATE_READ; - ackFrame.operateObjType = OPERATE_REGISTER; - ackFrame.format = MODBUS_EXT; - ackFrame.returnByteCount = requestFrame.readCount * 2; - ackFrame.data = (uint8_t *)((DATA_REGISTER_ADRR + DATA_REGISTER_NUMBER) + requestFrame.extMemoryAddr - 0x10000); - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - break; - } - case READ_ALL_SINGULAR_REGISTER: - { - ackFrame.operateType = OPERATE_READ; - ackFrame.operateObjType = OPERATE_REGISTER; - ackFrame.format = MODBUS_STANDARD; - ackFrame.returnByteCount = 0xFFFF; - ackFrame.memoryAddr = requestFrame.memoryAddr; - ackFrame.data = (uint8_t *)(pDataRegister + requestFrame.memoryAddr); - ackFrame.errorCode = ERROR_NONE; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - break; - } - case READ_CORRESPONDENCE_HISTORY: - { - ackFrame.data = (uint8_t *)0x08020000; - OSQPost(&AckQueue, &ackFrame, 1, - OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); - AckProcModuleSetFlags(NORMAL_FLAG_BIT); - break; - break; - } - - } - } -} - - -/** - * @brief 读取请求帧 - * @details - * - * @param[out] *requestFrame 接收请求数据帧结构体地址 - * @param[in] timeOut 读取请求帧数据超时时间 - * - * @return RESUIL 读取结果 - * @retval MODBUS_TURE 成功 - * @retval MODBUS_FALSE 失败 - */ -RESUIL OperateAckFrameRead(ACK_FRAME *ackFrame, OS_TICK timeOut) -{ - OS_ERR err; - OS_MSG_SIZE msgSize; - void *pMsgAddr = NULL; - - pMsgAddr = OSQPend(&AckQueue, - timeOut, - OS_OPT_PEND_BLOCKING, - &msgSize, - 0, - &err); - - if (err == OS_ERR_NONE) - { - memcpy(ackFrame, pMsgAddr, sizeof(ACK_FRAME)); - return MODBUS_TURE; - } - else - return MODBUS_FALSE; -} diff --git a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_request_module.c b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_request_module.c index f186a71..327faba 100644 --- a/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_request_module.c +++ b/TrainCamp_zhangcheng_PLSR/modbus/src/modbus_request_module.c @@ -79,7 +79,19 @@ RESUIL RequestProcModuleInit(void) -RESUIL AddrIsTure(uint8_t *data, uint8_t dataLenght, ACK_FRAME *ackFrame) +/** + * @brief 判断地址是否合法 + * @details + * + * @param[in] *data 地址起始字节 + * @param[in] *dataLenght 地址长度 + * @param[out] *ackFrame 异常码输出 + * + * @return RESUIL 检测结果 + * @retval MODBUS_TURE 成功 + * @retval MODBUS_FALSE 失败 +*/ +static RESUIL AddrIsTure(uint8_t *data, uint8_t dataLenght, ACK_FRAME *ackFrame) { uint32_t addr; if (dataLenght == 2) @@ -114,6 +126,20 @@ RESUIL AddrIsTure(uint8_t *data, uint8_t dataLenght, ACK_FRAME *ackFrame) return MODBUS_FALSE; } + + +/** + * @brief 判断数据长度是否合法 + * @details + * + * @param[in] *countLenght 计算的数据长度 + * @param[in] *buffLenght 接收到的数据长度 + * @param[out] *ackFrame 异常码输出 + * + * @return RESUIL 检测结果 + * @retval MODBUS_TURE 成功 + * @retval MODBUS_FALSE 失败 +*/ RESUIL DataLenghtIsTure(uint16_t countLenght, uint16_t buffLenght, ACK_FRAME *ackFrame) { if (countLenght != buffLenght) @@ -128,6 +154,18 @@ RESUIL DataLenghtIsTure(uint16_t countLenght, uint16_t buffLenght, ACK_FRAME *ac } } + +/** + * @brief 判断数据长度是否为零 + * @details + * + * @param[in] *data 数据帧数据长度起始地址 + * @param[out] *ackFrame 异常码输出 + * + * @return RESUIL 检测结果 + * @retval MODBUS_TURE 成功 + * @retval MODBUS_FALSE 失败 +*/ RESUIL DataCountIsZero(uint8_t *data, ACK_FRAME *ackFrame) { if (((data[0] << 8) | data[1]) == 0) @@ -149,9 +187,7 @@ RESUIL DataCountIsZero(uint8_t *data, ACK_FRAME *ackFrame) * * @param[in] *pArg 任务参数 * - * @return RESUIL 初始化结果 - * @retval MODBUS_TURE 成功 - * @retval MODBUS_FALSE 失败 + * @return 无 */ static void RequestProcModuleTask(void *pArg) { diff --git a/TrainCamp_zhangcheng_PLSR/system/src/system.c b/TrainCamp_zhangcheng_PLSR/system/src/system.c index 35a196b..e5aea7f 100644 --- a/TrainCamp_zhangcheng_PLSR/system/src/system.c +++ b/TrainCamp_zhangcheng_PLSR/system/src/system.c @@ -8,5 +8,5 @@ void system_hardware_init(void) usart1 = get_usart_obj("usart1"); if(NULL == usart1) while(1); - usart1->usart_init(usart1, 19200, 9, 1, 2); + usart1->usart_init(usart1, 19200, 9, 1, 1); } diff --git a/TrainCamp_zhangcheng_PLSR/system/src/usart.c b/TrainCamp_zhangcheng_PLSR/system/src/usart.c index 1de74d0..dcd2fb8 100644 --- a/TrainCamp_zhangcheng_PLSR/system/src/usart.c +++ b/TrainCamp_zhangcheng_PLSR/system/src/usart.c @@ -21,7 +21,7 @@ void _sys_exit(int x) //ضfputc int fputc(int ch, FILE *f) { - while((USART1->SR&0X40)==0);//ѭ,ֱ + while((USART1->SR&0X80)==0);//ѭ,ֱ USART1->DR = (u8) ch; return ch; }