三个传感器模块:光敏、热敏、反射式红外传感器
多通道首先想到了之前的扫描模式,方法不错,但要用到DMA来解决数据覆盖的问题,没学过DMA的同学可以忽略。
还有一种想法是一个通道转换完成后手动转运出数据不就行了,为啥要DMA?看似简单但实际操作会遇到问题,问题一:扫描模式下,启动列表后,里面的每一个单独的通道转换完成之后不会产生任何标志位,也不会触发中断,无法知道某个通道是否转换完毕,只有在整个列表转换完成后才会产生一次EOC标志位,才可触发中断;问题二:AD转换十分快速(几us/通道),手动转运困难。不过也不代表一定不行,可使用间断模式,扫描时每转换一个通道暂停一次,不推荐效率低。
还有一个方法,单次转换、非扫描模式基础上,在每次触发转换之前,手动更改下列表第一个位置的通道,比如第一次转换先写入通道哦,之后触发、等待、读值;第二次转换把通道0改为通道1...。具体操作如下:
//删除AD_Init()里的
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
//下面的AD_GetValue()函数变化为可改变通道的:
uint16_t AD_GetValue(uint8_t ADC_Channel){
ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);//通道可改
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发,ADC开始转换
while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//ADC转换需要一定时间
return ADC_GetConversionValue(ADC1);//获取转换值
}
//main.c
#include "stm32f10x.h"
#include "delay.h"
#include "OLED.h"
#include "ADC.h"
uint16_t AD0,AD1,AD2;//表示三个ADC输入通道的转换结果的接收变量
int main(void){
OLED_Init();
ADC_Init();
OLED_ShowString(1,1,"AD0:");
OLED_ShowString(2,1,"AD1:");
OLED_ShowString(3,1,"AD2:");
while(1){
AD0 = AD_GetValue(ADC_Channel_0);
AD1 = AD_GetValue(ADC_Channel_1);
AD2 = AD_GetValue(ADC_Channel_2);
OLED_ShowNum(1,5,AD0,4);
OLED_ShowNum(2,5,AD1,4);
OLED_ShowNum(3,5,AD3,4);
Delay_ms(100);
}
}