STM32CubeMX研究ノート(8)-ADCインターフェースの使用

1.ADCの概要

ADC(アナログ-デジタルコンバーター)、つまりアナログ-デジタルコンバーターは、連続的に変化するアナログ信号を個別のデジタル信号に変換し、デジタル信号処理と呼ばれる処理にデジタル回路を使用できます。

STM32f103シリーズには12ビットの精度の3つのADCがあり、各ADCには最大16の外部チャネルがあります。その中で、ADC1とADC2は両方とも16個の外部チャネルを持ち、ADC3はCPUピンのチャネル数によって異なります。通常、8個の外部チャネルがあります。各チャネルのA / D変換は、単一、連続、スキャン、または不連続モードで実行できます。ADCの結果は、16ビットデータレジスタに左寄せまたは右寄せで保存できます。アナログウォッチドッグ機能により、アプリケーションは入力電圧がユーザー定義の高/低しきい値を超えているかどうかを検出できます。ADC入力クロックは14MHzを超えてはなりません。周波数分割後にPCLK2によって生成されます。

2.ADCチャネルの選択

STM32のADCには最大18のチャネルがあり、そのうち16の外部チャネルはブロック図のADCx_IN0、ADCx_IN1 ... ADCx_IN5です。これらの16チャネルは、さまざまなIOポートに対応しています。どのIOポートがマニュアルに記載されています。その中で、ADC1 / 2/3には内部チャネルもあります。ADC1のチャネル16はチップ内の温度センサーに接続され、Vrefintはチャネル17に接続されています。ADC2のアナログチャネル16および17は、内部VSSに接続されています。ADC3のアナログチャネル9、14、15、16、および17は、内部VSSに接続されています。

3、ピン決定

開発ボードにはパッチスライディングレオスタットがあり、ピンはPC1で、ADC1のチャネル11に対応します。

4.新築

1. STM32CubeMXソフトウェアを開き、[新しいプロジェクト]をクリックします

2.MCUとパッケージを選択します

3.クロック
RCC設定を構成し、 HSE(外部高速クロック)を

選択し、水晶/セラミック共振子(水晶発振器/セラミック共振子)のクロック構成を選択し、システムクロックSYSCLKを72MHzに構成し、
HCLKの値を72に変更します。 Enterキーを押します。すべての構成を自動的に変更します

4.デバッグモード
設定することは非常に重要なステップです
設定しないと、最初のプログラミングプログラムの後でデバッガのSYS設定が認識されません。[シリアルワイヤとしてデバッグ]を選択してください。

5、ADC1

5.1パラメータ設定

Analog選択ADC1セット、および選択IN11チャンネル11

又は図の右側が見つかりました。PC1選択し、ピンをADC1_IN11

次のように特定の設定パラメータです。

  • ADCs_Common_Settings
    • モード
      Independent mod独立ADCモード、1つのADCを使用する場合は独立モード、2つのADCを使用する場合はデュアルモードデュアルモードで使用できる多くのサブディビジョンモードがあり、ADC_CR1:DUALMODビットが特別に構成されています。
  • ADC_Settings
    • データアライメント
      Right alignment変換結果データは右にアライメントされます。通常、右アライメントモードを選択します。
      Left alignment変換結果データは左揃えになります。
    • スキャン変換モード
      Disabledスキャンモードを無効にします。シングルチャネルAD変換の場合は、DISABLEを使用します。
      Enabledスキャンモードをオンにします。マルチチャネルAD変換の場合は、ENABLEを使用します。
    • 連続変換モード
      Disabled単一変換。変換を停止した後、変換を再開するには手動制御が必要です。
      Enabled自動連続変換。
    • DiscontinuousConvMode
      Disabled不連続モードは禁止されています。これは、消費電力を考慮する必要がある製品、つまり特定のイベントによってトリガーされたときに変換を開始する必要がある製品で必要です。
      Enabled間欠モードをオンにします。
  • ADC_Regular_ConversionMode
    Enable Regular Conversions通常の変換を有効にするかどうか。
    Number Of ConversionADC変換チャネルの数。必要な数だけ書き込みます。
    External Trigger Conversion Source外部トリガーの選択。これには複数のオプションがあり、通常はソフトウェアトリガーが使用されます。
  • ランク
    ChannelADC変換チャネルの
    Sampling Timeサンプリング周期の選択サンプリング周期が短いほど、ADC変換データの出力周期は短くなりますが、データの精度は低くなります。サンプリング周期が長いほど、ADC変換データの出力周期が長くなり、データの精度が高くなります。 。
  • ADC_Injected_ConversionMode
    Enable Injected Conversionsインジェクション変換を有効にするかどうか。インジェクションチャネルは、通常のチャネルが存在する場合にのみ表示されます。
  • WatchDog
    Enable Analog WatchDog Modeアナログウォッチドッグ割り込みを有効にするかどうか。ADCによって変換されたアナログ電圧が下限しきい値よりも低いか、上限しきい値よりも高い場合、割り込みが生成されます。

