STM32----摸石头过河系列(六)
今天了解一下ADC,stm32中的模數轉換利用的是逐次逼近的方法,這個當時在考研時特別熟,現在又忘了,又去問了一下萬能的百度。先是多少了解一下這個轉換過程,在32的開發過程中用不到,但畢竟從事這個的,別顯的太外行哈!現在拿一個四位的舉個例子。收到一個輸入的電壓,值設為X,第一步將四位的最高位置為1然后其他的全為零,設這個值為Y。那么第一次時二進制Y = 1000即十進制Y=8,若Y < X 則將第二位置1,此時Y = 12;若Y< X則將第一位置0,第二位置1,此時Y=4;按照這個過程得到四位的值,從而得到Y值。得到接近真實值的測量值。這就是逐次逼近的原理,數電學的不錯的可以去看看那個框圖,就是JK觸發器和D觸發器的組合。分析一下還是很有意思的。
話不多說進入正題,今天講的ADC就像用過的串口和DMA類似,自己配置好以后,就爽歪歪了。這次的實驗呢!是利用DMA將ADC中的數據讀取到內存中的一個變量中,然后再通過串口發送到上位機的串口調試工具中,就可以看到某個固定端口所測量的電壓值。
首先看一下DMA的配置(dma.c):
#include"dma.h"int16_t ADC_Value;void DMA1_Config(void) {DMA_InitTypeDef dma_struct;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);DMA_DeInit(DMA1_Channel1);dma_struct.DMA_PeripheralBaseAddr = ADC1_Address;dma_struct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;dma_struct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;dma_struct.DMA_MemoryBaseAddr = (u32)&ADC_Value;dma_struct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;dma_struct.DMA_MemoryInc = DMA_MemoryInc_Disable;dma_struct.DMA_BufferSize = 1;dma_struct.DMA_DIR = DMA_DIR_PeripheralSRC;dma_struct.DMA_M2M = DMA_M2M_Disable;dma_struct.DMA_Priority = DMA_Priority_High;dma_struct.DMA_Mode = DMA_Mode_Circular;DMA_Init(DMA1_Channel1,&dma_struct);DMA_Cmd(DMA1_Channel1,ENABLE); }這與之前的DMA配置大致相同,有一些細節的不同,來看一下。DMA_DeInit()這個函數用來開啟某個DMA通道。ADC1_Address為ADC的地址,DMA將從這里得到數據,這個在后面的頭文件的展示中將可以看到。ADC_Value變量為DMA將數據存放的位置,利用&符號取得該變量的地址。這個配置過程就是DMA將數據從ADC轉移到內存中國ADC_Value這個變量中。
來看一下定義DMA的頭文件(dma.h):
#ifndef __DMA_H #define __DMA_H#include"stm32f10x.h" #include"stm32f10x_gpio.h" #include"stm32f10x_rcc.h" #include"stm32f10x_dma.h"#define ADC1_Address ((u32)0x40012400+0x4c)void DMA1_Config(void);#endif下面這次的大BOSS將要登場了。直接來看一下如何一步步攻陷這個ADC的:
下面來具體看看ADC的配置代碼(adc.c):
void ADC1_Config(void) {ADC_InitTypeDef adc_struct;GPIO_InitTypeDef gpio_struct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_ADC1,ENABLE);gpio_struct.GPIO_Pin = GPIO_Pin_1;gpio_struct.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOC,&gpio_struct);adc_struct.ADC_Mode = ADC_Mode_Independent;adc_struct.ADC_ScanConvMode = DISABLE;adc_struct.ADC_DataAlign = ADC_DataAlign_Right;adc_struct.ADC_ContinuousConvMode = ENABLE;adc_struct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部觸發adc_struct.ADC_NbrOfChannel = 1;ADC_Init(ADC1,&adc_struct);RCC_ADCCLKConfig(RCC_PCLK2_Div8);ADC_RegularChannelConfig(ADC1,ADC_Channel_11,1,ADC_SampleTime_55Cycles5);ADC_DMACmd(ADC1,ENABLE);ADC_Cmd(ADC1,ENABLE);//以下是照本宣科了ADC_ResetCalibration(ADC1);while(ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);while(ADC_GetCalibrationStatus(ADC1));ADC_SoftwareStartConvCmd(ADC1,ENABLE);}這個配置簡單應用的配置,ADC可以多通道同時采集等復雜的操作,先來一個小實驗,測試使用。
最后來看看,程序的心臟吧!主函數(main.c):
#include"led.h" #include"usart.h" #include"dma.h" #include"adc.h"extern int16_t ADC_Value; float value;void Delay(uint32_t x) {while(x--); }int main(void) {GPIO_LED_Config();USART1_Config();DMA1_Config();ADC1_Config();while(1){value = (float)ADC_Value/4096*3.3;printf("the value = %f V \r\n ",value);printf("\r\n the current AD value = %fV\r\n",value);Delay(0xffffee);} }extern引用外部的變量,在本文件中使用。在主函數主要說一個公式value = (float)ADC_Value/4096*3.3;用這個來計算得到實際的測量值。這個公式是固定的,至于原理可以查看相關的。首次,使用不要著急慢慢的一步一步來,成功的喜悅你將會品嘗到。
總結
以上是生活随笔為你收集整理的STM32----摸石头过河系列(六)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NAR | 陈加余/陈亮合作建立R-lo
- 下一篇: C++ 私有构造函数的作用