该主题比上一主题主要是使用了中断
1.main.c文件
#include "stm32f10x.h" #include "adc.h" #include "usart1.h"uint16_t adc_val = 0; uint8_t cnt = 0; void delay(void) {uint32_t t = 0;for(t = 0; t < 0xfffef; t ++); }int main(void) {USART1_Init();ADC1_Init_Config();//ADC规则通道配置ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_239Cycles5);//RANK:数值越小,越先转换;这里通道2,第一个进行AD转换;要是有多个通道的话,设定先后顺序// ADC采样周期计算公式 = ADC_SampleTime_xxxCycles5 + 12.5个周期,这里是256个周期,频率设置成了12MHz,所以采样时间 = 256/12MHz = 21.3us,采样时间长,采样会准确些//ADC采样前先进行校准动作ADC_ResetCalibration(ADC1);//复位校准while(ADC_GetResetCalibrationStatus(ADC1) != RESET); //平时是1,复位完成变成0 ADC_StartCalibration(ADC1);while(ADC_GetCalibrationStatus(ADC1) != RESET);//平时是1,校准完成变成0while(1){ ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件启动AD转换功能 // while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //平时是0,转换完成变成1 ;这次使用的中断,转换完成会进入中断,读取数据。用的ADC_GetITStatus函数 printf("AD-VALUE:%d--- %.3f\r\n", cnt,(float)adc_val/4096.0*3.3);//这里注意需要除以4096.0,如果写成了整数,打印输出就会变成0.0了 delay();} }
和前篇的差异标红处理展示;
2.adc.c文件
#include "adc.h"void ADC1_Init_Config(void) {ADC_InitTypeDef ADC_InitStruct;//1.配置ADC的GPIO引脚 GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//输入功能不用设置输出速度参数GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;//2.配置时钟,GPIOA时钟和ADC1外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE);//PA2 ADC_IN2 GPIO_Init(GPIOA, &GPIO_InitStruct);//3.配置ADC模式相关参数ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; //设置成连续转换模式(ENABLE)或者单次转换模式(DISABLE)ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐,12位的数据,右对齐不用处理高位,高位就是0ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //若是选择外部触发转换,选择对应的触发条件,否则设置为不使用外部触发ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//多种模式组合,选择一种ADC_InitStruct.ADC_NbrOfChannel = 1;//需要转换的通道数,这里只有1个通道要转换ADC_InitStruct.ADC_ScanConvMode = DISABLE;//多通道扫描转换(ENABLE),或者是单通道转换(DISABLE),这里选择单通道转换//4.配置ADC时钟不能超过14MHz 系统时钟72MHz进行6分频,12MHz RCC_ADCCLKConfig(RCC_PCLK2_Div6);//5.ADC1初始化ADC_Init(ADC1, &ADC_InitStruct);//6.ADC中断使能 ,看到中断,要想到NVIC配置 ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);//7.进行中断相关设置 ADC_NVIC_Config();//8.ADC1功能使能 ADC_Cmd(ADC1, ENABLE); }
3.新增加了nvic.c文件
#include "nvic.h"void ADC_NVIC_Config(void) {NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = ADC1_2_IRQn; //ADC中断功能NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; //响应优先级NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //中断组配置 NVIC_Init(&NVIC_InitStruct); }
4.中断函数返回ADC采样数据
void ADC1_2_IRQHandler(void) {if(ADC_GetITStatus(ADC1, ADC_IT_EOC)) //如果,ADC1转换结束,则读取数据 {adc_val = ADC_GetConversionValue(ADC1);if(cnt < 200)cnt ++;}ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); //读取完后,清除标志位 }
虽然设置的是单次转换【ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;】,但是因为在主函数,主循环中,一段时间进行一次软件启动AD转换,所以AD一直出来新的采样值。