ADC模數(shù)轉(zhuǎn)換器電路設(shè)計

2023-07-27 16:26:11 來源:編程外星人

在我們的控制系統(tǒng)中需要使用一個"模數(shù)轉(zhuǎn)換"的功能。所謂“模數(shù)轉(zhuǎn)換”,就是將模擬量轉(zhuǎn)換為數(shù)字量,也就是我們經(jīng)常說的ADC采集,其中ADC的全稱為:“Analogto Digital Converter”。我們的電路設(shè)計中,采用的電源是3S鋰電池,其電壓最大值為12.6v,最小值為11.1v。所以我們通過了一路ADC采集到電壓的模擬量將其轉(zhuǎn)為數(shù)字量。我們先來看一下電路設(shè)計:


(相關(guān)資料圖)

我們可以看到,電源輸出VIN通過R6和R5兩個分壓電阻,將其線性的降壓到ADC1_CH0電路中,并接到PA0引腳上。我們可以通過計算得到以下內(nèi)容:

也就是說,我們通過了這個兩個電阻分壓的線性降壓電路將11.1v到12.6v的電壓降低到2.868v到3.256v。為什么這個做呢?原因是STM32的AD轉(zhuǎn)換引腳能夠接受的模擬電壓范圍為的最大值是3v。當(dāng)我們通過STM32的ADC采集將降壓后的電源轉(zhuǎn)為數(shù)字信號,再通過程序還原成原始的電壓數(shù)值(線性降壓之前的電壓),我們就可以得到電源電壓了。假設(shè)ADC采集到的電壓為v,于是我們可以得到電源電壓V的值的計算方法為:

接下來,我們來編寫STM32程序,通過ADC采集到我們的電源電壓:

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //配置GPIOA時鐘總線RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); //停用ADC1,以便下面進(jìn)行ADC1的配置GPIO_InitTypeDef GPIO_InitStructure;              //配置PA0作為ADC1的CH0的引腳GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOA, &GPIO_InitStructure);ADC_Cmd(ADC1, DISABLE);    //禁用ADC1ADC_DeInit();        //ADC1重定義ADC_CommonInitTypeDef ADC_CommonInitStructure;ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //獨立模式ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles; //兩個采樣階段之間的延遲ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA使能ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8; //預(yù)分頻8分頻ADC_CommonInit(&ADC_CommonInitStructure);ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模數(shù)轉(zhuǎn)換工作在單通道模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模數(shù)轉(zhuǎn)換工作在單次轉(zhuǎn)換模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None; //轉(zhuǎn)換由軟件而不是外部觸發(fā)啟動ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC數(shù)據(jù)右對齊ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;ADC_InitStructure.ADC_NbrOfConversion = 16; //順序進(jìn)行轉(zhuǎn)換通道的數(shù)目ADC_Init(ADC1, &ADC_InitStructure); //初始化外設(shè)ADC寄存器ADC_Cmd(ADC1, ENABLE); //使能指定的ADC

這樣我們就完成了ADC1的CH0的配置工作。之后我們還需要編寫一個函數(shù)用于讀取ADC1中CH0的數(shù)字信號值:

uint16_t adc_get(uint8_t ch){  //設(shè)置指定ADC的規(guī)則組通道,一個序列,采樣時間  ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_144Cycles);  ADC_SoftwareStartConv(ADC1);  while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))  {  }  //返回最近一次ADC1規(guī)則組的轉(zhuǎn)換結(jié)果  return ADC_GetConversionValue(ADC1); }

最后,我們通過在main函數(shù)中對ADC1中的CH0進(jìn)行配置,并在主循環(huán)中讀取電源電壓信息:

init_adc();uart_init();while (1){  uint16_t v = adc_get(0);  uart_write(v & 0xff);  uart_write((v > > 8) & 0xff);  uart_write(0x0);  uart_write(0x0);  // ...}

當(dāng)我們通過調(diào)用adc_get(0)函數(shù)得到采集電壓v之后,再通過uart_write(v)函數(shù)將電壓值發(fā)送到串口當(dāng)中方便我們觀察。注意,其中串口功能的配置與使用我們將下一講中來學(xué)習(xí),這里不再贅述。讀者只需要了解得到電壓v之后如何計算出電源電壓即可。例如我們從串口中得到的數(shù)據(jù)如下:

實際上,我們得到了很多組數(shù)據(jù),它們之間會存在一些小的差別,但并不很大,我們以上圖中的D0 FD這一組數(shù)據(jù)為例,16進(jìn)制數(shù)據(jù)為0xFDD0,轉(zhuǎn)為10進(jìn)制為64976,除以16位ADC分辨率65535(16進(jìn)制為0xFFFF)得到結(jié)果為0.991470207,再乘以3.256,得到3.228226993v,最后轉(zhuǎn)換為電源電壓3.228226993v * 387 / 100 = 12.493238463v,保留3位小數(shù)得到12.493v。于是我們就得到了當(dāng)前電源電壓為12.493v。

我們,可以在電源電壓接近11v時再進(jìn)行一次采集和計算,我們采集到的數(shù)據(jù)為50 DF:

通過上述方法計算得到電源電壓為:

16進(jìn)制轉(zhuǎn)10進(jìn)制: 0xDF50 = 57168除以16通道分辨率: 57168 / 65535 = 0.872327764乘以電路中分壓值3.256v: 0.872327764 × 3.256 = 2.840299199轉(zhuǎn)為實際電源電壓: 2.840299199 × 387 ÷ 100 = 10.992

最后,我們就得到了電源電壓為10.992v約等于11v

于是,我們通過程序來計算上面的內(nèi)容:

這樣我們就完成了通過STM32采集電源的電壓,方便我們以后實時查看小車的電源情況。

標(biāo)簽:

上一篇:STM32 USART串口的應(yīng)用 STM32中斷系統(tǒng)專題講解
下一篇:最后一頁