HALおよびSPLなしのSTM32

かつて5年以上、32ビットマイクロコントローラーに関する情報を検索するとき、STM32のほとんどすべての例がSPL(Standard Peripherals Library)の使用に関係していることに気付きました。 ウィキペディアからの引用:

STM32F10x標準周辺機器ライブラリ(略してSTM32F10x SPL)は、STM32F10xファミリのマイクロコントローラ用にC言語でSTMicroelectronicsが作成したライブラリです。 マイクロコントローラーの周辺機器との作業を容易にする機能、構造、マクロが含まれています。


現在、STM32CUBEを使用してエントリのしきい値を下げ、開発を高速化することが提案されています。 STMウェブサイトからの引用:
以下を含むSTM32Cube組み込みソフトウェアライブラリ:



HALハードウェアアブストラクションレイヤー。標準化されたAPI呼び出しを介して、異なるSTM32デバイス間の移植性を実現します。

Low-Layer(LL)APIは、パフォーマンスと実行時の効率の両方のために設計された、軽量で最適化されたエキスパート向けのAPIセットです。

RTOS、USBライブラリ、ファイルシステム、TCP / IPスタック、タッチセンシングライブラリまたはグラフィックライブラリ(MCUシリーズに依存)などのミドルウェアコンポーネントのコレクション


私の意見では、ほとんどのプロジェクトでは、外部ライブラリは不要であり、標準のドキュメントを使用してマイクロコントローラレジスタへのアクセスを使用する方が簡単です。



マイクロコントローラのレジスタを使用することは、外部ライブラリのラッパーを使用するよりも複雑な方法であるという意見があります。 これが常にそうであるとは限らないことを示しようと思います。

コメント付きのレジスタ初期化の例。



周辺機器の初期化。



ポート



多くのプロジェクトでは、コントローラーの対応する脚をオンまたはオフにして、アナログ値を読み取るだけです。



ポートの有効化:1行のコード:



//  A************************* RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
      
      





ポートAの0ピンのアナログモード2行への変換:



  //PA0 - PA0/ADC1_ADC2_ADC3_IN0 // GPIO_Pin_0  A   GPIOA->MODER |= GPIO_MODER_MODER0_0; GPIOA->MODER |= GPIO_MODER_MODER0_1;
      
      





ポートAの2つのピンを終了モード(プッシュプル)1行にする:



 GPIOA->MODER |= GPIO_MODER_MODER2_0;
      
      





代替機能の使用もそれほど難しくありません。 多くの場合、ハーフブリッジコンバーターの制御にはマイクロコントローラーが使用されます。 これを行うには、対応するポートピンを相補PWM出力として設定します。



CH1カウンターTIM1(3ライン)のPWM出力としてのポートAの出力8の​​決定:



  //PA8/TIM1_CH1 // Alternate function mode GPIOA->MODER &= ~GPIO_MODER_MODER8_0; //0 GPIOA->MODER |= GPIO_MODER_MODER8_1; //1 //GPIO alternate function high register (GPIOx_AFRL) //AFR8[3:0] = 0001: AF1 GPIOA -> AFR[1] |= 0x00000001;
      
      





CH1N TIM1カウンターのPWM出力としてのポートBの出力13の決定:



 //PB13/TIM1_CH1N // Alternate function mode GPIOB->MODER &= ~GPIO_MODER_MODER13_0; //0 GPIOB->MODER |= GPIO_MODER_MODER13_1; //1 //GPIO alternate function high register (GPIOx_AFRL) //AFR13[3:0] = 0001: AF1 GPIOB -> AFR[1] |= 0x00100000;
      
      





論理的な質問:必要なレジスタとビットの指定はどこで入手できますか? 回答:3つのドキュメント(たとえば、746)。



1.リファレンスマニュアルSTM32F7.pdf

2. STM32F745xx.pdf

3. stm32f746xx.h



これら3つのファイルは、マイクロコントローラーのすべてのレジスターに正しくアクセスするのに十分です。



ADC



