STM32H7 - ضبط الساعة بدون HAL

منذ وقت ليس ببعيد ، أطلقت STM خط STM32H7 القوي من البلورات بمعايير وحدات التحكم الدقيقة. ما جذبني إليها:

  • زيادة التردد الأساسي حتى 400 ميجاهرتز
  • زيادة ذاكرة الوصول العشوائي ، تصل إلى 1 ميغا بايت
  • 16 بت ADC
  • التوافق من طرف إلى طرف مع سلسلة F7

فكرت تمامًا ، لقد قمت بلحام الكريستال STM32H743IIT6 على اللوحة بدلاً من STM32F746IGT6 وبدأت مشروعًا جديدًا في SW4STM32.

من الملائم استخدام علامة تبويب تكوين الساعة لبرنامج STM32CubeMX لحساب معاملات الفواصل وعوامل نظام الساعة في وحدة التحكم الدقيقة.

إعدادات الساعة:

  • الكوارتز الخارجي - 8 ميجا هرتز
  • مصدر التردد لـ PLL1 - الكوارتز الخارجي (HSE)
  • مقسم PLL1 - 4 (DIVM1)
  • مضاعف PLL1-400 (DIVN1)
  • مقسمات الإخراج - 2 (DIVP1 ، DIVQ1 ، DIVR1)

وبالتالي ، فإن التردد الأساسي (SYSCLK) هو 400 ميجاهرتز.



بالإضافة إلى STM32CubeMX ، هناك أيضًا حزمة البرامج الثابتة STM32CubeH7 ، والتي تحتوي على عدد كبير من الأمثلة للعمل مع الأجهزة الطرفية لـ STM32H7. كان منه أن تسلسل التهيئة لنظام الساعة من متحكم دقيق.

المعلومات والتعليقات مأخوذة من المصادر التالية:

  • SystemClock_Config من حزمة البرامج الثابتة STM32CubeH7
  • دليل مرجعي STM32H743 / 753 و STM32H750 متقدم MCU 32 بت المستندة إلى ARM
  • - ورقة البيانات STM32H743xI

لذلك دعونا نبدأ.

1. تشغيل الكوارتز الخارجي وانتظار الاستعداد.

// Enable HSE RCC->CR |= RCC_CR_HSEON; // Wait till HSE is ready while((RCC->CR & RCC_CR_HSERDY) == 0); 

2. بيان مصدر التردد ل PLL1 - الكوارتز الخارجي.

 //RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC -> PLLCKSELR |= RCC_PLLCKSELR_PLLSRC_HSE; 

3. يتم تعيين قيمة المقسوم على 4.

 //PLLM = 4 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_5; //0 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_4; //0 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_3; //0 RCC -> PLLCKSELR |= RCC_PLLCKSELR_DIVM1_2; //1 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_1; //0 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_0; //0 

4. العامل N والمقسوم عليه P، Q، R

  //PLL1DIVR bits //DIVN1[8:0] 0 - 8 PLLN = 400 //DIVP1[6:0] 9 - 15 PLLP = 2 //DIVQ1[6:0] 16 - 22 PLLQ = 2 //DIVR1[6:0] 24 - 30 PLLR = 2 RCC -> PLL1DIVR |= 0x0101038F; 

5. مقسم التردد الجزئي PLL (إذا لزم الأمر)

 // /* Configure PLL PLL1FRACN */ //__HAL_RCC_PLLFRACN_CONFIG(RCC_OscInitStruct->PLL.PLLFRACN); RCC -> PLL1FRACR = 0; 

6. بيان نطاق تردد الإدخال PLL1

  /* Select PLL1 input reference frequency range: VCI */ //__HAL_RCC_PLL_VCIRANGE(RCC_OscInitStruct->PLL.PLLRGE) ; RCC->PLLCFGR |= RCC_PLLCFGR_PLL1RGE_3; 

7. بيان نطاق التردد الناتج PLL1

  /* Select PLL1 output frequency range : VCO */ //__HAL_RCC_PLL_VCORANGE(RCC_OscInitStruct->PLL.PLLVCOSEL) ; RCC->PLLCFGR &= ~RCC_PLLCFGR_PLL1VCOSEL; 

8. تشغيل فواصل الإخراج PLL1: P ، Q ، R

  /* Enable PLL System Clock output. */ // __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVP); //Bit 16 DIVP1EN: PLL1 DIVP divider output enable RCC->PLLCFGR |= RCC_PLLCFGR_DIVP1EN; /* Enable PLL1Q Clock output. */ //__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ); RCC->PLLCFGR |= RCC_PLLCFGR_DIVQ1EN; /* Enable PLL1R Clock output. */ // __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVR); RCC->PLLCFGR |= RCC_PLLCFGR_DIVR1EN; 

