新手入门
- 积分
- 13
- 金钱
- 13
- 注册时间
- 2019-5-28
- 在线时间
- 3 小时
|
1金钱
如题,STM32F103 ADC1/ADC2+DMA1双通道同时采集,ADC1和ADC2各采集3个通道 ,返回结果有2个通道总是错误,单次采集时每组数据都正常,
因单次采集数据小数点后一位跳动较大,采集1000次数据相加在求平均值 ,发现其中两组数据出错,贴上程序,请大神帮看看是哪里问题,谢谢!
unsigned int ADC_DectValue[3000]; //ADC采集缓存
void ADC_init(void)
{
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* 配置DMA1 通道 1 */
DMA_DeInit(DMA1_Channel1); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)ADC1_DR_Address; //定义DMA外设基地址 (ADC1的基地址)
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_DectValue; //定义DMA内存基地址(在主程序里申明,此处引用)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作为数据传输的来源
//定义指定DMA通道的DMA缓存的大小,单位为数据单位。根据传输方向,
//数据单位等于结构中参数DMA_PeripheralDataSize或者参数DMA_MemoryDataSize的值
DMA_InitStructure.DMA_BufferSize = 3000; //此值为完整一轮DMA传输的次数
//用来设定外设地址寄存器递增与否
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设ADC1地址寄存器不变
//DMA_MemoryInc用来设定内存地址寄存器递增与否
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
//DMA_PeripheralDataSize设定了外设数据宽度
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//数据宽度为32位(因为ADC1和ADC2同时采集数据,所以2个16位合并为32位数据)
//DMA_MemoryDataSize设定了外设数据宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //数据宽度为32位
//DMA_Mode设置了CAN的工作模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
//DMA_Priority设定DMA通道x的软件优先级
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道x拥有高优先级
//DMA_M2M使能DMA通道的内存到内存传输
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道x寄存器
/* Get Current Data Counter value before transfer begins */
CurrDataCounterBegin = DMA_GetCurrDataCounter(DMA1_Channel1);
/* Enable DMA1 Channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE); // 使能或者失能指定的通道x
//DCIN1--> PC0 //DC输入端1
//DCIN2--> PC1 //DC输入端2
//BATTV--> PC2 //电瓶电压检测
//BATTA--> PC3 //电源电流检测
//TEMP --> PC4 //电瓶温度检测
//ADCA --> PC5 //负载电流检测
/* 配置ADC1参数 */
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //ADC1和ADC2工作在同步规则模式
//ADC_ScanConvMode规定了模数转换工作在扫描模式(多通道)还是单次(单通道)模式。
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //连续扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //使用外部触发来启动规则通道的模数转
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 3; //规定了顺序进行规则转换的ADC通道的数目。这个数目的取值范围是1到16
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 规则通道配置 */
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
//输入参数1 ADCx:x可以是1或者2来选择ADC外设ADC1或ADC2
//输入参数2 ADC_Channel:被设置的ADC通道
//输入参数3 Rank:规则组采样顺序。取值范围1到16。
//输入参数4 ADC_SampleTime:指定ADC通道的采样时间值
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5); //V2输入端电压
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5); //V1输入端电压
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_239Cycles5); //电瓶电压检测
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* 配置ADC2参数 */
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //ADC1和ADC2工作在同步规则模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //连续扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //使用外部触发来启动规则通道的模数转
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 3; //规定了顺序进行规则转换的ADC通道的数目。这个数目的取值范围是1到16
ADC_Init(ADC2, &ADC_InitStructure);
/* ADC2 规则通道配置 */
ADC_RegularChannelConfig(ADC2, ADC_Channel_13,1, ADC_SampleTime_239Cycles5); //电瓶充电电流
ADC_RegularChannelConfig(ADC2, ADC_Channel_14,2, ADC_SampleTime_239Cycles5); //电瓶温度检测
ADC_RegularChannelConfig(ADC2, ADC_Channel_15,3, ADC_SampleTime_239Cycles5); //负载电流检测
ADC_ExternalTrigConvCmd(ADC2, ENABLE); //使能ADC2的经外部触发启动注入组转换功能
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable Vrefint channel17 */
ADC_TempSensorVrefintCmd(DISABLE);//失能温度传感器和内部参考电压通道
/* 使能ADC1转接复位寄存器 */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register 检查复位校准寄存器的结束 */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration 启动ADC1校准 */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration 检查ADC1校准结束 */
while(ADC_GetCalibrationStatus(ADC1));
/* 使能ADC2 */
ADC_Cmd(ADC2, ENABLE);
/*启用ADC2复位校准寄存器 */
ADC_ResetCalibration(ADC2);
/* 等待ADC2复位校准寄存器的结束 */
while(ADC_GetResetCalibrationStatus(ADC2));
/* 启动ADC2校准 */
ADC_StartCalibration(ADC2);
/*等待ADC2校准结束 */
while(ADC_GetCalibrationStatus(ADC2));
/*启动ADC1辅助软件转换 */
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC的软件转换启动功能
/* Test on Channel 1 DMA_FLAG_TC flag */
while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
/* 清除通道1 DMA_FLAG_TC 标志 */
DMA_ClearFlag(DMA1_FLAG_TC1);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_SoftwareStartConvCmd(ADC2, ENABLE);
}
/**********************************************************************************
ADC1和ADC2采集值输出
***********************************************************************************/
void adcvolout(void)
{
unsigned int ADCBuff[6]; //ADC采集缓存
unsigned int a,b=3000,c=1000;
float ref = 3.281; //基准电压值(实测3.3V供电电压)
for(a=0;a<b;a+=3)
{
ADCBuff[0] += (ADC_DectValue[a]&0x0000FFFF); //V2电压
ADCBuff[1] += (ADC_DectValue[a]/65536); //电瓶温度
}
for(a=1;a<b;a+=3)
{
ADCBuff[2] += (ADC_DectValue[a]&0x0000FFFF); //V1电压
ADCBuff[3] += (ADC_DectValue[a]/65536); //负载电流
}
for(a=2;a<b;a+=3)
{
ADCBuff[4] += (ADC_DectValue[a]&0x0000FFFF); //电瓶电压
ADCBuff[5] += (ADC_DectValue[a]/65536); //充电电流
}
ADCBuff[0] = ADCBuff[0]/c; //1000次数据相加后求平均值
ADCBuff[1] = ADCBuff[1]/c;
ADCBuff[2] = ADCBuff[2]/c;
ADCBuff[3] = ADCBuff[3]/c;
ADCBuff[4] = ADCBuff[4]/c;
ADCBuff[5] = ADCBuff[5]/c;
printf("V2电压:\n");
printf("%d\r\n",ADCBuff[0]);
printf("电瓶温度:\n");
printf("%d\r\n",ADCBuff[1]);
printf("V1电压:\n");
printf("%d\r\n",ADCBuff[2]);
printf("负载电流:\n");
printf("%d\r\n",ADCBuff[3]);
printf("电瓶电压:\n");
printf("%d\r\n",ADCBuff[4]);
printf("充电电流:\n");
printf("%d\r\n",ADCBuff[5]);
printf("\r\n");
//计算出各路显示值
DCIN1 = (float)ADCBuff[0]/4096*ref*13; //V2电压
DCIN0 = (float)ADCBuff[2]/4096*ref*13; //V1电压
BATTV = (float)ADCBuff[4]/4096*ref*10.1; //电瓶电压
BATTA = (float)ADCBuff[5]/4096*ref*32; //充电电流
//TEMP = ADCBuff[1]/4096*3.2; //电瓶温度(LM35未用)
ADCA = (float)ADCBuff[3]/4096*ref*32; //负载电流
}
串口返回数据:
V2电压:134232 (错误数据,电压输入为0V)
电瓶温度:2
V1电压:0
负载电流:0
电瓶电压:536877 (错误数据,电压输入为0V)
充电电流:0
V2电压:134232
电瓶温度:2
V1电压:0
负载电流:0
电瓶电压:536877
充电电流:0
V2电压:134232
电瓶温度:2
V1电压:0
负载电流:0
电瓶电压:536877
充电电流:0
V2电压:134232
电瓶温度:2
V1电压:0
负载电流:0
电瓶电压:536877
充电电流:0
|
|