5.2NVICの構成

ADC割り込みを有効にする

5.3ADCクロック構成

ADC変換時間は、ADC入力クロックとサンプリング時間に関連しています。
式は次のとおりです。Tconv=サンプリング時間+12.5サイクルADCLK = 14MHZ(最高)でサンプリング時間が1.5サイクル(最速)に設定されている場合、合計変換時間(最短)Tconv = 1.5サイクル+12.5サイクル= 14サイクル= 1us。
通常、PCLK2 = 72Mに設定します。ADCプリスケーラで最大周波数に分周できるクロックは12M、サンプリング周期を1.5サイクル設定し、最短変換時間を1.17usと計算することだけです。これが最も一般的に使用されます。

5.4コードの生成



アプリケーション開発環境のパスアイテム名とアイテム入力の選択IDEMDK-ARM V5

各ペリフェラルはフックではなく個別の’.c/.h’ファイルを生成します
:すべての初期化コードはmain.cで生成され
ますチェック済み:初期化コードファイルは関連するペリフェラルで生成されます。たとえば、GPIO初期化コードはgpio.cで生成されます。

[コードを生成]をクリックしてコードを生成します

6つの独立モードシングルチャネル取得割り込みモード

单通道采集适用 AD 转换完成中断,在中断服务函数中读取数据,不使用 DMA 传输,在多通道采集时才使用 DMA 传输。

6.1割り込みコールバック関数を変更する

stm32f1xx_it.c割り込みサービスルーチンファイルを開き、ADC1_2_IRQHandler()
ADC割り込みハンドラと呼ばれるADC1割り込みサービスルーチン割り込みサービス関数を見つけます。HAL_ADC_IRQHandler()

stm32f1xx_hal_adc.cファイルを開き、ADC割り込みハンドラプロトタイプを見つけますHAL_ADC_IRQHandler()。その主な役割は、どのADCが割り込みを生成するかを決定し、割り込みフラグをクリアしてから、割り込みコールバック関数を呼び出すことHAL_ADC_ConvCpltCallback()です。

/ *注:この関数は変更しないでください。コールバックが必要な場合は
、HAL_GPIO_EXTI_Callbackをユーザーファイルに実装できます
* /
この関数は変更しないでください。コールバック関数を使用する必要がある場合は、関数を再実装してください。ユーザーファイル内。

HAL_ADC_ConvCpltCallback()公式プロンプトによる__weakと、弱められたフラグである関数を再定義する必要があります。これを持つ関数は弱められた関数です。つまり、他の場所でまったく同じ名前とパラメーターを持つ関数を記述でき、コンパイラーは無視します。この関数。代わりにUNUSED(hadc)、作成した関数を実行します。これはエラー防止の定義です。渡されたADC番号が処理を行わない場合、コンパイラは警告を報告しません。実際、開発中に割り込みサービス関数について気にする必要はありません。割り込みコールバック関数を見つけて書き直すだけで済みます。このコールバック関数には、ここには反映されていないもう1つの非常に便利な側面があります。複数の割り込みが有効になっている場合、STM32CubeMXは複数の割り込みのサービス関数を自動的に編成し、コールバック関数を呼び出します。つまり、割り込みの数に関係なく、コールバック関数を書き直して着信タイマー番号を判断するだけで済みます。

次にstm32f1xx_it.c、このドキュメントの最後に追加しますHAL_ADC_ConvCpltCallback()

/* USER CODE BEGIN EV */
extern __IO uint32_t ADC_ConvertedValue;
/* USER CODE END EV */

/* USER CODE BEGIN 1 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    
    
    ADC_ConvertedValue = HAL_ADC_GetValue(hadc);
}
/* USER CODE END 1 */

割り込みコールバック関数でデータを読み取りますADC_ConvertedValueデータはの変数格納されます

6.2グローバル変数を追加する

main.cで関連する変数を定義します。

// ADC转换值
__IO uint32_t ADC_ConvertedValue;
// 用于保存转换计算后的电压值 	 
float ADC_Vol;

6.3ADC割り込み開始機能の追加

main.cで、whileループの前とADCの初期化後に、ADC割り込みイネーブル関数を追加します。これにより、データを初めて受信したときに割り込みがトリガーされます。

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    
    
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
  HAL_ADCEx_Calibration_Start(&hadc1);    //AD校准
  HAL_ADC_Start_IT(&hadc1); //开启ADC中断转换
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

6.4電圧値変換を追加

アナログ電圧をADCで変換した後は12ビットのデジタル値ですが、シリアルポートから16進数で出力すると読みやすさが比較的悪くなりますので、デジタル電圧をアナログ電圧に変換する必要がある場合があります。 、これは実際のアナログ電圧(マルチメーターで測定)を比較して、変換が正確かどうかを確認することもできます。
回路図を設計するとき、通常、ADC入力電圧範囲を次のように設定します0~3.3v。ADCは12ビットであるため、12ビットのフルスケールは3.3Vに対応し、12ビットのフルスケールはデジタル値に対応します。 2 ^ 12。値0は0Vに対応します。変換された値がXで、Xに対応するアナログ電圧がYの場合、式が確立されます:2 ^ 12 / 3.3 = X / Y、=> Y =(3.3 * X)/ 2 ^ 12

