打印

关于STM32 ADC使用的一个奇怪问题

[复制链接]
11969|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
linjinming2000|  楼主 | 2012-3-16 15:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人使用STM32F103CBT6的AIN0 ~ AIN8总共9路ADC通道采集9路交流信号,其中PA0,PA1,PA5使用ADC1,其余通道使用ADC2,双通道模式,DMA软件触发,在定时器2中定时触发ADC(触发频率为3.2KHZ),现在的情况是PA0,PA1,PA5的交流信号基本相同,而PA0,PA1采集得到的值是正确的,PA5采集的值明显偏小,大约偏小1%,理论上应该大致相等,请问这是什么原因造成的?谢谢!
沙发
香水城| | 2012-3-16 16:51 | 只看该作者
测量的准确性与硬件环境有很大关系。

使用特权

评论回复
板凳
午夜霓虹| | 2012-3-16 16:56 | 只看该作者
套句经典台词:没图没真相。

使用特权

评论回复
地板
airwill| | 2012-3-16 21:49 | 只看该作者
交流信号的频率是多少, 会不会是采样相位的原因?

使用特权

评论回复
5
linjinming2000|  楼主 | 2012-3-16 22:12 | 只看该作者
部分原理图和PCB如下:

部分原理图.pdf (17.16 KB)
PCB.pdf (52.42 KB)

使用特权

评论回复
6
linjinming2000|  楼主 | 2012-3-16 23:02 | 只看该作者
今天下午测试发现,只有PA0和PA1的精度较高,其余的精度较低,误差大约0.2%(以600V为量程的引用误差),而PA0和PA1可以达到0.05%,其他通道的信号用飞线引到PA1进行测试发现精度也非常高,排除了前端模拟电路的问题,然后把PA1通道的信号分别引到PA5、PA3和PA2进行测试,精度也只能达到0.2%,开始怀疑PCB走线问题,因为PA4、PA5、PA6、PA7、PB0并行走线,但是PA2走线应该没问题,但是现象还是一样,所以排除了走线问题。同时软件也是比较成熟的,之前测试三相电压是通过模拟开关进行切换到PA0,现在是去除了模拟开关,软件进行了相应的调整。ADC配置情况如下:双ADC模式,使用定时器2进行软件触发,触发频率固定为3.2K,ADC采样频率为204.8KHz,每次进行16倍过采样(DMA),最后采集到的数据采用准同步采样算法进行DFT分析!

使用特权

评论回复
7
午夜霓虹| | 2012-3-17 09:40 | 只看该作者
你的图不是很全,只能说亮点,建议你把R45等电阻变小,然后把采样时间加长,这样采样精度就会提高。

使用特权

评论回复
8
zxz_chy| | 2012-3-17 09:40 | 只看该作者
楼主是测三相电压的吗,我做的项目也是的,我用的是互感器的,你这种好像成本可以降低不少,我用双ADC模式时也有问题的,双ADC模式时测量出来电压偏低的,现在我就用1路ADC来扫描的

使用特权

评论回复
9
午夜霓虹| | 2012-3-17 09:45 | 只看该作者
我做的时候全部精度都在0.2%,当然互感器的精度都是0.2%的,所以没法说准确还是准确,个人感觉,两个AD同时没什么问题的,我也是这么用的。

使用特权

评论回复
10
午夜霓虹| | 2012-3-17 09:48 | 只看该作者
另外,你这样做,你要量一下你的模拟量电压或数字电压的差,看看是不是有问题。

使用特权

评论回复
11
linjinming2000|  楼主 | 2012-3-17 15:03 | 只看该作者
模拟量电压正确的,三路基本一致,但是出来的AD值差的很多

使用特权

评论回复
12
zjp8683463| | 2012-3-17 16:20 | 只看该作者
ADC的多个通道并不是同步触发和采集的.
ADC的多个通道间采集的间隔时间与ADC自身有关,可以仔细看看datasheet.
如果需要同步采集的ADC,价格要高很多.

使用特权

评论回复
13
午夜霓虹| | 2012-3-17 17:01 | 只看该作者
个人观点,就楼主这个产品而言,根本不需要什么同步采集,就说不同通道的问题,确实也很奇怪。

使用特权

评论回复
14
linjinming2000|  楼主 | 2012-3-17 19:14 | 只看该作者
同步采样是为了同时采集电压和电流,这样单项功率的精度要高些,克服了采样产生的相位差

使用特权

评论回复
15
午夜霓虹| | 2012-3-18 09:42 | 只看该作者
你电源是不是存在问题,因为stm32要求模拟电压和数字电压必须相同,而你的那个方法在升压过程中和完成后都有可能存在误差,导致模拟设备工作不正常。

使用特权

评论回复
16
午夜霓虹| | 2012-3-18 09:44 | 只看该作者
ST至今也没有说一个比较好的方法来解决这个问题,只说了要求。

使用特权

评论回复
17
linjinming2000|  楼主 | 2012-3-18 13:42 | 只看该作者
VDDA实测电压为3.252V,VDD实测电压为3.308,两者差值为56mV,在300mV以内!今天拿以前的产品验证了一下发现,PA0和PA1通道电压精度较高,其余通道精度较差,可以排除走线和软件问题,电源差异的问题我再测试一下!

使用特权

