今天在学习adc库函数 于是图方便想整个不用序列通道的 多路采集来实验下效果
初始化部分代码如下
GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; /* 使能ADC1和GPIOC的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE); /*配置ADC时钟,为PCLK2的8分频,即9MHz*/ RCC_ADCCLKConfig(RCC_PCLK2_Div8); /* 配置PC0,1,2,3为模拟输入模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //设置GPIO为模拟输入 GPIO_Init(GPIOC, &GPIO_InitStructure); // 输入时不用设置速率 ADC_DeInit(ADC1); //复位ADC1将外设ADC1的全部寄存器重设为缺省值 /* ADC1 初始化*/ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立ADC模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE ; //禁止扫描模式,扫描模式用于多通道采集 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式 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); /* DISABLE ADC1 DMA */ ADC_DMACmd(ADC1, DISABLE); //关闭DMA请求 (不需要用到) /* 使能 ADC1 */ ADC_Cmd(ADC1, ENABLE); /*复位校准寄存器 */ ADC_ResetCalibration(ADC1); /*等待校准寄存器复位完成 */ while(ADC_GetResetCalibrationStatus(ADC1)); /* ADC校准 */ ADC_StartCalibration(ADC1); /* 等待校准完成*/ while(ADC_GetCalibrationStatus(ADC1)); /*开启ADC1的软件启动功能 */ ADC_SoftwareStartConvCmd(ADC1, ENABLE);
读值的子程序
uint16_t Get_Adc(uint8_t ch) { ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,转换时间239.5个周期 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1的转换功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//判断ADC转换结束标志位 等待转换结束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC的数据 }
那么问题来了 我使用PC0一个通道的时候 程序运行很好
然后在主程序跑3个通道的时候 就出现了问题
原本的接线是 PC 0,1,2分别接的是 电位器的中间 3.3V GND 但是程序上把数据的位置混了
于是我开始检查 到底是哪出了问题
while (1) { CH0 =(float) Get_Adc(ADC_Channel_10)/4096*3.3; // 读取PC0转换的AD值 DisplayFloat(CH0,21,6); CH1 =(float) Get_Adc(ADC_Channel_11)/4096*3.3; // 读取PC1转换的AD值 DisplayFloat(CH1,37,6); CH2 =(float) Get_Adc(ADC_Channel_12)/4096*3.3; // 读取PC2转换的AD值 DisplayFloat(CH2,53,6); Delay(0x18ffee); }
初始化部分是库函数 一般不会有错误 于是我去检查获取ADC值的子程序
有人说是没清除标志位 于是我加入了
ADC_ClearFlag(ADC1, ADC_FLAG_EOC); // 清除转换结束标志位
然后结果还是这样 突然想起以前写外部adc的时候 读值都是直接加个延时 时间远大于转换周期
于是我在判断转换完成标志之后 加了一个1MS的延时
uint16_t Get_Adc(uint8_t ch) { ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,转换时间239.5个周期 提高转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1的转换功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//判断ADC转换结束标志位 等待转换结束 DelayMs(1); //延时1Ms等待外设ADC把数据写入ADC1_DR return ADC_GetConversionValue(ADC1); //返回最近一次ADC的数据 }
然后程序就正常了
由此不经想问在库函数的介绍中
ADC_FLAG_EOC不是转换完成的标志么 为什么判断标志完成后读值 数据会乱呢
唯一能理解的就是说 ADC转换完成 标志就被置位了
但是数据还没到ADC1_DR里面,于是需要人为添加一个短延时让ADC外设把数据移到DR里面。
不知道我说的对不对 不过问题是这样解决的。。。仅供参考,大神莫见笑