シリアルポート印刷機能ビューSTM32CubeMXスタディノート(6)-USARTシリアルポートの使用

/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
      ADC_Vol =(float) ADC_ConvertedValue/4096*3.3; // 读取转换的AD倿
      printf("The current AD value = 0x%04X \r\n", ADC_ConvertedValue); 
      printf("The current AD value = %f V \r\n\r\n",ADC_Vol); //实际电压倿
      HAL_Delay(1000); 
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

6.5HALライブラリと標準ライブラリコードの比較

STM32CubeMXは、HALライブラリによって生成されたコードを使用します。

__IO uint32_t ADC_ConvertedValue;

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC1_Init(void)
{
    
    

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {
    
    0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_11;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */
}

/**
  * @brief This function handles ADC1 and ADC2 global interrupts.
  */
void ADC1_2_IRQHandler(void)
{
    
    
  /* USER CODE BEGIN ADC1_2_IRQn 0 */

  /* USER CODE END ADC1_2_IRQn 0 */
  HAL_ADC_IRQHandler(&hadc1);
  /* USER CODE BEGIN ADC1_2_IRQn 1 */

  /* USER CODE END ADC1_2_IRQn 1 */
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    
    
    ADC_ConvertedValue = HAL_ADC_GetValue(hadc);
}

HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start_IT(&hadc1);

STM32標準ライブラリコードを使用します。

__IO uint16_t ADC_ConvertedValue;

/**
  * @brief  ADC GPIO 初始化
  * @param  无
  * @retval 无
  */
static void ADCx_GPIO_Config(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 打开 ADC IO端口时钟
	ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
	
	// 配置 ADC IO 引脚模式
	// 必须为模拟输入
	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	
	// 初始化 ADC IO
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);				
}

/**
  * @brief  配置ADC工作模式
  * @param  无
  * @retval 无
  */
static void ADCx_Mode_Config(void)
{
    
    
	ADC_InitTypeDef ADC_InitStructure;	

	// 打开ADC时钟
	ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
	
	// ADC 模式配置
	// 只使用一个ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	
	// 禁止扫描模式,多通道才要,单通道不需要
	ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 

	// 连续转换模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

	// 不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

	// 转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	
	// 转换通道1个
	ADC_InitStructure.ADC_NbrOfChannel = 1;	
		
	// 初始化ADC
	ADC_Init(ADCx, &ADC_InitStructure);
	
	// 配置ADC时钟为PCLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 
	
	// 配置 ADC 通道转换顺序和采样时间
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, 
	                         ADC_SampleTime_55Cycles5);
	
	// ADC 转换结束产生中断,在中断服务程序中读取转换值
	ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
	
	// 开启ADC ,并开始转换
	ADC_Cmd(ADCx, ENABLE);
	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx));
	
	// ADC开始校准
	ADC_StartCalibration(ADCx);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx));
	
	// 由于没有采用外部触发,所以使用软件触发ADC转换 
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}

static void ADC_NVIC_Config(void)
{
    
    
  NVIC_InitTypeDef NVIC_InitStructure;
  // 优先级分组
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  // 配置中断优先级
  NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/**
  * @brief  ADC初始化
  * @param  无
  * @retval 无
  */
void ADCx_Init(void)
{
    
    
	ADCx_GPIO_Config();
	ADCx_Mode_Config();
	ADC_NVIC_Config();
}

void ADC_IRQHandler(void)
{
    
    	
	if (ADC_GetITStatus(ADCx,ADC_IT_EOC)==SET) 
	{
    
    
		// 读取ADC的转换值
		ADC_ConvertedValue = ADC_GetConversionValue(ADCx);
	}
	ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
}

MX_ADC1_Init();対応するADCx_GPIO_Config();ADCx_Mode_Config();ADC_NVIC_Config();
HAL_ADC_Init(&hadc1)対応するADC_Init(ADCx, &ADC_InitStructure)
HAL_ADCEx_Calibration_Start(&hadc1);対応ADC_StartCalibration(ADCx);
HAL_ADC_Start_IT(&hadc1);する対応ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
HAL_ADC_GetValue(hadc);する対応するADC_GetConversionValue(ADCx);

七、注意が必要な事項

追加するユーザーコードUSER CODE BEGIN NUSER CODE END Nその間に追加するユーザーコード。それ以外の場合は、STM32CubeMXがコードを再生成した後、次に使用すると削除されます。


2021年1月19日にLeungによって書かれました

•リファレンス:STM32CubeMXシリーズチュートリアル7:アナログ-デジタル変換(ADC)
    「組み込み-STM32開発ガイド」パート2の基本-第8章アナログ入力および出力-ADC(HALライブラリ)

おすすめ

転載: blog.csdn.net/qq_36347513/article/details/112850329