打印
[STM32F2]

STM32F207 PWM波形峰峰值检查问题(有图有大码)

[复制链接]
2781|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ymdeid|  楼主 | 2015-12-7 16:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ymdeid 于 2015-12-7 16:58 编辑

最近开发了一个基于STM32F207的控制器,其中一部分功能是通过PWM方式驱动一个电阻负载,同时检测这个电阻负载上的电流和电压有效值。PWM输出这个倒是简单,关键是PWM波形峰峰值的获取。我的想法是这样的:通过霍尔电流传感器得到电流PWM方波的信号,通过电阻分压并通过一个电压跟随器获得负载上的PWM电压方波信号,然后通过STM32F207的ADC1分别同时采集电压和电流方波信号。为了实现这个目的,将TIM3配置为PWM1模式(比较输出),并开启Tim3的TIM_IT_Update和TIM_IT_CC1两个中断。以我的理解,TIM_IT_Update这个中断,就是当自动重载寄存器被更新时产生中断,而TIM_IT_CC1这个中断,就是当比较寄存器与TIM3计数值匹配是产生中断,换句话说,TIM_IT_Update中断产生在PWM输出高电平时,而TIM_IT_CC1中断产生在PWM输出低电平时。所以,在TIM3的中断服务程序中,PWM高电平和低电平设置不同ADC1的DMA缓冲区,从而得到负载上的电流和电压的高电平和低电平值,高低只差就是峰峰值,再通过计算即可得到它们的RMS值。目前整个硬件和软件运行看来是正常的,特别是电压采集很准确,但获得电流值却不正确。获得电流比实际电流值大了3-4A,且并不是静态误差,而且让人觉得纳闷儿的是,虽然电流不准,但从示波器看,进入ADC1采集通道的电流的峰值是会随电流大小而变化的,检查了程序和硬件目前都没发现明显的 问题,请各位老师帮忙看看问题出在哪里。以下是ADC输入通道上的电流波形和TIM3中断服务程序的代码:


// TIM3中断服务程序
void TIM3_IRQHandler(void)
{
        uint16_t FilterData_Lo[ADC_CHANNEL_NUM];
        uint16_t FilterData_Hi[ADC_CHANNEL_NUM];

        //如果是这个中断,则说明是刚开始一个新的PWM周期,即自动
        //重载寄存器被更新,此时获得上一个PWM周期的低电平数据。
        if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
        {     
                 //清除中断标志
                TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
                //如果CCR1中没有值,则说明还没有开始PWM输出
                if(TIM3->CCR1==0)
                {
                        ADC_Cmd(ADC1, DISABLE);
                        
                        return;
                }
                //如果已开始ADC转换,则停止它,获得请一个PWM周期的低电平数据
                if(ADC_GetFlagStatus(ADC1,ADC_FLAG_STRT)==SET)
                {
                        ADC_Cmd(ADC1, DISABLE);
                        
                        //从ADC的DMA数据缓冲区中获得数据并波(PWM波谷数据)
                        WaveformDataFilter(WaveformDataBuffer_Lo,FilterData_Lo);
                        //保存滤波后的电流低电平数据
                        WaveformData[ADC_DATA_INDEX_CUNT].uiLowLevel=FilterData_Lo[ADC_DATA_INDEX_CUNT];
                        //保存滤波后的电压低电平数据
                        WaveformData[ADC_DATA_INDEX_VOLT].uiLowLevel=FilterData_Lo[ADC_DATA_INDEX_VOLT];
                        
                }
               
                //启动新的ADC转换和DMA传输,并设置DMA缓冲区为高电平数据缓冲区
                ADC1_Config();
                DMA2_Stream0_Config(WaveformDataBuffer_Hi);
                ADC_SoftwareStartConv(ADC1);
               
        }
        //如果是这个中断,则说明是此时TIM3计数器值正好和CCR1寄存器
        //值相等,PWM输出低电平,此时获得当前PWM周期的高电平数据
        else if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == SET)
        {
                TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
               
                if(TIM3->CCR1==0)
                {
                        ADC_Cmd(ADC1, DISABLE);
                        return;
                }
                //如果一开始ADC转换,则停止它,以便获得数据
                if(ADC_GetFlagStatus(ADC1,ADC_FLAG_STRT)==SET)
                {
                        //停止ADC转换
                        ADC_Cmd(ADC1, DISABLE);
                        
                        //从DMA缓冲区中获得电流和电压的高电平数据
                        WaveformDataFilter(WaveformDataBuffer_Hi,FilterData_Hi);
                        //保存电流和电压的高电平数据数据
                        WaveformData[ADC_DATA_INDEX_CUNT].uiHighLevel=FilterData_Hi[ADC_DATA_INDEX_CUNT];
                        WaveformData[ADC_DATA_INDEX_VOLT].uiHighLevel=FilterData_Hi[ADC_DATA_INDEX_VOLT];
                        
                }
               
                //启动新的ADC转换和DMA,并设置DMA缓冲区为低电平数据缓冲区
                ADC1_Config();
                DMA2_Stream0_Config(WaveformDataBuffer_Lo);
                ADC_SoftwareStartConv(ADC1);
        }
}


沙发
ymdeid|  楼主 | 2015-12-8 18:59 | 只看该作者
没人出招!不过问题已经解决了。

使用特权

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

本版积分规则

1

主题

2

帖子

0

粉丝