QuakeGod
2024-11-25 9aed5d7e7b3c7bf09da712e9c272ece401a7acc9
提交 | 用户 | age
5dd1b7 1
Q 2 /**
3   ******************************************************************************
4   * @file           : main.c
5   * @brief          : Main program body
6   ******************************************************************************
7   ** This notice applies to any and all portions of this file
8   * that are not between comment pairs USER CODE BEGIN and
9   * USER CODE END. Other portions of this file, whether 
10   * inserted by the user or by software development tools
11   * are owned by their respective copyright owners.
12   *
13   * COPYRIGHT(c) 2018 STMicroelectronics
14   *
15   * Redistribution and use in source and binary forms, with or without modification,
16   * are permitted provided that the following conditions are met:
17   *   1. Redistributions of source code must retain the above copyright notice,
18   *      this list of conditions and the following disclaimer.
19   *   2. Redistributions in binary form must reproduce the above copyright notice,
20   *      this list of conditions and the following disclaimer in the documentation
21   *      and/or other materials provided with the distribution.
22   *   3. Neither the name of STMicroelectronics nor the names of its contributors
23   *      may be used to endorse or promote products derived from this software
24   *      without specific prior written permission.
25   *
26   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36   *
37   ******************************************************************************
38   */
39 /* Includes ------------------------------------------------------------------*/
40 #include "main.h"
41 #include "stm32f0xx_hal.h"
42
43 /* USER CODE BEGIN Includes */
44 #include "Globaldef.h"
45 #include "debug.h"
46 #include "Functions.h"
47 #include "KMachine.h"
48 #include "PLCfunctions.h"
49 //#include "KBus.h"
50 #include "KLink.h"
51 #include "string.h"
52 #include "BSP.h"
53 #include "ModbusRTU.h"
54 #if (BOARD_TYPE == 13)
55 #include "w5500_port.h"
56 #include "../src/Ethernet/socket.h"
57 #include "../src/Ethernet/loopback.h"
58 #elif (BOARD_TYPE == 14)
59 #include "FP0.h"
60 #elif (BOARD_TYPE == 15 || BOARD_TYPE == 16)
61 #include "KWireless.h"
62 //#include "user.h"
63 //#include "../src/radio/inc/sx126x-board.h"
64 #endif
65
66 /* USER CODE END Includes */
67
68 /* Private variables ---------------------------------------------------------*/
69
70 /* USER CODE BEGIN PV */
71 /* Private variables ---------------------------------------------------------*/
72
73 #define RX2BUFSIZE 64
74 #define TX2BUFSIZE 64
75
76 unsigned char Uart1RxBuf[128];
77 unsigned char Uart1TxBuf[260];
78
79 unsigned char Uart2RxBuf[RX2BUFSIZE];
80 unsigned char Uart2TxBuf[TX2BUFSIZE];
81
82 unsigned char SlowFlicker=0;
83 unsigned char FastFlicker=0;
84
85 unsigned int Uart1IdelTimer = 0;
86 stBinProg1 * pProgs = (stBinProg1 *)STORE_PRG_BASE;
87
88 uint32_t us1,us2,us3,us4,us5,us6;
89
90 /* USER CODE END PV */
91
92 /* Private function prototypes -----------------------------------------------*/
93
94
95 /* USER CODE BEGIN PFP */
96 /* Private function prototypes -----------------------------------------------*/
97
98 const unsigned char LEDSEGTAB[]={
99 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,    //0-F
100 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc,0xb9,0xde,0xf9,0xf1,  //0.-F.
101 0x00,0x40,            //  ,-,_,~,o,n,N,<,>,J,r,
102 };
103
104 /* USER CODE END PFP */
105
106 /* USER CODE BEGIN 0 */
107
108 int HexToInt(char ch)
109 {
110     if (ch>='0' && ch <='9') return ch-'0';
111     if (ch>='A' && ch <='F') return ch-'A'+10;
112     if (ch>='a' && ch <='f') return ch-'a'+10;
113     return 0;
114 }
115
116 void HAL_SYSTICK_Callback(void)
117 {
118 static int Count=0;
119     CurTickuS += 100;    
120     nCurTick++;
121     nSlaveTick++;
122     Count++;
123     if (Count>=10000) 
124     {
125         Count=0; 
126         KMem.CurTimeSec++;
127         KMem.ThisRunTime++; KMem.TotalRunTime++;
128         if (KMRunStat.bLEDFlick) KMRunStat.bLEDFlick--;
129         if (KMRunStat.bLEDFlick >120) KMRunStat.bLEDFlick=120;
130     }
131
132     return;
133 }
134
135 /* USER CODE END 0 */
136
137 /**
138   * @brief  The application entry point.
139   *
140   * @retval None
141   */
142 int main(void)
143 {
144   /* USER CODE BEGIN 1 */
145     KMRunStat.bLEDFlick = 1;
146     
147     InitUartstat(&Uart1Stat,Uart1RxBuf,sizeof(Uart1RxBuf),Uart1TxBuf,sizeof(Uart1TxBuf));
148     InitUartstat(&Uart2Stat,Uart2RxBuf,sizeof(Uart2RxBuf),Uart2TxBuf,sizeof(Uart2TxBuf));
149   /* USER CODE END 1 */
150
151   /* MCU Configuration----------------------------------------------------------*/
152
153   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
154   HAL_Init();
155
156   /* USER CODE BEGIN Init */
157
158     for (int i=0;i<9;i++)
159     {
160 //        memset(KBusChnStats[i],0,0);        
161         KBusChnStats[i].SendPackets=0;
162         KBusChnStats[i].RecvPackets=0;
163         KBusChnStats[i].LostPackets=0;
164         KBusChnStats[i].CtnLstPkts=0;
165         KBusChnStats[i].MaxCtnLstPkts=0;
166         KBusChnStats[i].NotPkgErr=0;
167         KBusChnStats[i].PkgLenErr=0;
168         KBusChnStats[i].TimeOutErr=0;
169         KBusChnStats[i].BCCErr=0;
170         KBusChnStats[i].Delay=0;
171         KBusChnStats[i].MaxDelay=0;
172     }
173     
174         KMem.LastScanTime=0;
175         KMem.ScanTimeuS=0;
176         KMem.MinScanTimeuS=99999;
177         KMem.MaxScanTimeuS=0;
178
179 //        KMem.SDD[14]=(unsigned int)&KMStoreSysCfg;
180 //        KMem.SDD[15]=(unsigned int)&KMStoreSysCfg1;
181         KMem.SDD[12]=((uint32_t *)UID_BASE)[0];
182 //        KMem.SDD[13]=((uint32_t *)UID_BASE)[1];
183 //        KMem.SDD[14]=((uint32_t *)UID_BASE)[2];
184         KMem.SDD[13]=PendSvCount;
185         KMem.SDD[14]=RCC->CSR;
186 //        KMem.SDD[15]=*(uint32_t *)FLASHSIZE_BASE;
187 //        KMem.SDD[16]=(unsigned int)&KMSysCfg;
188     
189   /* USER CODE END Init */
190
191   /* Configure the system clock */
192   SystemClock_Config();
193
194   /* USER CODE BEGIN SysInit */
195     TickFreq=10000;        //Tick频率
196     InituS(TickFreq);    
197  // HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/TickFreq);    //重新定义SysTick的频率
198
199   /* USER CODE END SysInit */
200
201   /* Initialize all configured peripherals */
202   MX_GPIO_Init();
203   MX_DMA_Init();
204     
205     KMachineInit();
206     ReadSysCfgFromFlash(&storedKMSysCfg);
207     
208     KMRunStat.bLEDFlick = 1;
209     
210     KMem.CurJumperSW=ReadJumperSW();
211         KMem.CurJumperSW=1;
212     KMem.EffJumperSW=KMem.CurJumperSW;
213     
214 //    Uart2Baud = AlterUart2Baud;
215     
216 #if (BOARD_TYPE == 14)
217     KMem.EffJumperSW|=0x10;
218     nStationID=KMem.EffJumperSW&0x0f;
219   if ((KMem.EffJumperSW&0x10)!=0) {bKBusMaster=1;bKBusSlave=0;}
220     else{bKBusMaster=0;bKBusSlave=1;}
221     nChilds=nStationID;
222     FP0_Init();
223
224 #elif (BOARD_TYPE == 15 || BOARD_TYPE == 16)
225     nStationID=1 ;//KMem.EffJumperSW&0x0f;
226 //    if (KMem.EffJumperSW == 0x1f) {bKBusRepeater=1;bKBusMaster=1;bKBusSlave=0;}
227 //  else if ((KMem.EffJumperSW&0x10)!=0) {bKBusMaster=1;bKBusSlave=0;}
228 //    else
229         {bKBusMaster=0;bKBusSlave=1;}    
230 #else
231     nStationID=KMem.EffJumperSW&0x0f;
232     if (KMem.EffJumperSW == 0x1f) {bKBusRepeater=1;bKBusMaster=1;bKBusSlave=0;}
233   else if ((KMem.EffJumperSW&0x10)!=0) {bKBusMaster=1;bKBusSlave=0;}
234     else{bKBusMaster=0;bKBusSlave=1;}
235 #endif
236     nChilds=nStationID;
237     nCurPollId=1;
238     //if (KMem.EffJumperSW == 0x00)
239         Uart1Baud = DefaultUart1Baud;
240   MX_USART1_UART_Init();
241   MX_USART2_UART_Init();
242
243     MX_SPI1_Init();
244     LL_SPI_EnableIT_RXNE(SPI1);
245
246 #if (BOARD_TYPE == 14)
247 //    MX_SPI2_Init();
248 //  MX_ADC_Init();
249 #else
250     MX_SPI2_Init();
251   MX_ADC_Init();
252 #endif
253
254     MX_IWDG_Init();
255
256     MX_TIM6_Init();
257     LL_TIM_EnableCounter(TIM6);
258     
259   /* USER CODE BEGIN 2 */
260     LL_USART_EnableIT_RXNE(USART1);
261     LL_USART_EnableIT_IDLE(USART1);
262     LL_USART_EnableIT_TC(USART1);
263
264 //    LL_USART_EnableIT_RXNE(USART2);
265     Uart2RecvDMA(Uart2RecvBuf1,sizeof(Uart2RecvBuf1));    
266     LL_USART_EnableIT_IDLE(USART2);
267     LL_USART_EnableIT_TC(USART2);
268 #if (BOARD_TYPE == 13)
269     int res;
270     res = w5500_init();
271     KMem.SDD[28]=res;
272     
273 //    res=socket(0,Sn_MR_TCP,5000,0);
274     KMem.SDD[29]=res;    
275     
276 //    res = listen(0);
277 #endif    
278 //    if (bKBusSlave)
279     {
280     //    LL_USART_EnableAutoBaudRate(USART1);
281     //    LL_USART_SetAutoBaudRateMode(USART1, LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE);        
282     //    LL_USART_EnableAutoBaudRate(USART2);
283     //    LL_USART_SetAutoBaudRateMode(USART2, LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE);        
284     }
285     //LL_USART_EnableIT_TXE(USART1);
286   /* USER CODE END 2 */
287
288     
289   /* Infinite loop */
290   /* USER CODE BEGIN WHILE */
291
292     HAL_Delay(10);                
293     SetRunLed(1);                //Turn On Run Led
294     SetErrLed(0);                //Turn Off Err Led
295
296 #if (BOARD_TYPE == 14)
297 //    PutOutput (0);                    //Clear all Output
298 //    Enable595(1);                        //Enable 595 Output 
299 #else
300     PutOutput (0);                    //Clear all Output
301     Enable595(1);                        //Enable 595 Output 
302 #endif
303
304         if (GetBoardType() == 7 || GetBoardType() ==8 
305             || GetBoardType() == 9 || GetBoardType() ==10 ||GetBoardType() ==13 ||GetBoardType() ==15 || BOARD_TYPE == 16) 
306         {
307             displayInput(0xffff);        //
308             EnableDisIn(1);                //Input Diaplay Enable 595 
309         }
310     SetOutStat(0);            //OK Good, signal
311     ShowInitInfo();
312     KMem.LastScanTime = GetuS();
313
314     KMRunStat.WorkMode=0;
315     KMRunStat.WorkMode2=0;
316         
317     KMRunStat.WorkMode = storedKMSysCfg.theKMSysCfg.workmode;
318         
319     if (KMRunStat.WorkMode == 1){
320         InitPLC();
321         KMRunStat.WorkMode2 = KMem.CurJumperSW&0x20 ;
322         if (KMRunStat.WorkMode2) {
323             StartPLC(); }
324     }
325     KMem.WX[7]=0x5a;
326     
327   while (1)
328   {
329         //int MyKeyStat1,MyKeyStat2;
330         //MyKeyStat1=GetInput();
331
332         //*((unsigned int *)&(PLCMem.SDT[10]))=nRunCount;
333     //    KMem.nRunCount=nRunCount;
334         SlowFlicker=0;
335         FastFlicker=1;        
336         us1=GetuS();
337         int haltick=HAL_GetTick();
338         
339         int thisJumperSW=ReadJumperSW();
340         
341         if (KMRunStat.WorkMode&1){
342             if (thisJumperSW&0x20 && !(KMem.CurJumperSW&0x20))  // Run 开关 正 跳变。
343             {StartPLC();}
344             if (!(thisJumperSW&0x20) && (KMem.CurJumperSW&0x20))  // Run 开关 负 跳变。
345             {StopPLC();}
346         }
347         
348         KMem.CurJumperSW=thisJumperSW;
349         KMem.haltick=haltick;
350 //        KMem.TotalRunTime=TotalRunTime;
351 //        KMem.ThisRunTime=ThisRunTime;        
352         
353 //        *((unsigned int *)&(PLCMem.SDT[2]))=nChilds;
354 //        KMem.SDD[13]=PendSvCount;
355 //        KMem.SDD[14]=RCC->CSR;        
356         
357         int a;
358         a        = LL_GPIO_ReadInputPort(GPIOA);
359         KMem.WDT[120]=a;
360         a        = LL_GPIO_ReadInputPort(GPIOB);
361         KMem.WDT[121]=a;
362         a        = LL_GPIO_ReadInputPort(GPIOC);
363         KMem.WDT[122]=a;
364         a        = LL_GPIO_ReadInputPort(GPIOD);
365         KMem.WDT[123]=a;
366         
367
368         KMem.WX[0]= GetInput();        
369         
370         if (GetBoardType() == 7 || GetBoardType() ==8 
371             || GetBoardType() == 9 || GetBoardType() ==10 || GetBoardType() ==15 || GetBoardType() ==16) 
372         {
373             displayInput(KMem.WX[0]);
374         }
375         us2=GetuS();
376         if (PowerDownEvent) {        KMem.WX[0]=0;}
377 ///*
378         if ((KMem.nRunCount &0x1f) == 0x02)
379         {
380             ADCProcess();
381             if (PowerDownEvent)
382             {
383                 KMem.WX[0]=0;
384                 if (!OldPowerDownEvent)
385                 {
386                     OldPowerDownEvent = PowerDownEvent;
387                     OldPowerDownEventTime = nCurTick;
388                     PowerDownProcess();
389                 }
390             }else
391             {
392                 if (OldPowerDownEvent)
393                 {
394                     OldPowerDownEvent=PowerDownEvent;
395                     PowerRecoverProcess();
396                     
397                 }
398             }
399         }
400 //*/
401
402         KMem.WX[0] =  KMem.ADCValues[3];
403         KMem.WX[1] =  KMem.ADCValues[4];        
404
405 //        pProgs = (stBinProg1 *) STORE_PRG_BASE;
406
407         if (    KMRunStat.WorkMode==1 ) //&& bKBusMaster)
408         {
409             if (KMRunStat.nBinProgBank == 0){
410                 pProgs=(stBinProg1 *)STORE_PRG_BASE;
411             }else {
412                 pProgs=(stBinProg1 *)ALT_PRG_BASE;
413             }
414             nSizeProg1=KMRunStat.nBinProgSize;
415         //    pProgs=(stBinProg1 *)prog1;
416             
417             ProcessPLCBinProg(pProgs, nSizeProg1);
418         }
419
420         KMem.ScanTimeuS=us2-KMem.LastScanTime;
421         KMem.LastScanTime = us2;
422         if (KMem.ScanTimeuS < KMem.MinScanTimeuS) {KMem.MinScanTimeuS = KMem.ScanTimeuS;}
423         if (KMem.ScanTimeuS > KMem.MaxScanTimeuS) {KMem.MaxScanTimeuS = KMem.ScanTimeuS;}
424
425         //        if (bKBusRepeater)        {    KBusRepeaterFunc();    }
426
427         us3=GetuS();
428
429         if (bKBusMaster)        
430         {
431             if (nChilds>0) {        KBusMasterFunc(2); }
432
433         }
434             if (haltick&0x00002000) SlowFlicker=1;
435             else SlowFlicker=0;
436             if (haltick&0x00000800) FastFlicker=1;
437             else FastFlicker=0;    
438
439         if (bKBusSlave)        
440         {
441 //            BufferOut[0]=KMem.WX[0];
442 #if (BOARD_TYPE == 15 || BOARD_TYPE == 16)
443 //            KBusSlaveFunc(2);    
444         //    if (! KMem.RunStat) {BufferIn[0]=0;}
445         //    KMem.WY[0]=BufferIn[0];
446 #else
447             KBusSlaveFunc(2);    
448             if (! KMem.RunStat) {KMem.WLY[0]=0;}
449 //            KMem.WLY[0]=BufferIn[0];
450 #endif
451             if (nSlaveTick&0x00002000) SlowFlicker=1;
452             else SlowFlicker=0;
453             if (nSlaveTick&0x00000800) FastFlicker=1;
454             else FastFlicker=0;            
455
456         }
457
458 //        KMem.WY[0]=nCount2>>5;
459         if (KMem.RunStat) {KMem.RunStat--;}
460         if (KMem.ErrStat) {KMem.ErrStat--;}
461         
462         if (KMRunStat.bLEDFlick)
463         {
464             SetRunLed(FastFlicker);
465             SetErrLed(FastFlicker);
466             SetErr2Led(FastFlicker);
467             SetOutStat(!FastFlicker);
468             //KMRunStat.bLEDFlick-- ;
469         }
470         else
471         {
472             if (KMRunStat.WorkMode==1 ) {
473                 if (PLCMem.bPLCRunning){SetRunLed(SlowFlicker);}
474                     else {SetRunLed(0);}
475             }
476             else {
477                     if (!KMem.RunStat) SetRunLed(SlowFlicker);
478                     else SetRunLed(FastFlicker);
479             }
480             if (!KMem.ErrStat) 
481             {
482                 SetErrLed(0);
483                 SetErr2Led(0);
484                 SetOutStat(1);
485             }
486             else 
487             {
488                 SetErrLed(FastFlicker);
489                 SetErr2Led(FastFlicker);
490                 SetOutStat(0);
491                 
492             }
493         }
494         
495 //        SetRunLed(RunStat);
496 //        SetErrLed(ErrStat);
497         
498         us4=GetuS();
499 //        EffJumperSW = GetInput(20)&0xff;
500
501
502         KBusMem.WLX[0]=KMem.WX[0];
503         KBusMem.WLX[1]=KMem.WX[1];
504
505         us5=GetuS();
506         
507 #if (BOARD_TYPE == 14)
508 //        PutOutput (KMem.WY[0]);
509 #else
510         PutOutput (KMem.WY[0]);
511 #endif
512         //PutOutput (KMem.nRunCount>>8);
513         //PutOutput(0x0f70);
514
515 //        if (bKBusMaster) ShowInfo();
516 //        if (bKBusSlave) ShowInfo();
517         us6=GetuS();
518         add1(10,10);
519         for (int i=0;i<64;i++)
520         {
521 //            ProcessTimer(i);
522         }
523         KMem.nRunCount++;
524 //        int nSize=sizeof(stKBusChnStat);
525 //        memcpy(&KMem.SDT[64],&KBusChnStats[1],nSize);
526 //        memcpy(&KMem.SDT[64+nSize/2],&KBusChnStats[2],nSize);
527 //        for (int i=0;i<128;i++)    {        SDT[i]=i;    }
528 //        SDT[48]=55;
529         if (Uart1RecvBuf1DataLen >0 && Uart1Stat.bPacketRecved)
530         {
531             int res1 = -1;
532             res1 = ModBusSlaveParsePkg(1, Uart1RecvBuf1, Uart1RecvBuf1DataLen);
533             if (res1 !=0)
534             {
535                 KLParsePacket(1, Uart1RecvBuf1, Uart1RecvBuf1DataLen);
536             }
537             Uart1RecvBuf1DataLen=0;
538             Uart1Stat.bPacketRecved=0;
539             Uart1IdelTimer = 0;
540         }else {
541             if (Uart1IdelTimer>600000) { // 超过60秒没有数据传输,重新进入自适应波特率状态
542                 LL_USART_EnableAutoBaudRate(USART1);
543                 LL_USART_SetAutoBaudRateMode(USART1, LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE);
544             }else {
545                     Uart1IdelTimer++;
546             }
547         }
548  if (bKBusSlave)    HAL_Delay(0);
549 /*
550         if (!IsEmpty(&Uart1Stat.QRx))
551         {
552             unsigned char k=PopOne(&Uart1Stat.QRx);
553             if (k=='L')
554             {
555                 clearscreen();
556             }
557         }
558 */
559
560
561 #if (BOARD_TYPE == 13)    
562      w5500_network_info_show();
563 //     loopback_tcps(0,str1,5000);
564 #endif
565
566      LL_IWDG_ReloadCounter(IWDG);
567         
568   }    //while (1) ;
569   /* USER CODE END WHILE */
570
571   /* USER CODE BEGIN 3 */
572
573   /* USER CODE END 3 */
574
575 }
576
577
578 /* USER CODE BEGIN 4 */
579
580 /* USER CODE END 4 */
581
582 /**
583   * @brief  This function is executed in case of error occurrence.
584   * @param  file: The file name as string.
585   * @param  line: The line in file as a number.
586   * @retval None
587   */
588 void _Error_Handler(char *file, int line)
589 {
590   /* USER CODE BEGIN Error_Handler_Debug */
591   /* User can add his own implementation to report the HAL error return state */
592   while(1)
593   {
594   }
595   /* USER CODE END Error_Handler_Debug */
596 }
597
598 #ifdef  USE_FULL_ASSERT
599 /**
600   * @brief  Reports the name of the source file and the source line number
601   *         where the assert_param error has occurred.
602   * @param  file: pointer to the source file name
603   * @param  line: assert_param error line source number
604   * @retval None
605   */
606 void assert_failed(uint8_t* file, uint32_t line)
607
608   /* USER CODE BEGIN 6 */
609   /* User can add his own implementation to report the file name and line number,
610      tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
611   /* USER CODE END 6 */
612 }
613 #endif /* USE_FULL_ASSERT */
614
615 /**
616   * @}
617   */
618
619 /**
620   * @}
621   */
622
623 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/