高级会员

- 积分
- 680
- 金钱
- 680
- 注册时间
- 2013-8-16
- 在线时间
- 37 小时
|
5金钱
ADC采样出现干扰现象;干扰现象1:依次采样ADC1的通道10,11,12,13,14,15等6个通道,当我采集10通道的时候,发现第11通道的值也在随着通道10的变化而变化且变化趋势相同。两个IO口距离越近干扰想象就越明显。
干扰现象2:采集单个通道值的时候,在个别位置会出现采得的数据来回跳动,跳动的值最大相差8.
如果只保留一个通道,其他通道全都关闭,再进行采集,数据就不干扰现象出现。
我使用的是航模遥控器上的摇杆进行ADC采集,摇动摇杆控制进行对应通道的ADC数据的采集,使用串口输出在串口调试工具上检测各个通道ADC实时采样数值的变化。
我的实验代码如下:
ADC初始化部分:
static unsigned int g_aAdValue[8];
unsigned int ret;
void ADC_init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );//使能I/O口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PC0/1/2/3/4/5作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOC, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1工作为独立模式
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数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);//失能ADC1通道时钟待用
}
//获得ADC值
unsigned short int Get_Adc(unsigned char ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1,ADC_SampleTime_7Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
unsigned short int AdcConvert(unsigned char ch)
{
unsigned char max_id,min_id,max_value,min_value;
unsigned char t;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//使能ADC1通道时钟
ret=Get_Adc(ch);
for(t=0;t<8;t++)
{
ret=Get_Adc(ch);
g_aAdValue[t]=ret;
ret=0;
}
ret=0;
for(t=1;t<8;t++)
ret+=g_aAdValue[t];
ret/=7;
max_id=min_id=1;
max_value=min_value=0;
for(t=1;t<8;t++)
{
if(g_aAdValue[t]>ret)
{
if(g_aAdValue[t]-ret>max_value)
{
max_value=g_aAdValue[t]-ret;
max_id=t;
}
}
else
{
if(ret-g_aAdValue[t]>min_value)
{
min_value=ret-g_aAdValue[t];
min_id=t;
}
}
}
ret=0;
for(t=1;t<8;t++)
{
if((t!=min_id)&&(t!=max_id))
ret+=g_aAdValue[t];
}
if(min_id!=max_id)
ret/=5;
else
ret/=6;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);//失能ADC1通道时钟,待用
return ret;
}
int main(void)
{
SystemInit();//系统初始化
cli();
delay_init(72);//延时函数初始化
LED_Init();//led灯初始化
time_init(19999,71);//定时器初始化,定时器产生溢出中断
ADC_init();//ADC模块初始化
sei();
while(1)
{
}
}
//串口初始化,发送中断
void usart_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
USART_Cmd(USART2, ENABLE);
GPIO_SetBits(GPIOA,GPIO_Pin_2);
GPIO_SetBits(GPIOA,GPIO_Pin_3);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
ADC_value=AdcConvert(10)/4;
ADC_value1=AdcConvert(11)/4;
ADC_value2=AdcConvert(12)/4;
ADC_value3=AdcConvert(13)/4;
usart_init();
NVIC_Configuration();
TX_Counter=0;
}
}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
{
USART_ClearITPendingBit(USART2,USART_IT_TXE);
sei();
if(TX_Counter>7)
{TX_Counter=7;}
switch(TX_Counter)
{
case 0:
USART2->DR=ADC_value>>8;
TX_Counter++;
break;
case 1:
USART2->DR=ADC_value&0x00FF;
TX_Counter++;
break;
case 2:
USART2->DR=ADC_value1>>8;
TX_Counter++;
break;
case 3:
USART2->DR=ADC_value1&0x00FF;
TX_Counter++;
break;
case 3:
USART2->DR=ADC_value2>>8;
TX_Counter++;
break;
case 4:
USART2->DR=ADC_value2&0x00FF;
TX_Counter++;
break;
case 5:
USART2->DR=ADC_value2>>8;
TX_Counter++;
break;
case 6:
USART2->DR=ADC_value2&0x00FF;
TX_Counter++;
break;
case 7:
while((USART2->SR&0x80)!=0x80);
TX_Counter++;
break;
}
}
}
|
最佳答案
查看完整内容[请看2#楼]
代码太长了,没仔细看。从你说的现象来看,你可以试试:
1.缩短采集线,弄到最短先试试。
2.滤波算法。去掉最大和最小求平均之类。
3.ADC_SampleTime_7Cycles5这个值太小了,比较次数那么少,精度肯定不行。
|