Tekijä | SHA1 | Viesti | Päivämäärä |
---|---|---|---|
|
85b6075f9b | 增加绝对模式 | 7 tuntia sitten |
|
17b02e2aed | 过程性保存 | 1 päivä sitten |
|
9e3fa14782 | 增加减速功能 | 1 päivä sitten |
|
16daa756ed | 修改输出计数误差 | 1 päivä sitten |
|
eede0ad12f | 增加脉冲输出计数 | 1 päivä sitten |
|
0d58029f71 | 优化跳转时多段波形逻辑 | 2 päivää sitten |
|
ba4a9f0c58 | 增加直线加减速多段跳转功能 | 2 päivää sitten |
|
42778b3d2c | 增加直线加减速功能 | 2 päivää sitten |
|
49d9775f1f | 添加PLSR.c | 6 päivää sitten |
|
62d4addc0c | 添加PLSR.c | 6 päivää sitten |
|
8b72eb7900 | 增加定时器配置 | 1 viikko sitten |
@@ -2,4 +2,5 @@ TrainCamp_zhangcheng_PLSR/.vscode | |||||
TrainCamp_zhangcheng_PLSR/iar/Debug | TrainCamp_zhangcheng_PLSR/iar/Debug | ||||
TrainCamp_zhangcheng_PLSR/iar/settings | TrainCamp_zhangcheng_PLSR/iar/settings | ||||
TrainCamp_zhangcheng_PLSR/iar/PLSR.dep | TrainCamp_zhangcheng_PLSR/iar/PLSR.dep | ||||
TrainCamp_zhangcheng_PLSR/iar/PLSR.ewt | |||||
TrainCamp_zhangcheng_PLSR/iar/PLSR.ewt | |||||
.TMP |
@@ -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); |
@@ -4,37 +4,7 @@ | |||||
#include "../modbus/inc/modbus_operate_module.h" | #include "../modbus/inc/modbus_operate_module.h" | ||||
#include "../modbus/inc/modbus_ack_module.h" | #include "../modbus/inc/modbus_ack_module.h" | ||||
#include "../modbus/inc/modbus_link_check_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) | int main(void) | ||||
@@ -60,6 +30,7 @@ int main(void) | |||||
OperateProcModuleInit(); | OperateProcModuleInit(); | ||||
AckProcModuleInit(); | AckProcModuleInit(); | ||||
linkCheckModuleInit(); | linkCheckModuleInit(); | ||||
PLSRInit(); | |||||
OSStart(); | OSStart(); | ||||
} | } | ||||
@@ -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); | |||||
} |
@@ -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 | |||||
@@ -187,6 +187,30 @@ static gpio_obj_t g_stm32f103_gpio_g = { | |||||
&g_stm32f103_gpio_g_priv | &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外设列表 */ | /* GPIO外设列表 */ | ||||
static gpio_obj_t *g_gpio_devs[] = { | static gpio_obj_t *g_gpio_devs[] = { | ||||
&g_stm32f103_gpio_a, | &g_stm32f103_gpio_a, | ||||
@@ -195,7 +219,8 @@ static gpio_obj_t *g_gpio_devs[] = { | |||||
&g_stm32f103_gpio_d, | &g_stm32f103_gpio_d, | ||||
&g_stm32f103_gpio_e, | &g_stm32f103_gpio_e, | ||||
&g_stm32f103_gpio_f, | &g_stm32f103_gpio_f, | ||||
&g_stm32f103_gpio_g | |||||
&g_stm32f103_gpio_g, | |||||
&g_stm32f103_gpio_h | |||||
}; | }; | ||||
/* GPIO模式私有数据列表 */ | /* GPIO模式私有数据列表 */ | ||||
@@ -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; | |||||
} |
@@ -2122,6 +2122,9 @@ | |||||
<file> | <file> | ||||
<name>$PROJ_DIR$\..\app\src\main.c</name> | <name>$PROJ_DIR$\..\app\src\main.c</name> | ||||
</file> | </file> | ||||
<file> | |||||
<name>$PROJ_DIR$\..\app\src\plsr.c</name> | |||||
</file> | |||||
</group> | </group> | ||||
<group> | <group> | ||||
<name>BSP</name> | <name>BSP</name> | ||||
@@ -2131,6 +2134,9 @@ | |||||
<file> | <file> | ||||
<name>$PROJ_DIR$\..\bsp\src\led.c</name> | <name>$PROJ_DIR$\..\bsp\src\led.c</name> | ||||
</file> | </file> | ||||
<file> | |||||
<name>$PROJ_DIR$\..\bsp\src\time.c</name> | |||||
</file> | |||||
</group> | </group> | ||||
<group> | <group> | ||||
<name>CMSIS</name> | <name>CMSIS</name> | ||||
@@ -8,17 +8,6 @@ | |||||
* @copyright Copyright (c) 2025 | * @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 | #ifndef _MODBUS_H | ||||
#define _MODBUS_H | #define _MODBUS_H | ||||
@@ -76,9 +76,7 @@ RESUIL AckProcModuleInit(void) | |||||
* | * | ||||
* @param[in] *pArg 任务参数 | * @param[in] *pArg 任务参数 | ||||
* | * | ||||
* @return RESUIL 初始化结果 | |||||
* @retval MODBUS_TURE 成功 | |||||
* @retval MODBUS_FALSE 失败 | |||||
* @return 无 | |||||
*/ | */ | ||||
static void AckProcModuleTask(void *pArg) | static void AckProcModuleTask(void *pArg) | ||||
{ | { | ||||
@@ -76,9 +76,7 @@ RESUIL linkCheckModuleInit(void) | |||||
* | * | ||||
* @param[in] *pArg 任务参数 | * @param[in] *pArg 任务参数 | ||||
* | * | ||||
* @return RESUIL 初始化结果 | |||||
* @retval MODBUS_TURE 成功 | |||||
* @retval MODBUS_FALSE 失败 | |||||
* @return 无 | |||||
*/ | */ | ||||
static void LinkCheckModuleTask(void *pArg) | static void LinkCheckModuleTask(void *pArg) | ||||
{ | { | ||||
@@ -77,9 +77,7 @@ RESUIL OperateProcModuleInit(void) | |||||
* | * | ||||
* @param[in] *pArg 任务参数 | * @param[in] *pArg 任务参数 | ||||
* | * | ||||
* @return RESUIL 初始化结果 | |||||
* @retval MODBUS_TURE 成功 | |||||
* @retval MODBUS_FALSE 失败 | |||||
* @return 无 | |||||
*/ | */ | ||||
static void OperateProcModuleTask(void *pArg) | static void OperateProcModuleTask(void *pArg) | ||||
{ | { | ||||
@@ -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; | |||||
} |
@@ -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; | uint32_t addr; | ||||
if (dataLenght == 2) | if (dataLenght == 2) | ||||
@@ -114,6 +126,20 @@ RESUIL AddrIsTure(uint8_t *data, uint8_t dataLenght, ACK_FRAME *ackFrame) | |||||
return MODBUS_FALSE; | 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) | RESUIL DataLenghtIsTure(uint16_t countLenght, uint16_t buffLenght, ACK_FRAME *ackFrame) | ||||
{ | { | ||||
if (countLenght != buffLenght) | 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) | RESUIL DataCountIsZero(uint8_t *data, ACK_FRAME *ackFrame) | ||||
{ | { | ||||
if (((data[0] << 8) | data[1]) == 0) | if (((data[0] << 8) | data[1]) == 0) | ||||
@@ -149,9 +187,7 @@ RESUIL DataCountIsZero(uint8_t *data, ACK_FRAME *ackFrame) | |||||
* | * | ||||
* @param[in] *pArg 任务参数 | * @param[in] *pArg 任务参数 | ||||
* | * | ||||
* @return RESUIL 初始化结果 | |||||
* @retval MODBUS_TURE 成功 | |||||
* @retval MODBUS_FALSE 失败 | |||||
* @return 无 | |||||
*/ | */ | ||||
static void RequestProcModuleTask(void *pArg) | static void RequestProcModuleTask(void *pArg) | ||||
{ | { | ||||
@@ -8,5 +8,5 @@ void system_hardware_init(void) | |||||
usart1 = get_usart_obj("usart1"); | usart1 = get_usart_obj("usart1"); | ||||
if(NULL == usart1) | if(NULL == usart1) | ||||
while(1); | while(1); | ||||
usart1->usart_init(usart1, 19200, 9, 1, 2); | |||||
usart1->usart_init(usart1, 19200, 9, 1, 1); | |||||
} | } |
@@ -21,7 +21,7 @@ void _sys_exit(int x) | |||||
//重定义fputc函数 | //重定义fputc函数 | ||||
int fputc(int ch, FILE *f) | int fputc(int ch, FILE *f) | ||||
{ | { | ||||
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 | |||||
while((USART1->SR&0X80)==0);//循环发送,直到发送完毕 | |||||
USART1->DR = (u8) ch; | USART1->DR = (u8) ch; | ||||
return ch; | return ch; | ||||
} | } | ||||