评论回复
18
linjinming2000|  楼主 | 2012-3-18 14:03 | 只看该作者
现在我用VDD给VDDA供电进行测试,发现现象还是一样的,同一个信号分别连到PA0和PA2,AD测出来的值相差1.4%左右,而PA0和PA1则没有这个问题

使用特权

评论回复
19
linjinming2000|  楼主 | 2012-3-18 14:10 | 只看该作者
想确认下STM32的ADC内部的MUX到底是怎么做的,按照道理来讲不应该有这个问题,除非是通道之间的漏电流较大。

使用特权

评论回复
20
linjinming2000|  楼主 | 2012-3-18 14:16 | 只看该作者
//--------------------------------------------------------------------------------------------------
//         STM32 ADC相关定义
//--------------------------------------------------------------------------------------------------
#define                ADC_SAMP_CYC                                ADC_Samp_41Cyc5                                // ADC采样周期28.5       

/***************************************************************************************************
* 函数名称: stm32_ADCSetup()
* 函数功能: STM32 ADC初始化设置,PA1 ~ PA6为模拟输入
* 入口参数: 无
* 出口参数: 无
* 使用说明:初始化ADC相关寄存器,ADC时钟为11.0592MHz
* 创建日期: 2010年08月09日
***************************************************************************************************/
__inline static void stm32_ADCSetup(void)
{
        RCC->APB2ENR |= RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN;                // ADC1、ADC2时钟使能
        Delay(20);                                                                                                                // 增加一定延时,等待时钟使能完成       
        RCC->APB2RSTR |= RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN;                // 复位ADC1、ADC2
        Delay(20);                                                                                                                       
        RCC->APB2RSTR &= (~RCC_APB2ENR_ADC1EN) & (~RCC_APB2ENR_ADC2EN);        // 复位结束
        Delay(20);
       
        // AIN0作为电压输入,16倍过采样
        ADC1->CR1  = 0x00060100;                                                                                 // 规则同步模式、使用扫描方式、禁止产生EOC中断
        ADC1->CR2  = 0x001E0000;                                                                                // 规则通道软件触发、右对齐、不使用DMA、关闭ADC1转换
       
        ADC1->SQR1 = (ADC_Chl_0)|(ADC_Chl_0 << 5)|(ADC_Chl_0 << 10)|(ADC_Chl_0 << 15)|(0x0F << 20);       
        ADC1->SQR2 = (ADC_Chl_0)|(ADC_Chl_0 << 5)|(ADC_Chl_0 << 10)|(ADC_Chl_0 << 15)|(ADC_Chl_0 << 20)|(ADC_Chl_0 << 25);                                                               
        ADC1->SQR3 = (ADC_Chl_0)|(ADC_Chl_0 << 5)|(ADC_Chl_0 << 10)|(ADC_Chl_0 << 15)|(ADC_Chl_0 << 20)|(ADC_Chl_0 << 25);
                       
        // AIN1作为电流输入,16倍过采样
        ADC2->CR1  = 0x00000100;
        ADC2->CR2  = 0x001E0000;
       
        ADC2->SQR1 = (ADC_Chl_2)|(ADC_Chl_2 << 5)|(ADC_Chl_2 << 10)|(ADC_Chl_2 << 15)|(0x0F << 20);
        ADC2->SQR2 = (ADC_Chl_2)|(ADC_Chl_2 << 5)|(ADC_Chl_2 << 10)|(ADC_Chl_2 << 15)|(ADC_Chl_2 << 20)|(ADC_Chl_2 << 25);       
        ADC2->SQR3 = (ADC_Chl_2)|(ADC_Chl_2 << 5)|(ADC_Chl_2 << 10)|(ADC_Chl_2 << 15)|(ADC_Chl_2 << 20)|(ADC_Chl_2 << 25);                                                                               
               
        // 设置通道0 ~ 1的采样时间,41.5 + 12.5个周期 fadc = 11059.200 / 54 = 204.8 KHz
        ADC1->SMPR2 = (ADC_SAMP_CYC) | (ADC_SAMP_CYC << 3);               
        ADC2->SMPR2 = (ADC_SAMP_CYC) | (ADC_SAMP_CYC << 3);
       
        ADC1->CR2 |= ADC_CR2_ADON;                                                                                         // 开启AD转换器,上电时间最大1uS
        ADC2->CR2 |= ADC_CR2_ADON;
        Delay(1000);
       
        ADC1->CR2 |= ADC_CR2_RSTCAL;                                                                                 // 使能ADC1、ADC2复位校准寄存器
        ADC2->CR2 |= ADC_CR2_RSTCAL;                                                                                       
        while(ADC1->CR2 & ADC_CR2_RSTCAL);                                                                         // 等待复位结束                                                       
        while(ADC2->CR2 & ADC_CR2_RSTCAL);        
        Delay(1000);       
       
        ADC1->CR2 |= ADC_CR2_CAL;                                                                                         // 开启ADC1、ADC2校准
        ADC2->CR2 |= ADC_CR2_CAL;                                                                                       
        while(ADC1->CR2 & ADC_CR2_CAL);                                                                         // 等待校准结束                                                                       
        while(ADC2->CR2 & ADC_CR2_CAL);       
        Delay(1000);
        ADC1DMAEnable();
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

121

帖子

2

粉丝