AD模數(shù)轉(zhuǎn)換器
ADC簡(jiǎn)介
- ADC(Analog-Digtal Converter) 模擬-數(shù)字轉(zhuǎn)換器
- ADC可以將引腳上連續(xù)變化的模擬電壓轉(zhuǎn)換為內(nèi)存中存儲(chǔ)的數(shù)字變量, 建立模擬電路到數(shù)字電路的橋梁
- 12位逐次逼近型ADC, 1us轉(zhuǎn)換時(shí)間
- 輸入電壓范圍: 0~3.3V, 轉(zhuǎn)換結(jié)果范圍: 0~4095
- 18個(gè)輸入通道, 可測(cè)量16個(gè)外部和2個(gè)內(nèi)部信號(hào)源
- 規(guī)則組和注入組兩個(gè)轉(zhuǎn)換單元
- 模擬看門(mén)狗自動(dòng)監(jiān)測(cè)輸入電壓范圍
- STM32F103C8T6 ADC資源: ADC1、ADC2, 10個(gè)外部輸入通道
逐次逼近型ADC
- IN0~IN7是八個(gè)輸入通道
- 通過(guò)配置ADDA~ADDC可以選擇一個(gè)通道作為信號(hào)輸入
- 通過(guò)比較器, DAC逐漸逼近輸入信號(hào), DAC的值最終與輸入信號(hào)十分接近
ADC框圖
ADC基本結(jié)構(gòu)
輸入通道
通道 | ADC1 | ADC2 | ADC3 |
---|---|---|---|
通道0 | PA0 | PA0 | PA0 |
通道1 | PA1 | PA1 | PA1 |
通道2 | PA2 | PA2 | PA2 |
通道3 | PA3 | PA3 | PA3 |
通道4 | PA4 | PA4 | PF6 |
通道5 | PA5 | PA5 | PF7 |
通道6 | PA6 | PA6 | PF8 |
通道7 | PA7 | PA7 | PF9 |
通道8 | PB0 | PB0 | PF10 |
通道9 | PB1 | PB1 | |
通道10 | PC0 | PC0 | PC0 |
通道11 | PC1 | PC1 | PC1 |
通道12 | PC2 | PC2 | PC2 |
通道13 | PC3 | PC3 | PC3 |
通道14 | PC4 | PC4 | |
通道15 | PC5 | PC5 | |
通道16 | 溫度傳感器 | ||
通道17 | 內(nèi)部參考電壓 |
轉(zhuǎn)換模式
- 單次轉(zhuǎn)換, 非掃描模式
- 連續(xù)轉(zhuǎn)換, 非掃描模式
- 單次轉(zhuǎn)換, 掃描模式
- 連續(xù)轉(zhuǎn)換, 掃描模式
觸發(fā)控制
數(shù)據(jù)對(duì)齊
- 數(shù)據(jù)右對(duì)齊:
- 數(shù)據(jù)左對(duì)齊:
轉(zhuǎn)換時(shí)間
-
AD轉(zhuǎn)換的步驟: 采樣, 保持, 量化, 編碼
-
STM32 ADC的總轉(zhuǎn)換時(shí)間為:
? Tconv = 采樣時(shí)間 + 12.5個(gè)ADC周期
-
例如: 當(dāng)ADCCLK = 14MHz, 采樣時(shí)間為1.5個(gè)ADC周期
? Tconv = 1.5 + 12.5 = 14個(gè)ADC周期 = 1us
校準(zhǔn)
- ADC有一個(gè)內(nèi)置自校準(zhǔn)模式。校準(zhǔn)可大幅減小因內(nèi)部電容器組的變化而造成的精準(zhǔn)度誤差。校準(zhǔn)期間, 在每個(gè)電容器上都會(huì)計(jì)算出一個(gè)修正碼(數(shù)字值), 這個(gè)碼用于消除在隨后的轉(zhuǎn)換中每個(gè)電容器上產(chǎn)生的誤差
- 建議在每次上電后執(zhí)行一次校準(zhǔn)
- 啟動(dòng)校準(zhǔn)前, ADC必須處于關(guān)電狀態(tài)超過(guò)至少兩個(gè)ADC時(shí)鐘周期
硬件電路
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-766225.html
案例1: ADC單通道
配置ADC轉(zhuǎn)換
void AD_Init(void)
{
// RCC使能時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 12MHz
// 配置GPIO口
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 選擇規(guī)則通道
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
// 配置ADC轉(zhuǎn)換器
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 單次轉(zhuǎn)換或者連續(xù)轉(zhuǎn)換
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 數(shù)據(jù)對(duì)齊模式
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC模式, 單獨(dú)還是交叉
ADC_InitStructure.ADC_NbrOfChannel = 1; // 掃描的通道數(shù)
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 掃描模式或者非掃描模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 觸發(fā)控制
ADC_Init(ADC1, &ADC_InitStructure);
// 開(kāi)啟ADC功能
ADC_Cmd(ADC1, ENABLE);
// ADC校準(zhǔn)
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1) == SET); // 已初始化為零
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
RCC_ADCCLKConfig
/**
* @brief Configures the ADC clock (ADCCLK).
* @param RCC_PCLK2: defines the ADC clock divider. This clock is derived from
* the APB2 clock (PCLK2).
* This parameter can be one of the following values:
* @arg RCC_PCLK2_Div2: ADC clock = PCLK2/2
* @arg RCC_PCLK2_Div4: ADC clock = PCLK2/4
* @arg RCC_PCLK2_Div6: ADC clock = PCLK2/6
* @arg RCC_PCLK2_Div8: ADC clock = PCLK2/8
* @retval None
*/
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2)
ADC_ContinuousConvMode
*!< Specifies whether the conversion is performed in
Continuous or Single mode.
This parameter can be set to ENABLE or DISABLE. */
ADC_DataAlign
#define ADC_DataAlign_Right ((uint32_t)0x00000000)
#define ADC_DataAlign_Left ((uint32_t)0x00000800)
ADC_Mode
#define ADC_Mode_Independent ((uint32_t)0x00000000)
#define ADC_Mode_RegInjecSimult ((uint32_t)0x00010000)
#define ADC_Mode_RegSimult_AlterTrig ((uint32_t)0x00020000)
#define ADC_Mode_InjecSimult_FastInterl ((uint32_t)0x00030000)
#define ADC_Mode_InjecSimult_SlowInterl ((uint32_t)0x00040000)
#define ADC_Mode_InjecSimult ((uint32_t)0x00050000)
#define ADC_Mode_RegSimult ((uint32_t)0x00060000)
#define ADC_Mode_FastInterl ((uint32_t)0x00070000)
#define ADC_Mode_SlowInterl ((uint32_t)0x00080000)
#define ADC_Mode_AlterTrig ((uint32_t)0x00090000)
ADC_NbrOfChannel
/*!< Specifies the number of ADC channels that will be converted
using the sequencer for regular channel group.
This parameter must range from 1 to 16. */
ADC_ScanConvMode
/*!< Specifies whether the conversion is performed in
Scan (multichannels) or Single (one channel) mode.
This parameter can be set to ENABLE or DISABLE */
ADC_ExternalTrigConv
#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 only */
整體代碼:
ADC.c
#include "stm32f10x.h"
/*
初始化ADC
*/
void AD_Init(void)
{
// RCC使能時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 12MHz
// 配置GPIO口
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 選擇規(guī)則通道
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
// 配置ADC轉(zhuǎn)換器
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 單次轉(zhuǎn)換或者連續(xù)轉(zhuǎn)換
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 數(shù)據(jù)對(duì)齊模式
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC模式, 單獨(dú)還是交叉
ADC_InitStructure.ADC_NbrOfChannel = 1; // 掃描的通道數(shù)
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 掃描模式或者非掃描模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 觸發(fā)控制
ADC_Init(ADC1, &ADC_InitStructure);
// 開(kāi)啟ADC功能
ADC_Cmd(ADC1, ENABLE);
// ADC校準(zhǔn)
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1) == SET); // 已初始化為零
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/*
獲取ADC模塊轉(zhuǎn)換的值
*/
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 軟件觸發(fā)
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待轉(zhuǎn)換完畢
return ADC_GetConversionValue(ADC1);
}
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "OLED.h"
#include "ADC.h"
// ADC單通道
// 2023年3月25日19:12:09
uint16_t ADValue;
float volatge;
int main(void)
{
OLED_Init();
AD_Init();
OLED_ShowString(1, 1, "ADValue:");
OLED_ShowString(2, 1, "Volatge:0.00V");
while(1)
{
ADValue = AD_GetValue();
volatge = (float)ADValue / 4095 * 3.3;
OLED_ShowNum(1, 9, ADValue, 4);
OLED_ShowNum(2, 9, volatge, 1);
OLED_ShowNum(2, 11, (uint16_t)(volatge * 100)% 100, 2);
Delay_ms(100);
}
}
案例2: ADC多通道
整體代碼
ADC.c
#include "stm32f10x.h"
/*
初始化ADC
*/
void AD_Init(void)
{
// RCC使能時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 12MHz
// 配置GPIO口
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置ADC轉(zhuǎn)換器
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 單次轉(zhuǎn)換或者連續(xù)轉(zhuǎn)換
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 數(shù)據(jù)對(duì)齊模式
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC模式, 單獨(dú)還是交叉
ADC_InitStructure.ADC_NbrOfChannel = 1; // 掃描的通道數(shù)
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 掃描模式或者非掃描模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 觸發(fā)控制
ADC_Init(ADC1, &ADC_InitStructure);
// 開(kāi)啟ADC功能
ADC_Cmd(ADC1, ENABLE);
// ADC校準(zhǔn)
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1) == SET); // 已初始化為零
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/*
獲取ADC模塊轉(zhuǎn)換的值
*/
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 軟件觸發(fā)
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待轉(zhuǎn)換完畢
return ADC_GetConversionValue(ADC1);
}
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "OLED.h"
#include "ADC.h"
// ADC多通道
// 2023年3月25日20:42:57
uint16_t AD0, AD1, AD2, AD3;
float volatge;
int main(void)
{
OLED_Init();
AD_Init();
OLED_ShowString(1, 1, "AD0:");
OLED_ShowString(2, 1, "AD1:");
OLED_ShowString(3, 1, "AD2:");
OLED_ShowString(4, 1, "AD3:");
while(1)
{
AD0 = AD_GetValue(ADC_Channel_0);
AD1 = AD_GetValue(ADC_Channel_1);
AD2 = AD_GetValue(ADC_Channel_2);
AD3 = AD_GetValue(ADC_Channel_3);
OLED_ShowNum(1, 5, AD0, 4);
OLED_ShowNum(2, 5, AD1, 4);
OLED_ShowNum(3, 5, AD2, 4);
OLED_ShowNum(4, 5, AD3, 4);
Delay_ms(100);
}
}
參考資料
【STM32入門(mén)教程-2023持續(xù)更新中】 https://www.bilibili.com/video/BV1th411z7sn/?p=22&share_source=copy_web&vd_source=ee06a25b3dfb2900ab707b01fdff6667文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-766225.html
到了這里,關(guān)于STM32入門(mén)筆記08_ADC模數(shù)轉(zhuǎn)換器+案例: ADC單通道&ADC多通道的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!