自己的网站上面写文章,没有读者,没有交流,所以想另外找个地方同步更新博文,怎奈21ic不能兼容我的网站格式,所以就找到这了,哈哈,希望在这里会有所收获。
一、GPIO配置
/**
* @brief 使能ADC1和DMA1的时钟,初始化PC.01
* @param 无
* @retval 无
*/
static void ADC1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable DMA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable ADC1 and GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
/* Configure PC.01 as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);// PC1,因为是输入模式,所以不用设置速率
}
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
因为DMA1挂载于AHB总线上,所以开启AHB时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
开启ADC1、GPIOC的时钟,它们挂载于APB2总线上。
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);// PC1,因为是输入模式,所以不用设置速率
引脚选为GPIOC->Pin1脚,IO模式为模拟输入。
因为PC1为ADC1的第11输入通道,而我们选择这个通道来实现ADC功能,所以要选中PC1引脚。
由上图可知,不管是使用ADC还是DAC功能,其所在引脚均应配置为模拟模式。所以我们将PC1配置为模拟输入。
最后调用库函数GPIO_Init()初始化GPIOC->Pin1脚,IO口配置完毕。
二、ADC配置
/**
* @brief 配置ADC1的工作模式为DMA模式
* @param 无
* @retval 无
*/
static void ADC1_Mode_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* DMA channel1 configuration */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;//内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址固定
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //内存地址固定
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//半字
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环传输
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC1 configuration */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立ADC模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE ; //禁止扫描模式,扫描模式用于多通道采集
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换模式,即不停地进行ADC转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //要转换的通道数目1
ADC_Init(ADC1, &ADC_InitStructure);
/*配置ADC时钟,为PCLK2的8分频,即9MHz*/
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
/*配置ADC1的通道11为55.5个采样周期,序列为1 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/*初始化校准寄存器 */
ADC_ResetCalibration(ADC1);
/*等待校准寄存器初始化完成 */
while(ADC_GetResetCalibrationStatus(ADC1));
/* ADC校准 */
ADC_StartCalibration(ADC1);
/* 等待校准完成*/
while(ADC_GetCalibrationStatus(ADC1));
/* 由于没有采用外部触发,所以使用软件触发ADC转换 */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
先定义结构体ADC_InitStructure,其类型为ADC_InitTypeDef,成员为ADC相关配置:模式、扫描转换、连续转换、外部触发、数据对齐、要转换的通道数目。
DMA_DeInit(DMA1_Channel1);
DMA1通道1的参数初始化为缺省值。
DMA各参数的定义如下:
#define ADC1_DR_Address ((u32)0x40012400+0x4c)
因为ADC1的基地址为0x4001 2400,而其数据寄存器相对于基地址的偏移为0x4c,所以外设地址为两者之和(0x4001 2400 + 0x4c)。
__IO uint16_t ADC_ConvertedValue;
#define DMA_DIR_PeripheralSRC ((uint32_t)0x00000000)
#define DMA_PeripheralInc_Disable ((uint32_t)0x00000000)
#define DMA_MemoryInc_Disable ((uint32_t)0x00000000)
#define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100)
#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400)
#define DMA_Mode_Circular ((uint32_t)0x00000020)
#define DMA_Priority_High ((uint32_t)0x00002000)
#define DMA_M2M_Disable ((uint32_t)0x00000000)
根据上述参数值对DMA进行初始化
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Init()函数定义如下:
/**
* @brief Initializes the DMAy Channelx according to the specified
* parameters in the DMA_InitStruct.
* @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and
* x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel.
* @param DMA_InitStruct: pointer to a DMA_InitTypeDef structure that
* contains the configuration information for the specified DMA Channel.
* @retval None
*/
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));
assert_param(IS_DMA_DIR(DMA_InitStruct->DMA_DIR));
assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize));
assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc));
assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc));
assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(DMA_InitStruct->DMA_PeripheralDataSize));
assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitStruct->DMA_MemoryDataSize));
assert_param(IS_DMA_MODE(DMA_InitStruct->DMA_Mode));
assert_param(IS_DMA_PRIORITY(DMA_InitStruct->DMA_Priority));
assert_param(IS_DMA_M2M_STATE(DMA_InitStruct->DMA_M2M));
/*--------------------------- DMAy Channelx CCR Configuration -----------------*/
/* Get the DMAy_Channelx CCR value */
tmpreg = DMAy_Channelx->CCR;
/* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */
tmpreg &= CCR_CLEAR_Mask;
/* Configure DMAy Channelx: data transfer, data size, priority level and mode */
/* Set DIR bit according to DMA_DIR value */
/* Set CIRC bit according to DMA_Mode value */
/* Set PINC bit according to DMA_PeripheralInc value */
/* Set MINC bit according to DMA_MemoryInc value */
/* Set PSIZE bits according to DMA_PeripheralDataSize value */
/* Set MSIZE bits according to DMA_MemoryDataSize value */
/* Set PL bits according to DMA_Priority value */
/* Set the MEM2MEM bit according to DMA_M2M value */
tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode |
DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc |
DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize |
DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M;
/* Write to DMAy Channelx CCR */
DMAy_Channelx->CCR = tmpreg;
/*--------------------------- DMAy Channelx CNDTR Configuration ---------------*/
/* Write to DMAy Channelx CNDTR */
DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize;
/*--------------------------- DMAy Channelx CPAR Configuration ----------------*/
/* Write to DMAy Channelx CPAR */
DMAy_Channelx->CPAR = DMA_InitStruct->DMA_PeripheralBaseAddr;
/*--------------------------- DMAy Channelx CMAR Configuration ----------------*/
/* Write to DMAy Channelx CMAR */
DMAy_Channelx->CMAR = DMA_InitStruct->DMA_MemoryBaseAddr;
}
tmpreg = DMAy_Channelx->CCR;
即tmpreg = 0;
tmpreg &= CCR_CLEAR_Mask;
0与上任何数仍旧为0,所以tmpreg = 0;
tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode |
DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc |
DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize |
DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M;
即temreg = 0 | 0x0000 0000 | 0x0000 0020 | 0x0000 0000 | 0x0000 0000 | 0x0000 0100 | 0x0000 0400 | 0x0000 2000 | 0x0000 0000 = 0x0000 2520;
DMAy_Channelx->CCR = tmpreg;
即DMA1_Channel1->CCR = 0x0000 2520;由DMA的CCR寄存器描述
可知,DMA1的通道1被配置为:非存储器到存储器模式、通道优先级为高、存储器数据宽度为16位、外设数据宽度为16位、不执行存储器地址增量操作、不执行外设地址增量操作、执行循环操作、从外设读(即外设为数据源)。
DMA_Cmd(DMA1_Channel1, ENABLE);
使能DMA1通道1,这里说明一下,ADC1的DMA请求是通过DMA1的通道1来实现的(具体可参考DMA请求映像图)。
ADC各参数的定义如下:
#define ADC_Mode_Independent ((uint32_t)0x00000000)
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
#define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_DataAlign_Right ((uint32_t)0x00000000)
根据上述参数值对ADC进行初始化:
ADC_Init(ADC1, &ADC_InitStructure);
库函数ADC_Init()的定义如下:
/**
* @brief Initializes the ADCx peripheral according to the specified parameters
* in the ADC_InitStruct.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains
* the configuration information for the specified ADC peripheral.
* @retval None
*/
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)
{
uint32_t tmpreg1 = 0;
uint8_t tmpreg2 = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_MODE(ADC_InitStruct->ADC_Mode));
assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ScanConvMode));
assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ContinuousConvMode));
assert_param(IS_ADC_EXT_TRIG(ADC_InitStruct->ADC_ExternalTrigConv));
assert_param(IS_ADC_DATA_ALIGN(ADC_InitStruct->ADC_DataAlign));
assert_param(IS_ADC_REGULAR_LENGTH(ADC_InitStruct->ADC_NbrOfChannel));
/*---------------------------- ADCx CR1 Configuration -----------------*/
/* Get the ADCx CR1 value */
tmpreg1 = ADCx->CR1;
/* Clear DUALMOD and SCAN bits */
tmpreg1 &= CR1_CLEAR_Mask;
/* Configure ADCx: Dual mode and scan conversion mode */
/* Set DUALMOD bits according to ADC_Mode value */
/* Set SCAN bit according to ADC_ScanConvMode value */
tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_Mode | ((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8));
/* Write to ADCx CR1 */
ADCx->CR1 = tmpreg1;
/*---------------------------- ADCx CR2 Configuration -----------------*/
/* Get the ADCx CR2 value */
tmpreg1 = ADCx->CR2;
/* Clear CONT, ALIGN and EXTSEL bits */
tmpreg1 &= CR2_CLEAR_Mask;
/* Configure ADCx: external trigger event and continuous conversion mode */
/* Set ALIGN bit according to ADC_DataAlign value */
/* Set EXTSEL bits according to ADC_ExternalTrigConv value */
/* Set CONT bit according to ADC_ContinuousConvMode value */
tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | ADC_InitStruct->ADC_ExternalTrigConv |
((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1));
/* Write to ADCx CR2 */
ADCx->CR2 = tmpreg1;
/*---------------------------- ADCx SQR1 Configuration -----------------*/
/* Get the ADCx SQR1 value */
tmpreg1 = ADCx->SQR1;
/* Clear L bits */
tmpreg1 &= SQR1_CLEAR_Mask;
/* Configure ADCx: regular channel sequence length */
/* Set L bits according to ADC_NbrOfChannel value */
tmpreg2 |= (uint8_t) (ADC_InitStruct->ADC_NbrOfChannel - (uint8_t)1);
tmpreg1 |= (uint32_t)tmpreg2 << 20;
/* Write to ADCx SQR1 */
ADCx->SQR1 = tmpreg1;
}
tmpreg1 = ADCx->CR1;
即tmpreg1 = 0;
tmpreg1 &= CR1_CLEAR_Mask;
0与上任何数都为0,所以tmpreg1 = 0;
tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_Mode | ((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8));
即tmpreg1 = 0 | (0x0000 0000) | (0 << 8) = 0;
ADCx->CR1 = tmpreg1;
即ADC1->CR1 = 0;由ADC的CR1寄存器描述
可知,ADC1被配置为:独立模式、关闭扫描模式。
tmpreg1 = ADCx->CR2;
即tmpreg1 = 0;
tmpreg1 &= CR2_CLEAR_Mask;
即tmpreg1 = 0;
tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | ADC_InitStruct->ADC_ExternalTrigConv |
((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1));
即tmpreg1 = 0 | 0x0000 0000 | 0x000E 0000 | (0x01 << 1) = 0x000E 0002;
ADCx->CR2 = tmpreg1;
即ADC1->CR2 = 0x000E 0002;由ADC的CR2寄存器描述
可知,ADC1被配置为:选择SWSTART为触发事件、连续转换模式。
tmpreg1 = ADCx->SQR1;
即tmpreg1 = 0;
tmpreg1 &= SQR1_CLEAR_Mask;
即tmpreg1 = 0;
tmpreg2 |= (uint8_t) (ADC_InitStruct->ADC_NbrOfChannel - (uint8_t)1);
即tmpreg2 = 0 | (1 - 1) = 0;
tmpreg1 |= (uint32_t)tmpreg2 << 20;
即tmpreg1 = 0 | (0 << 20) = 0;
ADCx->SQR1 = tmpreg1;
即ADC1->SQR1 = 0;由ADC的SQR1寄存器描述
可知,ADC1被配置为:1个转换。
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
/**
* @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)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_ADCCLK(RCC_PCLK2));
tmpreg = RCC->CFGR;
/* Clear ADCPRE[1:0] bits */
tmpreg &= CFGR_ADCPRE_Reset_Mask;
/* Set ADCPRE[1:0] bits according to RCC_PCLK2 value */
tmpreg |= RCC_PCLK2;
/* Store the new value */
RCC->CFGR = tmpreg;
}
根据上述RCC_ADCCLKConfig()函数定义及Debug调试
可得:RCC->CFGR = 0x001D C40A;由RCC的CFGR寄存器描述
可知,ADC时钟被配置为:PCLK2的8分频(72 / 8 = 9 MHz)。
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig()函数定义如下:
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
{
uint32_t tmpreg1 = 0, tmpreg2 = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_CHANNEL(ADC_Channel));
assert_param(IS_ADC_REGULAR_RANK(Rank));
assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime));
/* if ADC_Channel_10 ... ADC_Channel_17 is selected */
if (ADC_Channel > ADC_Channel_9)
{
/* Get the old register value */
tmpreg1 = ADCx->SMPR1;
/* Calculate the mask to clear */
tmpreg2 = SMPR1_SMP_Set << (3 * (ADC_Channel - 10));
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10));
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SMPR1 = tmpreg1;
}
else /* ADC_Channel include in ADC_Channel_[0..9] */
{
/* Get the old register value */
tmpreg1 = ADCx->SMPR2;
/* Calculate the mask to clear */
tmpreg2 = SMPR2_SMP_Set << (3 * ADC_Channel);
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel);
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SMPR2 = tmpreg1;
}
/* For Rank 1 to 6 */
if (Rank < 7)
{
/* Get the old register value */
tmpreg1 = ADCx->SQR3;
/* Calculate the mask to clear */
tmpreg2 = SQR3_SQ_Set << (5 * (Rank - 1));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SQR3 = tmpreg1;
}
/* For Rank 7 to 12 */
else if (Rank < 13)
{
/* Get the old register value */
tmpreg1 = ADCx->SQR2;
/* Calculate the mask to clear */
tmpreg2 = SQR2_SQ_Set << (5 * (Rank - 7));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SQR2 = tmpreg1;
}
/* For Rank 13 to 16 */
else
{
/* Get the old register value */
tmpreg1 = ADCx->SQR1;
/* Calculate the mask to clear */
tmpreg2 = SQR1_SQ_Set << (5 * (Rank - 13));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SQR1 = tmpreg1;
}
}
Debug调试得:
ADC1->SMPR1 = 0x0000 0028;由SMPR1寄存器描述
可知,ADC1被配置为:采样时间为55.5个周期。
ADC1->SQR3 = 0x0000 000B;由SQR3寄存器描述
可知,ADC1被配置为:规则序列中的第1个转换。
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
使能ADC1的DMA模式、使能ADC1。
/*初始化校准寄存器 */
ADC_ResetCalibration(ADC1);
/*等待校准寄存器初始化完成 */
while(ADC_GetResetCalibrationStatus(ADC1));
/* ADC校准 */
ADC_StartCalibration(ADC1);
/* 等待校准完成*/
while(ADC_GetCalibrationStatus(ADC1));
注意:在开始ADC转换之前,建议对ADC进行校准,上面即为校准代码,限于篇幅不再详细介绍。
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_SoftwareStartConvCmd()函数定义如下:
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC conversion on external event and start the selected
ADC conversion */
ADCx->CR2 |= CR2_EXTTRIG_SWSTART_Set;
}
else
{
/* Disable the selected ADC conversion on external event and stop the selected
ADC conversion */
ADCx->CR2 &= CR2_EXTTRIG_SWSTART_Reset;
}
}
即ADC1->CR2 = 0x005E 0103(这里的调试结果(0x001E 0103)我觉得有问题,前面是我自己的结果),再由CR2描述
可知,ADC1被配置为:使用外部触发信号启动转换、开始转换规则通道。
ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3;
最后计算AD转换的结果,它是以参考电压值(这里是3.3V)为一个单位,即把3.3V等分成4096份来计算的。
注意:
ADC输入电压范围:VREF- <= VIN <= VREF+
VREF+电压范围: 2.4V <= VREF+ <= VDDA
VDDA电压范围: 2.4V <= VDDA <= VDD(3.6V)
故:ADC输入电压最高不超过3.6V。
到此为止,STM32的ADC功能就配置完成了,我们可以对从PC1脚输入的电压进行测量并通过串口或LCD来显示电压的具体数值(可测量电压范围:0 ~ 3.3V)。
由于作者学识有限,文中的错误及疏漏之处敬请读者批评指正。
原创作品