DMAモードで動作するためのADC初期化の例。 このモードでは、ADC2の4つのチャネルが自動的に円形に切り替わり、データをアレイに追加するDMAコントローラーにデータを送信します。



 void init_ADC1(void) { RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //   ADC1->CR2 |= ADC_CR2_ADON; //  ADC1->CR1 |= ADC_CR1_EOCIE; ADC1->CR1 |= ADC_CR1_SCAN; // Bit 8 SCAN: Scan mode ADC1->CR2 |= ADC_CR2_EOCS; //Bit 10 EOCS: End of conversion selection ADC1->CR2 |= ADC_CR2_DMA; //Bit 8 DMA: Direct memory access mode (for single ADC mode) ADC1->CR2 |= ADC_CR2_DDS; //Bit 9 DDS: DMA disable selection (for single ADC mode //Bits 23:20 L[3:0]: Regular channel sequence length (4) //0003: 4 conversion ADC1->SQR1 |= ADC_SQR1_L_0; //1 ADC1->SQR1 |= ADC_SQR1_L_1; //1 ADC1->SQR1 &= ~ADC_SQR1_L_2; //0 ADC1->SQR1 &= ~ADC_SQR1_L_3; //0 //Bits 4:0 SQ1[4:0]: 1st conversion in regular sequence PC0/ADC1_ADC2_ADC3_IN10 ADC1->SQR3 &= ~ADC_SQR3_SQ1_0; //0 ADC1->SQR3 |= ADC_SQR3_SQ1_1; //1 ADC1->SQR3 &= ~ADC_SQR3_SQ1_2; //0 ADC1->SQR3 |= ADC_SQR3_SQ1_3; //1 ADC1->SQR3 &= ~ADC_SQR3_SQ1_4; //0 //Bits 4:0 SQ2[4:0]: 2st conversion in regular sequence PC1/ADC1_ADC2_ADC3_IN11 ADC1->SQR3 |= ADC_SQR3_SQ2_0; //1 ADC1->SQR3 |= ADC_SQR3_SQ2_1; //1 ADC1->SQR3 &= ~ADC_SQR3_SQ2_2; //0 ADC1->SQR3 |= ADC_SQR3_SQ2_3; //1 ADC1->SQR3 &= ~ADC_SQR3_SQ2_4; //0 //Bits 4:0 SQ3[4:0]: 3st conversion in regular sequence PC2/ADC1_ADC2_ADC3_IN12 ADC1->SQR3 &= ~ADC_SQR3_SQ3_0; //0 ADC1->SQR3 &= ~ADC_SQR3_SQ3_1; //0 ADC1->SQR3 |= ADC_SQR3_SQ3_2; //1 ADC1->SQR3 |= ADC_SQR3_SQ3_3; //1 ADC1->SQR3 &= ~ADC_SQR3_SQ3_4; //0 //Bits 4:0 SQ4[4:0]: 4st conversion in regular sequence PC3/ADC1_ADC2_ADC3_IN13 ADC1->SQR3 |= ADC_SQR3_SQ4_0; //1 ADC1->SQR3 &= ~ADC_SQR3_SQ4_1; //0 ADC1->SQR3 |= ADC_SQR3_SQ4_2; //1 ADC1->SQR3 |= ADC_SQR3_SQ4_3; //1 ADC1->SQR3 &= ~ADC_SQR3_SQ4_4; //0 NVIC_EnableIRQ (ADC_IRQn); }
      
      





RAP



ADCからアレイへのデータ転送用の1つのDAPストリームの初期化(上記参照)



  // DMA2 RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; //Stream3 Channel 1 DMA2 -   ADC2_array 2 a //Bits 27:25 CHSEL[2:0]: Channel selection (1) DMA2_Stream3->CR |= DMA_SxCR_CHSEL_0; //1 DMA2_Stream3->CR &= ~DMA_SxCR_CHSEL_1; //0 DMA2_Stream3->CR &= ~DMA_SxCR_CHSEL_2; //0 //Bits 14:13 MSIZE[1:0]: Memory data size (16 bit) DMA2_Stream3->CR |= DMA_SxCR_MSIZE_0; //1 DMA2_Stream3->CR &= ~DMA_SxCR_MSIZE_1; //0 //Bits 12:11 PSIZE[1:0]: Peripheral data size (16 bit) DMA2_Stream3->CR |= DMA_SxCR_PSIZE_0; //1 DMA2_Stream3->CR &= ~DMA_SxCR_PSIZE_1; //0 //Bits 10 MINC: Memory increment mode DMA2_Stream3->CR |= DMA_SxCR_MINC; //Bits 7:6 DIR[1:0]: Data transfer direction (00: Peripheral-to-memory) DMA2_Stream3->CR &= ~DMA_SxCR_DIR_0; //0 DMA2_Stream3->CR &= ~DMA_SxCR_DIR_1; //0 //Bits 4 TCIE: Transfer complete interrupt enable DMA2_Stream3->CR |= DMA_SxCR_TCIE; //Bits 15:0 NDT[15:0]: Number of data items to transfer //1000 point x 4 channel DMA2_Stream3-> NDTR = 4000; //Bits 31:0 PAR[31:0]: Peripheral address DMA2_Stream3->PAR = (uint32_t) &(ADC2->DR); //Bits 31:0 M0A[31:0]: Memory 0 address DMA2_Stream3->M0AR = (uint32_t) ADC2_array; //Bits 0 EN: Stream enable / flag stream ready when read low DMA2_Stream3->CR |= DMA_SxCR_EN; NVIC_EnableIRQ (DMA2_Stream0_IRQn);
      
      





タイマー



3つのハーフブリッジ(3相インバーター)を制御するための相補的な12ビットPWM出力を備えたタイマー構成の例



  // TIM1 PWM RCC -> APB2ENR |= RCC_APB2ENR_TIM1EN; // TIM1 TIM1->CR1 |= TIM_CR1_CMS_0; //Center-aligned mode 1 TIM1->CR1 |= TIM_CR1_ARPE; //  // 8   4000 - 3000  //  108  TIM1->PSC = 8; TIM1->ARR = 4000; TIM1->CCR1 = 1000; //  TIM1->CCR2 = 1000; TIM1->CCR3 = 1000; TIM1->CCMR1 &= ~TIM_CCMR1_OC1M_0; TIM1->CCMR1 |= TIM_CCMR1_OC1M_1; TIM1->CCMR1 |= TIM_CCMR1_OC1M_2; //110: PWM mode 1 TIM1->CCMR1 &= ~TIM_CCMR1_OC2M_0; TIM1->CCMR1 |= TIM_CCMR1_OC2M_1; TIM1->CCMR1 |= TIM_CCMR1_OC2M_2; //110: PWM mode 1 TIM1->CCMR2 &= ~TIM_CCMR2_OC3M_0; TIM1->CCMR2 |= TIM_CCMR2_OC3M_1; TIM1->CCMR2 |= TIM_CCMR2_OC3M_2; //110: PWM mode 1 TIM1->CCER |= TIM_CCER_CC1E; // Capture/Compare 1 output enable TIM1->CCER |= TIM_CCER_CC1NE; // Capture/Compare 1 complementary output enable TIM1->CCER |= TIM_CCER_CC2E; // Capture/Compare 2 output enable TIM1->CCER |= TIM_CCER_CC2NE; // Capture/Compare 2 complementary output enable TIM1->CCER |= TIM_CCER_CC3E; // Capture/Compare 3 output enable TIM1->CCER |= TIM_CCER_CC3NE; // Capture/Compare 3 complementary output enable //DTG[7:0]: Dead-time generator setup 1 mks TIM1->BDTR |= TIM_BDTR_DTG_0; TIM1->BDTR |= TIM_BDTR_DTG_1; TIM1->BDTR |= TIM_BDTR_DTG_2; TIM1->BDTR |= TIM_BDTR_DTG_3; TIM1->BDTR |= TIM_BDTR_DTG_4; TIM1->BDTR |= TIM_BDTR_DTG_5; TIM1->BDTR |= TIM_BDTR_DTG_6; TIM1->BDTR |= TIM_BDTR_DTG_7; TIM1->DIER |= TIM_DIER_CC1IE; //Capture/Compare 1 interrupt enable //TIM1->DIER |= TIM_DIER_CC2IE; //Capture/Compare 2 interrupt enable //TIM1->DIER |= TIM_DIER_CC3IE; //Capture/Compare 3 interrupt enable TIM1->CR1 |= TIM_CR1_CEN; //Bit 0 CEN: Counter enable TIM1->BDTR |= TIM_BDTR_MOE; //MOE: Main output enable NVIC_EnableIRQ (TIM1_CC_IRQn); //   
      
      





時間割り込みを生成するためのタイマー構成の例。 通常、このタイマーからの割り込みは、インターフェイス上のデータを更新するために使用されます。 このモードでは、外部タイマー出力は使用されません。



  // TIM3 100  RCC -> APB1ENR |= RCC_APB1ENR_TIM3EN; //TIM3 Timer clock enable TIM3->CR1 |= TIM_CR1_CEN; //Bit 0 CEN: Counter enable TIM3->CR1 |= TIM_CR1_ARPE; //Bit 7 ARPE: Auto-reload preload enable TIM3->DIER |= TIM_DIER_UIE; //Bit 0 UIE: Update interrupt enable TIM3->PSC = 2000; TIM3->ARR = 5400; NVIC_EnableIRQ (TIM3_IRQn); //   
      
      





これらの構成ファイルは、ほとんど変更されずに長期間使用されます。 まだ103コントローラーで開始されましたが、現在は7番目のシリーズで使用されています:)



もちろん、ADC、タイマー、およびDAPの初期化はポートよりも少し複雑ですが、それも簡単なタスクです。

外部ライブラリ、よりコンパクトなコード、より予測可能なコントローラーの動作を使用しません。



All Articles