打印

STM8 ADC-DMA 采集多路电压获得数据不断跳变。求助

[复制链接]
10109|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
十万火急。请求大侠们指点
   小弟使用STM8L采集16个电压值,改写ST库配置完了,一次采样16路电压,在DMA中断中读取采样值。在主函数中五次启动AD转换,再把采样值转存到v_tem1【16】~v_tem5【5】五个数组中,不知为什么这五个数组中每一路的采样值都在跳变,硬件电压没问题。
主程序如下。
#include "STM8L151M8.h"

#define ADC1_DR_ADDRESS        ((uint)0x5344)
#define BUFFER_SIZE            ((uint) 0x10)
#define BUFFER_ADDRESS         ((uint)(&Buffer))

uint arr[16]={0};
uint v_tem1[16]={0},v_tem2[16]={0},v_tem3[16]={0};
uint v_tem4[16]={0},v_tem5[16]={0};

uint Buffer[BUFFER_SIZE]={0};
FunctionalState ProcessStatus = DISABLE;
main()
{
        uchar j;
  clock_cfg();
        ports_init();
       
        adc_cfg();
        dma_cfg();
        Adc_DmaCmd(ADC1, ENABLE);       //Enable DMA for ADC.
       
        _asm("rim");                          //Enable globle interrupt
        while (1)
        {
                //第一次采样16个A/D 通道的值,存放在数组v_tem1【16】中。
                ADC1_CR1|=0x02;       
                while(ProcessStatus!=ENABLE); //等待DMA中断转换结束。
                for(j=0;j<16;j++)
                v_tem1[j]=arr[j];         //把DMA中断的中转值存入v_tem1[16],
                ProcessStatus = DISABLE;
仿真结果如下,不知道为什么每一路都在跳变。

               
                ADC1_CR1|=0x02;       
                while(ProcessStatus!=ENABLE);
                for(j=0;j<16;j++)
                v_tem2[j]=arr[j];
                ProcessStatus = DISABLE;
               
                ADC1_CR1|=0x02;       
                while(ProcessStatus!=ENABLE);
                for(j=0;j<16;j++)
                v_tem3[j]=arr[j];
                ProcessStatus = DISABLE;
               
                ADC1_CR1|=0x02;       
                while(ProcessStatus!=ENABLE);
                for(j=0;j<16;j++)
                v_tem4[j]=arr[j];
                ProcessStatus = DISABLE;
               
                //第五次采样相同16个通道的值,存放在数组v_tem1【16】中。
                ADC1_CR1|=0x02;       
                while(ProcessStatus!=ENABLE);
                for(j=0;j<16;j++)
                v_tem5[j]=arr[j];
                ProcessStatus = DISABLE;
               
                _asm("nop");
                _asm("nop");
                while(1);
        }
       
}
/***************************************************
   ADC配置程序
****************************************************/
void adc_cfg(void)
{
        ADC1_CR1=0x20;            /*Overrun interrupt disable,10-bit resolution,Analog watchdog interrupt
                                                                                                                 disable,EOC interrupt disable,Single conversion mode selected,Conversion
                                                                                                                 start disable,A/D modle has't enabled.*/                                                                                                         

        ADC1_CR2=0x00;                                                /*Clock prescaler equal CK,Active edge for external triggers disable,
                                                                                                                Software start selected,select 4 ADC clock cycle samping time.*/
       
        ADC1_CR1|=0x01;            //Enable the ADC model.
       
  //ADC1_SQR1=0x00;          //DMA enabled,It default status is enable.
  
        ADC1_SQR2=0x7F;                                                 //Select channels 16 to 22 for scan.
        ADC1_SQR3=0xFC;            //Select channels 10 to 15 for scan
  ADC1_SQR4=0x07;            //Select channels 0 to 2 for scan.
}
/****************************************************
   DMA 配置程序
*****************************************************/
void dma_cfg(void)
{
        SYSCFG_RMPCR1&=0xFC;                                        //Configure ADC-DMA channel remapping on DMA channel0.
        DMA1_C0CR=0x00;                                        //Reset value                       
        DMA1_C0CR|=0x30;
                                                                                                                          /*
                                      The channel works as regular channel,Memory in increment
                                                                                                                    mode,Circular mode disabled,Date transfer from the peripheral
                                                                                                                          to memory,Half transaction interrupt disabled,Transaction
                                                                                                                          complete interrupt disabled,Channel has't been enabled.
                                                                                                                         */
        DMA1_C0SPR&=0xC7;             /*Clear old priority and memory data size  option,
                                                                                                                          This is recommened by ST peripheral firmware library*/
                                                                                                                          
        DMA1_C0SPR|=0x38;                                                 //Set channel priority level Very high,Transfer size is 16-bit mode
       
        DMA1_C0NDTR=BUFFER_SIZE;            //Cofigure 16 half_word data transfer.
       
        DMA1_C0PARH = (uchar)(ADC1_DR_ADDRESS >> (uchar)8);  //The map of ADC data register high
  DMA1_C0PARL = (uchar)(ADC1_DR_ADDRESS);              //The map of ADC data register low
       
        DMA1_C0M0ARH = (uchar)(BUFFER_ADDRESS >> 8);         //Memory 0 address pointer(HSB)
  DMA1_C0M0ARL = (uchar)(BUFFER_ADDRESS);               //Memory 0 address pointer(LSB)
  
  DMA1_C0CR|=0x01;              //Channel enable.
  DMA1_C0CR|=0x02;                                                         //Enable the Transaction complete interrupt.
       
        DMA1_GCSR&=0x03;               //Timeout is zero.
       
  DMA1_GCSR|=0x01;                                                         //Enable globle DMA module       
}       
//配置时钟
void clock_cfg(void)
{
        //Sysclk configuration
        CLK_SWCR|=0x02;                 //Enable sysclk switch.
        CLK_SWR=0x01;                   //switch to HSI.
       
        CLK_CKDIVR=0x00;                //prescaling factor is 1.
       
        while(CLK_SCSR!=0x01);          //wait for HSI selected as system clock source
        CLK_PCKENR2|=0x10;              //enable the SYSCLK clock to DMA1 peripheral
        CLK_PCKENR2|=0x01;              //enable the SYSCLK clock to ADC peripheral   
}
DMA中断函数如下:
@far @interrupt void DMA1_CHANNEL0_1_IRQHandler (void)
{
         unsigned char i;
         for(i=0;i<16;i++)
         {
                        arr[i]=Buffer[i];     //把采集的16路AD值装入中转数组arr[16]中,
         }
         DMA1_C0SPR&=0xFD;
         ProcessStatus = ENABLE;       
}

QQ截图20130227201757.png (6.54 KB )

硬件仿真结果

硬件仿真结果
沙发
jacky_018|  楼主 | 2013-2-27 20:26 | 只看该作者
本帖最后由 jacky_018 于 2013-3-22 11:52 编辑

软件设置没问题。参考电源忘记连接造成的这一现象。

使用特权

评论回复
板凳
lyt20050326| | 2019-1-4 14:49 | 只看该作者
自投自抢!厉害!
刚遇到这个问题看到你的帖子。
只是我用的便宜一点的单片机,没有专门的参考电压脚。
受电源电压跳动影响比较大,也不知道到底应该怎么解决呢!!!

使用特权

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

本版积分规则

2

主题

12

帖子

1

粉丝