AddFunction.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /**
  2. @copyright (C) COPYRIGHT 2022 Fortiortech Shenzhen
  3. @file AddFunction.c
  4. @author Fortiortech Appliction Team
  5. @since Create:2022-07-13
  6. @date Last modify:2022-07-14
  7. @note Last modify author is Marcel He
  8. @brief This file contains main function used for Motor Control.
  9. */
  10. #include <MyProject.h>
  11. /* Public variables --------------------------------------------------------- */
  12. bit isCtrlPowOn = false; ///< 开关机控制
  13. PWMINPUTCAL xdata mcPwmInput; ///< PWM捕获结构体变量
  14. FOCCTRL xdata mcFocCtrl; ///< FOC电机控制相关结构体变量
  15. MCRAMP data mcRefRamp; ///< 控制指令爬坡结构体相关变量
  16. debugONOFFTypeDef xdata debug_ONOFFTest; ///< ONOFF启停测试小工具结构体变量
  17. /**
  18. @brief 对变量取16位的绝对值
  19. @param[in] value
  20. @return 绝对值
  21. @date 2022-07-13
  22. */
  23. uint16 Abs_F16(int16 value)
  24. {
  25. if (value < 0)
  26. {
  27. return (-value);
  28. }
  29. else
  30. {
  31. return (value);
  32. }
  33. }
  34. /**
  35. @brief 对变量取32位的绝对值
  36. @param[in] value
  37. @return 绝对值
  38. @date 2022-07-13
  39. */
  40. uint32 Abs_F32(int32 value)
  41. {
  42. if (value < 0)
  43. {
  44. return (-value);
  45. }
  46. else
  47. {
  48. return (value);
  49. }
  50. }
  51. /**
  52. @brief PWM调速信号计算,本例程提供Duty计算,如需频率信号可自行使用mcPwmInput.Period周期值计算
  53. @date 2022-07-14
  54. */
  55. void PWMDutyCal(void)
  56. {
  57. static uint16 dutyTemp = 0;
  58. if (mcPwmInput.isUpdate) // 有新的duty更新
  59. {
  60. if ((Abs_F32(mcPwmInput.TimerDR - mcPwmInput.TimerDROld) < 0xFF) // 误差在1个Byte之间再处理
  61. && (Abs_F32(mcPwmInput.TimerARROld - mcPwmInput.TimerARR) < 0xFF)) // 误差在1个Byte之间再处理
  62. {
  63. mcPwmInput.Compare = mcPwmInput.TimerDR; // 读取DR与ARR值
  64. mcPwmInput.Period = mcPwmInput.TimerARR;
  65. mcPwmInput.Duty = DivQ_L_MDU(mcPwmInput.Compare >> 1, 0x0000, mcPwmInput.Period);
  66. /***速度随PWM增大而增大***/
  67. #if (PWMDUTY_POLARITY == NegaPWMDUTY)
  68. {
  69. dutyTemp = 32768 - mcPwmInput.Duty;
  70. }
  71. /***速度随PWM增大而减小***/
  72. #else
  73. {
  74. dutyTemp = mcPwmInput.Duty;
  75. }
  76. #endif
  77. if ((dutyTemp > ONPWMDuty) && (dutyTemp <= OFFPWMDutyHigh))
  78. {
  79. isCtrlPowOn = 1; // 开机
  80. }
  81. else if ((dutyTemp < OFFPWMDuty) || (dutyTemp > OFFPWMDutyHigh))
  82. {
  83. isCtrlPowOn = 0; // 关机
  84. }
  85. else
  86. {
  87. // 不做处理,保持前一个状态
  88. }
  89. // 转速曲线计算
  90. if (isCtrlPowOn)
  91. {
  92. if (dutyTemp <= MINPWMDuty)
  93. {
  94. mcFocCtrl.Ref = MOTOR_SPEED_MIN_RPM;
  95. }
  96. else if (dutyTemp >= MAXPWMDuty)
  97. {
  98. mcFocCtrl.Ref = MOTOR_SPEED_MAX_RPM;
  99. }
  100. else
  101. {
  102. mcFocCtrl.Ref = MOTOR_SPEED_MIN_RPM + SPEED_K * (dutyTemp - MINPWMDuty);
  103. }
  104. }
  105. else
  106. {
  107. mcFocCtrl.Ref = 0;
  108. }
  109. }
  110. mcPwmInput.isUpdate = 0;
  111. mcPwmInput.TimerDROld = mcPwmInput.TimerDR; // 将此次比较值赋值给上次比较值
  112. mcPwmInput.TimerARROld = mcPwmInput.TimerARR; // 将此次周期值赋值给上次周期值
  113. }
  114. }
  115. /**
  116. @brief VSP调速信号处理
  117. @date 2022-07-14
  118. */
  119. void VSPSample(void)
  120. {
  121. static int16 VSP = 0;
  122. /*****VREF的采样获取值并滤波******/
  123. VSP = LPFFunction(ADC7_DR, VSP, 10); // 注意低通滤波器系数范围为0---127
  124. // if((VSP > ONPWMDuty)&&(VSP <= OFFPWMDutyHigh)) lint认为右边永远成立 //在ONPWMDuty-OFFPWMDutyHigh之间,电机有转速运行
  125. if (VSP > ONPWMDuty)
  126. {
  127. isCtrlPowOn = 1; // 开机
  128. }
  129. // else if((VSP < OFFPWMDuty)||(VSP > OFFPWMDutyHigh)) //电机停机 lint认为右边永远不成立
  130. else if ((VSP < OFFPWMDuty)) // 电机停机
  131. {
  132. isCtrlPowOn = 0; // 关机
  133. }
  134. // 转速曲线计算
  135. if (isCtrlPowOn) //
  136. {
  137. #if (MOTOR_CTRL_MODE == SPEED_LOOP_CONTROL)
  138. {
  139. if (VSP <= MINPWMDuty) // 最小转速运行
  140. {
  141. mcFocCtrl.Ref = MOTOR_SPEED_MIN_RPM;
  142. }
  143. else if (VSP < MAXPWMDuty) // 调速
  144. {
  145. mcFocCtrl.Ref = MOTOR_SPEED_MIN_RPM + SPEED_K * (VSP - MINPWMDuty);
  146. }
  147. else // 最大转速运行
  148. {
  149. mcFocCtrl.Ref = MOTOR_SPEED_MAX_RPM;
  150. }
  151. }
  152. #endif
  153. }
  154. else
  155. {
  156. mcFocCtrl.Ref = 0;
  157. }
  158. }
  159. /**
  160. @brief 启停测试工具,用于测试启动可靠性
  161. @date 2022-07-14
  162. */
  163. void ONOFF_Test(void)
  164. {
  165. if (debug_ONOFFTest.State == 1) // 开机状态
  166. {
  167. debug_ONOFFTest.TimeCnt++;
  168. if (debug_ONOFFTest.TimeCnt > ONOFFTEST_ON_TIME)
  169. {
  170. debug_ONOFFTest.Times++; // 启停次数+1
  171. debug_ONOFFTest.State = 0; // 切换到关机状态
  172. debug_ONOFFTest.TimeCnt = 0;
  173. mcFocCtrl.Ref = 0; // 目标值也给0
  174. isCtrlPowOn = 0; // 关机
  175. }
  176. }
  177. else // 关机状态
  178. {
  179. debug_ONOFFTest.TimeCnt++;
  180. if (debug_ONOFFTest.TimeCnt > ONOFFTEST_OFF_TIME)
  181. {
  182. debug_ONOFFTest.TimeCnt = 0;
  183. if (mcState != mcFault)
  184. {
  185. debug_ONOFFTest.State = 1; // 切换到开机状态
  186. mcFocCtrl.Ref = ONOFFTEST_REF;
  187. isCtrlPowOn = 1; // 开机
  188. mcFocCtrl.PowerLimitValue = POWERLPFLIMIT;
  189. }
  190. }
  191. }
  192. }
  193. /**
  194. @brief 调速信号处理包含:开关机控制、将调速信号处理成控制目标给定信号
  195. @date 2022-07-14
  196. */
  197. void TargetRef_Process(void)
  198. {
  199. #if (SPEED_MODE == PWMMODE)
  200. {
  201. PWMDutyCal();
  202. mcFocCtrl.PowerLimitValue = POWERLPFLIMIT;
  203. }
  204. #elif (SPEED_MODE == SREFMODE)
  205. {
  206. VSPSample();
  207. mcFocCtrl.PowerLimitValue = POWERLPFLIMIT;
  208. }
  209. #elif (SPEED_MODE == NONEMODE)
  210. {
  211. mcFocCtrl.PowerLimitValue = POWERLPFLIMIT;
  212. isCtrlPowOn = 1; // 开机
  213. mcFocCtrl.Ref = S_Value(1500);
  214. }
  215. #elif (SPEED_MODE == KEYSCANMODE)
  216. {
  217. mcFocCtrl.PowerLimitValue = POWERLPFLIMIT;
  218. isCtrlPowOn = 1; // 开机
  219. KeyScan(); // 获取按键值
  220. }
  221. #elif (SPEED_MODE == ONOFFTEST)
  222. {
  223. ONOFF_Test();
  224. }
  225. #endif
  226. }
  227. int16 TempTHECOMP_Target = 0;
  228. /**
  229. @brief 外部闭环控制函数,示例代码提供 电流环,速度环,功率环,UQ控制示例代码,可根据需要自行修改
  230. 建议使用默认1ms周期运行
  231. @date 2022-07-14
  232. */
  233. void Speed_response(void)
  234. {
  235. static int16 refRampOut = 0;
  236. if ((mcState == mcRun) || (mcState == mcStop))
  237. {
  238. switch (mcFocCtrl.CtrlMode)
  239. {
  240. case 0:
  241. {
  242. if (mcFocCtrl.SpeedFlt > MOTOR_LOOP_RPM) //>=MOTOR_LOOP_RPM
  243. {
  244. mcFocCtrl.Mode0HoldCnt++;
  245. if (mcFocCtrl.Mode0HoldCnt > 10)
  246. {
  247. FOC_QKP = QKP;
  248. FOC_QKI = QKI;
  249. FOC_DKP = DKP;
  250. FOC_DKI = DKI;
  251. // FOC_THECOMP = _Q15(-25.0 / 180.0); // SMO 估算补偿角
  252. // 启动电流环与外环给定衔接
  253. #if (MOTOR_CTRL_MODE == SPEED_LOOP_CONTROL)
  254. {
  255. mcRefRamp.OutValue_float = mcFocCtrl.SpeedFlt;
  256. }
  257. #elif (MOTOR_CTRL_MODE == POWER_LOOP_CONTROL)
  258. {
  259. mcRefRamp.OutValue_float = mcFocCtrl.PowerFlt;
  260. }
  261. #elif (MOTOR_CTRL_MODE == UQ_LOOP_CONTROL)
  262. {
  263. mcRefRamp.OutValue_float = mcFocCtrl.UqFlt;
  264. }
  265. #endif
  266. mcFocCtrl.LoopTime = LOOP_TIME;
  267. mcRefRamp.IncValue = RAMP_INC;
  268. mcRefRamp.DecValue = RAMP_DEC;
  269. mcFocCtrl.IqRef = FOC_IQREF;
  270. FOC_IDREF = ID_RUN_CURRENT; // D轴启动电流
  271. PI1_UKH = mcFocCtrl.IqRef;
  272. PI2_Init(); // PI初始化
  273. #if (MotorFiledWeakenEn)
  274. {
  275. FiledWeakenInit();
  276. }
  277. #endif
  278. VoltageComp.Undervoltage_flag=0;
  279. VoltageComp.IncVoltage = _Q15(40.0 / HW_BOARD_VOLT_MAX);
  280. VoltageComp.LineAngel = LinearCompensationAngel;
  281. VoltageComp.LineAngelMax = LinearCompensationAngel_MAX;
  282. VoltageComp.LineAngelMin = LinearCompensationAngel_MIN;
  283. VoltageComp.VCDelayCnt = VoltageCompensationDelayCnt;
  284. mcFocCtrl.CtrlMode = 1;
  285. }
  286. }
  287. else
  288. {
  289. mcFocCtrl.Mode0HoldCnt = 0;
  290. }
  291. }
  292. break;
  293. case 1:
  294. {
  295. mcFocCtrl.LoopTime++;
  296. if (mcFocCtrl.LoopTime >= LOOP_TIME)
  297. {
  298. mcFocCtrl.LoopTime = 0;
  299. refRampOut = Motor_Ramp(mcFocCtrl.Ref); // 控制命令爬坡函数,用于实现调速信号之间平滑过渡
  300. #if (MOTOR_CTRL_MODE == CURRENT_LOOP_CONTROL)
  301. {
  302. mcFocCtrl.IqRef = refRampOut;
  303. FOC_IQREF = mcFocCtrl.IqRef;
  304. }
  305. #elif (MOTOR_CTRL_MODE == SPEED_LOOP_CONTROL)
  306. {
  307. mcFocCtrl.IqSpeedRef = HW_One_PI(refRampOut - mcFocCtrl.SpeedFlt);
  308. mcFocCtrl.LimitIqOut = HW_One_PI2(mcFocCtrl.PowerLimitValue - mcFocCtrl.PowerFlt); // 限制功率
  309. if ((mcFocCtrl.LimitIqOut < mcFocCtrl.IqSpeedRef)) // 限制输出电流
  310. {
  311. mcFocCtrl.ExtDec = (mcFocCtrl.IqRef - mcFocCtrl.LimitIqOut) / 3;
  312. mcFocCtrl.IqRef -= mcFocCtrl.ExtDec;
  313. }
  314. else
  315. {
  316. mcFocCtrl.IqRef = mcFocCtrl.IqSpeedRef;
  317. }
  318. #if (MotorFiledWeakenEn)
  319. {
  320. FileWeakenControl();
  321. }
  322. #else
  323. {
  324. FOC_IQREF = mcFocCtrl.IqRef;
  325. }
  326. #endif
  327. }
  328. #elif (MOTOR_CTRL_MODE == POWER_LOOP_CONTROL)
  329. {
  330. mcFocCtrl.IqRef = HW_One_PI(refRampOut - mcFocCtrl.PowerFlt);
  331. FOC_IQREF = mcFocCtrl.IqRef;
  332. }
  333. #elif (MOTOR_CTRL_MODE == UQ_LOOP_CONTROL)
  334. {
  335. mcFocCtrl.IqRef = HW_One_PI(refRampOut - mcFocCtrl.UqFlt);
  336. FOC_IQREF = mcFocCtrl.IqRef;
  337. }
  338. #else
  339. {
  340. /* ------------------自定义闭环START--------------------- */
  341. /* ------------------自定义闭环 END--------------------- */
  342. }
  343. #endif
  344. // if(PI1_UKMAX < SOUTMAX)
  345. // {
  346. // PI1_UKMAX+=1;
  347. // }
  348. }
  349. #if (SVPWM_5_Segment_Run_Enale == 1) // 开启五段式
  350. {
  351. if (mcFocCtrl.SpeedFlt > Motor_F5SEG_Speed) // S_Value(73500)
  352. {
  353. SetBit(FOC_CR2, F5SEG);
  354. }
  355. else if (mcFocCtrl.SpeedFlt < Motor_F7SEG_Speed) // S_Value(71500)
  356. {
  357. ClrBit(FOC_CR2, F5SEG);
  358. }
  359. }
  360. #endif
  361. }
  362. break;
  363. }
  364. }
  365. }
  366. /**
  367. @brief 控制给定爬坡函数
  368. 以浮点进行计算,解决整数爬坡由于精度的影响,导致爬坡结果阶梯变化
  369. 函数控制周期默认为闭环控制周期,建议使用默认1ms周期运行
  370. @param[in] ref 给定目标值
  371. @return 爬坡结果(int16)
  372. @date 2022-07-14
  373. */
  374. int16 Motor_Ramp(int16 ref)
  375. {
  376. mcRefRamp.RefValue = ref; // 爬坡函数输入
  377. if (mcRefRamp.OutValue_float < mcRefRamp.RefValue)
  378. {
  379. if (mcRefRamp.OutValue_float + mcRefRamp.IncValue < mcRefRamp.RefValue)
  380. {
  381. mcRefRamp.OutValue_float += mcRefRamp.IncValue;
  382. }
  383. else
  384. {
  385. mcRefRamp.OutValue_float = mcRefRamp.RefValue;
  386. }
  387. }
  388. else
  389. {
  390. if (mcRefRamp.OutValue_float - mcRefRamp.DecValue > mcRefRamp.RefValue)
  391. {
  392. mcRefRamp.OutValue_float -= mcRefRamp.DecValue;
  393. }
  394. else
  395. {
  396. mcRefRamp.OutValue_float = mcRefRamp.RefValue;
  397. }
  398. }
  399. return (int16)mcRefRamp.OutValue_float; // 输出浮点数取整
  400. }
  401. /**
  402. @brief 启动ATO爬坡函数,用于静止启动时候对ATO进行爬坡,提高启动可靠性
  403. @date 2022-07-14
  404. */
  405. void ATORamp(void)
  406. {
  407. if (mcState == mcRun)
  408. {
  409. if (mcFocCtrl.State_Count == (ATO_RAMP_PERIOD << 2))
  410. {
  411. FOC_EKP = OBSW_KP_GAIN_RUN1; // 估算器里的PI的KP
  412. FOC_EKI = OBSW_KI_GAIN_RUN1; // 估算器里的PI的KI
  413. }
  414. else if (mcFocCtrl.State_Count == ((ATO_RAMP_PERIOD << 1) + ATO_RAMP_PERIOD))
  415. {
  416. FOC_EKP = OBSW_KP_GAIN_RUN2; // 估算器里的PI的KP
  417. FOC_EKI = OBSW_KI_GAIN_RUN2; // 估算器里的PI的KI
  418. }
  419. else if (mcFocCtrl.State_Count == (ATO_RAMP_PERIOD << 1))
  420. {
  421. FOC_EKP = OBSW_KP_GAIN_RUN3; // 估算器里的PI的KP
  422. FOC_EKI = OBSW_KI_GAIN_RUN3; // 估算器里的PI的KI
  423. }
  424. else if (mcFocCtrl.State_Count <= ATO_RAMP_PERIOD && mcFocCtrl.Flg_ATORampEnd == 0)
  425. {
  426. FOC_EKP = OBSW_KP_GAIN_RUN4; // 估算器里的PI的KP
  427. FOC_EKI = OBSW_KI_GAIN_RUN4; // 估算器里的PI的KI
  428. mcFocCtrl.Flg_ATORampEnd = 1; // ATO 爬坡结束
  429. }
  430. }
  431. }
  432. /**
  433. @brief 默认1ms周期服务函数,运行信号采样,调速信号处理,闭环控制,故障检测,ATO爬坡函数
  434. 该函数运行于大循环中,由SYSTICK定时器间隔1ms触发运行。
  435. @date 2022-07-14
  436. */
  437. void TickCycle_1ms(void)
  438. {
  439. uint16 TempKeyValue = 0;
  440. #if (VoltageCompensationEn == 1)
  441. {
  442. if (VoltageComp.cpscnt <= VoltageCompensationDelayCnt)
  443. {
  444. SetBit(ADC_CR, ADCBSY); // 使能ADC的DCBUS采样
  445. }
  446. }
  447. #else
  448. {
  449. SetBit(ADC_CR, ADCBSY); // 使能ADC的DCBUS采样
  450. }
  451. #endif
  452. if ((mcState != mcInit) && (mcState != mcReady))
  453. {
  454. /* -----速度滤波----- */
  455. mcFocCtrl.SpeedFlt = LPFFunction(FOC__EOME, mcFocCtrl.SpeedFlt, 50); // 注意低通滤波器系数范围为0---127
  456. mcFocCtrl.EMFsquare = Sqrt_alpbet(FOC__EALP, FOC__EBET);
  457. if (mcState == mcRun)
  458. {
  459. mcFocCtrl.Power = FOC__POW << 3; /* -----功率滤波----- */
  460. mcFocCtrl.PowerFlt = LPFFunction(mcFocCtrl.Power, mcFocCtrl.PowerFlt, 10);
  461. }
  462. }
  463. else
  464. {
  465. mcFocCtrl.SpeedFlt = 0;
  466. mcFocCtrl.PowerFlt = 0;
  467. }
  468. /*****DCbus的采样获取值并滤波******/
  469. #if (VoltageCompensationEn == 1) // 电压补偿开启
  470. {
  471. if (VoltageComp.cpscnt <= VoltageCompensationDelayCnt) // 未进入电压补偿之前在1ms中断里面采集电压,进入之后在载波中断里面采集电压
  472. {
  473. mcFocCtrl.mcDcbusFlt = LPFFunction(ADC2_DR, mcFocCtrl.mcDcbusFlt, 50); /* -----母线电压值滤波----- */
  474. }
  475. if ((mcFocCtrl.CtrlMode == 1) && (mcState == mcRun) && (mcFaultSource == FaultNoSource)) // 进入速度环后进行延时计数
  476. {
  477. if (VoltageComp.cpscnt < VoltageCompensationDelayCnt + 10)
  478. {
  479. VoltageComp.cpscnt++;
  480. }
  481. else
  482. {
  483. VoltageComp.cpscnt = VoltageCompensationDelayCnt + 10;
  484. }
  485. }
  486. else
  487. {
  488. VoltageComp.cpscnt = 0;
  489. }
  490. /*****母线电压平均值******/
  491. BusAverageVoltage();
  492. }
  493. #else
  494. {
  495. mcFocCtrl.mcDcbusFlt = LPFFunction(ADC2_DR, mcFocCtrl.mcDcbusFlt, 50); /* -----母线电压值滤波----- */
  496. }
  497. #endif
  498. mcFocCtrl.NTCValue = ADC7_DR;
  499. mcFocCtrl.NTCValueFlt = LPFFunction(mcFocCtrl.NTCValue, mcFocCtrl.NTCValueFlt, 60);
  500. mcFocCtrl.UqFlt = LPFFunction(FOC__UQ, mcFocCtrl.UqFlt, 50);
  501. mcFocCtrl.UdFlt = LPFFunction(FOC__UD, mcFocCtrl.UdFlt, 50);
  502. /* 获取调速信号,不同调速模式(PWMMODE,NONEMODE,SREFMODE,KEYSCANMODE)的目标值修改 */
  503. TargetRef_Process();
  504. /* 启动ATO控制,环路响应,如速度环、转矩环、功率环等 */
  505. Speed_response();
  506. /* 故障保护函数功能,如过欠压保护、启动保护、缺相、堵转等 */
  507. Fault_Detection();
  508. /* 电机启动ATO爬坡函数处理 */
  509. ATORamp();
  510. /* 电机状态机的时序处理 */
  511. if (mcFocCtrl.State_Count > 0)
  512. {
  513. mcFocCtrl.State_Count--;
  514. }
  515. if ((mcState == mcRun) && (User.TPCtrlDealy > 0))
  516. {
  517. User.TPCtrlDealy--;
  518. }
  519. }
  520. uint16 SqrtUDQ(int16 sqrtUd, int16 sqrtUq)
  521. {
  522. SCAT2_COS = sqrtUd;
  523. SCAT2_SIN = sqrtUq;
  524. SMDU_RunBlock(2, ATAN);
  525. return SCAT2_RES1;
  526. }
  527. void SinCal(int16 Ref, int16 Theta, int16 *Sin, int16 *Cos)
  528. {
  529. SCAT3_COS = Ref;
  530. SCAT3_SIN = 0;
  531. SCAT3_THE = Theta;
  532. SMDU_RunBlock(3, SIN_COS);
  533. *Cos = SCAT3_RES1;
  534. *Sin = SCAT3_RES2;
  535. }