9. إدراج مقسم كسري.

  /* Enable PLL1FRACN . */ //__HAL_RCC_PLLFRACN_ENABLE(); RCC->PLLCFGR |= RCC_PLLCFGR_PLL1FRACEN; 

10. ابدأ PLL1 وانتظر الاستعداد

  /* Enable the main PLL. */ //__HAL_RCC_PLL_ENABLE(); RCC->CR |= RCC_CR_PLLON; while((RCC->CR & RCC_CR_PLL1RDY) == 0); 

تم تكوين PLL1 وتشغيله. الآن حدد مصدر تردد SYSCLK وقم بإعداد فواصل الناقل.

11. مقسم بواسطة 2 HPRE

  //RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; // MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider); //HPRE[3:0]: D1 domain AHB prescaler //1000: rcc_hclk3 = sys_d1cpre_ck / 2 RCC -> D1CFGR |= RCC_D1CFGR_HPRE_3; //1 RCC -> D1CFGR &= ~RCC_D1CFGR_HPRE_2; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_HPRE_1; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_HPRE_0; //0 

12. بدون تقسيم D1CPRE

  //RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; //MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1CPRE, RCC_ClkInitStruct->SYSCLKDivider); //D1CPRE[3:0]: D1 domain Core prescaler //0xxx: sys_ck not divided (default after reset) RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_3; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_2; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_1; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_0; //0 

13. تعيين PLL1 كمصدر SYSCLK وانتظر الاستعداد

  //RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); //SW[2:0]: System clock switch //011: PLL1 selected as system clock (pll1_p_ck) RCC->CFGR &= ~RCC_CFGR_SW_2; //0 RCC->CFGR |= RCC_CFGR_SW_1; //1 RCC->CFGR |= RCC_CFGR_SW_0; //1 while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL1); 

14. مقسم على 2 D1PPRE

  //D1PCLK1 Configuration //RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; //MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1PPRE, RCC_ClkInitStruct->APB3CLKDivider); //Bits 6:4 D1PPRE[2:0]: D1 domain APB3 prescaler //100: rcc_pclk3 = rcc_hclk3 / 2 RCC -> D1CFGR |= RCC_D1CFGR_D1PPRE_2; RCC -> D1CFGR &= ~RCC_D1CFGR_D1PPRE_1; RCC -> D1CFGR &= ~RCC_D1CFGR_D1PPRE_0; 

15. مقسم على 2 D2PPRE1

  //PCLK1 Configuration //RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; //MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE1, (RCC_ClkInitStruct->APB1CLKDivider)); //Bits 6:4 D2PPRE1[2:0]: D2 domain APB1 prescaler //100: rcc_pclk1 = rcc_hclk1 / 2 RCC -> D2CFGR |= RCC_D2CFGR_D2PPRE1_2; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE1_1; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE1_0; 

16. مقسم على 2 D2PPRE2

  //PCLK2 Configuration //RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; //MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE2, (RCC_ClkInitStruct->APB2CLKDivider)); //Bits 10:8 D2PPRE2[2:0]: D2 domain APB2 prescaler //100: rcc_pclk2 = rcc_hclk1 / 2 RCC -> D2CFGR |= RCC_D2CFGR_D2PPRE2_2; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE2_1; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE2_0; 

17. المقسم على 2 D3PPRE

  //D3PCLK1 Configuration //RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; //MODIFY_REG(RCC->D3CFGR, RCC_D3CFGR_D3PPRE, (RCC_ClkInitStruct->APB4CLKDivider) ); //Bits 6:4 D3PPRE[2:0]: D3 domain APB4 prescaler //100: rcc_pclk4 = rcc_hclk4 / 2 RCC -> D3CFGR |= RCC_D3CFGR_D3PPRE_2; RCC -> D3CFGR &= ~RCC_D3CFGR_D3PPRE_1; RCC -> D3CFGR &= ~RCC_D3CFGR_D3PPRE_0; 

من أجل التأكد من نجاح التكوين والبدء ، نستخدم إخراج متحكم MCO2. يجب أن يكون لهذا الإخراج تردد 26.666 ميجاهرتز مع مقسم إخراج 15.



عظيم. التردد موجود ، ثم يتم كل شيء بشكل صحيح.

Source: https://habr.com/ru/post/ar427435/


All Articles