打印
[开发工具]

请问一个问题 关于定时采样的,谢谢

[复制链接]
2522|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
heqinlong|  楼主 | 2009-3-15 01:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如果我想把采样率设在20K
我想有一下办法:
1:用定时器作为DMA触发源,频率20K,触发一次,把数据从ADC中放入内存。

2:用ADC作为DMA触发源 但是ADC触发源使用定时器。

再一个 我看到ADC1有一个TIM1_DCR TIM1_DMAR 这个貌似和DMA相关 请问是个啥东东啊 谢谢!
沙发
成成| | 2009-3-15 02:35 | 只看该作者

这应该没有问题!

你可以用定时器的PWM输出作为ADC的触发输入,实现20K采样,

另外设置ADC模块的DMA使能,使之AD转换结束之后,直接由DMA把数据搬移到内存;

使用特权

评论回复
板凳
heqinlong|  楼主 | 2009-3-15 02:43 | 只看该作者

您说 使用PWM作为触发 那么需要在外部连线吧?

好想ADC可以直接使用内部的TIM的信号触发吧。。。
DMA貌似都要用到

使用特权

评论回复
地板
成成| | 2009-3-15 03:00 | 只看该作者

不需要外部连线,内部处理的

不需要外部连线,内部处理的

使用特权

评论回复
5
heqinlong|  楼主 | 2009-3-15 04:56 | 只看该作者

很奇怪 AD采数据后 通过DMA后 丢失一半的数据 这是为啥呢?

很奇怪 AD采数据后 通过DMA后 丢失一半的数据 这是为啥呢?

使用特权

评论回复
6
香水城| | 2009-3-15 11:12 | 只看该作者

丢失一半的数据?当然是你的设置有问题

不为啥~~~~

使用特权

评论回复
7
heqinlong|  楼主 | 2009-3-15 12:31 | 只看该作者

香版主,麻烦您看看我的配置 我用的库

 
   /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  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_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channel10 configuration */ 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_1Cycles5);

  /* Enable ADC1 DMA */
   ADC_DMACmd(ADC1, ENABLE);

  
  /* Enable ADC1 */
   ADC_Cmd(ADC1, ENABLE);

  /* Enable ADC1 reset calibaration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibaration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));
     
  /* Start ADC1 Software Conversion */ 
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
 
 
 
  /* DMA1 channel1 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 512;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  
  /* Enable DMA1 channel1 */
   DMA_Cmd(DMA1_Channel1, ENABLE);

使用特权

评论回复
8
heqinlong|  楼主 | 2009-3-15 17:19 | 只看该作者

解决了!!

是KEIL的问题
换IAR后正常
莫非是KEIL的BUG 还是STLINK2和KEIL不兼容呢?
打算入手JLINK

使用特权

评论回复
9
成成| | 2009-3-19 09:12 | 只看该作者

keil应该没有问题

keil应该没有问题,我就是在Keil下进行的做的

使用特权

评论回复
10
heqinlong|  楼主 | 2009-3-19 11:06 | 只看该作者

同样的程序 我在IAR下OK

同样的程序 我在IAR下OK
在KEIL下 不行。见鬼了。。。

楼上的朋友 您也做过和我类似的东西?您在KEIL下 正常么? 可以看看您的配置么

使用特权

评论回复
11
成成| | 2009-3-23 11:03 | 只看该作者

我做过

以下是我的配置,你参考一下

//////////////////////////////////////////////////////////////////
/*
************************************************************
    函数名        Timer4_Configurate
    功能        定时器4的配置函数
    输入参数    unSampRate    每个周波的采样点数
    输出参数    无
    变量        无
************************************************************
*/
void Timer4_Configurate(UINT16 unSampRate)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
    TIM_OCInitTypeDef TIM_OCInitStructure; 
    
    switch(unSampRate)
    {
        case 16:    unSampRate = 5000;    break;
        case 20:    unSampRate = 4000;    break;
        case 32:    unSampRate = 2500;    break;
        case 64:    unSampRate = 1250;    break;
        case 128:    unSampRate = 625;    break;
        default:    unSampRate = 0xFFFF;
    }
        
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 , ENABLE);            // 使能各个功能模块的的时钟
    TIM_DeInit(TIM4);
    
    // 配置时间基
    if(unSampRate == 0xFFFF)
    {
    // 测试下的设置
    // 72,000,000 / 7200 / 4 = 2500Hz
    // 因此最后的时钟就完全由TIM_Period决定,
    TIM_TimeBaseStructure.TIM_Period = 250-1;
    TIM_TimeBaseStructure.TIM_Prescaler = 7199;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV4;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
    }else
    {
    TIM_TimeBaseStructure.TIM_Period = unSampRate-1;                // 周期    
    TIM_TimeBaseStructure.TIM_Prescaler = 18-1;                        // 预分频
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;            // 输入时钟1分频,72MHz/1, 时基输出频率=72/18=4MHz
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        // 向上递增模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
    }

    // 通道4:输出比较模式
    TIM_OCInitStructure.TIM_OCMode = TIM1_OCMode_PWM1; 
    TIM_OCInitStructure.TIM_Channel = TIM_Channel_4; 
    TIM_OCInitStructure.TIM_Pulse = 10; 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 
    TIM_OCInit(TIM4, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
    
    // 使能定时器4
    TIM_Cmd(TIM4, ENABLE);    
}

/*
************************************************************
    函数名        ADC_Configrate
    功能        ADC模块配置
    输入参数    无
    输出参数    无
    变量        无
************************************************************
*/
void ADC_Configrate(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    ////////////////////////////////////////////////////////
    // 配置定时器4,使之能够根据采样率的要求产生定时中断
    // 并触发ADC模块的运行
    Timer4_Configurate(ADSAMPIONT);
    //Timer4_Configurate(0);

    // 配置ADC的中断向量
    NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    ////////////////////////////////////////////////////////
    // DMA 通道1配置
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);                        // 使能DMA的时钟
    DMA_DeInit(DMA_Channel1);                                                // 复位
    DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;                // 外围设备的基址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&tAD_Cur;                    // 存储空间的基址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                        // 方向:外围->内存
    DMA_InitStructure.DMA_BufferSize = ADC_CONVNUM;                            // 传输的数目
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外围设备地址不增加
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                    // 内存空间地址加1
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;    // 外围设备的字长
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;            // 内存空间的字长
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                            // 模式:循环缓冲
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                        // 优先级:高
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                            // 没有使用内存到内存方式
    DMA_Init(DMA_Channel1, &DMA_InitStructure);
    DMA_Cmd(DMA_Channel1, ENABLE);                                            // 使能DMA通道1

    ////////////////////////////////////////////////////////
    // 模拟量输入管脚的配置
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                    // 时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3;            // 选中的管脚
    //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    ////////////////////////////////////////////////////////
    // ADC配置
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2, ENABLE);// 时钟

    ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = ADC_CONVNUM;// 进行规则转换的ADC通道的数目。这个数目的取值范围是1到16
    ADC_Init(ADC1, &ADC_InitStructure);            // ADC1初始化
    ADC_Init(ADC2, &ADC_InitStructure);            // ADC2初始化
    
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_1Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_1Cycles5);    

    ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
    ADC_RegularChannelConfig(ADC2, ADC_Channel_0, 2, ADC_SampleTime_1Cycles5);

    
    ADC_Cmd(ADC1, ENABLE);                        // 使能ADC1
    ADC_ResetCalibration(ADC1);                    // 复位ADC1的校准寄存器
    while(ADC_GetResetCalibrationStatus(ADC1));    // 等待检测校准过程完成
    ADC_StartCalibration(ADC1);                    // 开始校准各个通道
    while(ADC_GetCalibrationStatus(ADC1));        // 等待校准过程完成

    ADC_Cmd(ADC2, ENABLE);                        // 使能ADC2
    ADC_ResetCalibration(ADC2);                    // 复位ADC2的校准寄存器
    while(ADC_GetResetCalibrationStatus(ADC2));    // 等待检测校准过程完成
    ADC_StartCalibration(ADC2);                    // 开始校准各个通道
    while(ADC_GetCalibrationStatus(ADC2));        // 等待校准过程完成

    ADC_ExternalTrigConvCmd(ADC1, ENABLE);        // 采用外部触发方式启动(目前采用定时器4的CC4)
    ADC_ExternalTrigConvCmd(ADC2, ENABLE);        // 采用外部触发方式启动(目前采用定时器4的CC4)
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);        // 使能EOC中断
    ADC_DMACmd(ADC1, ENABLE);                    // 使能ADC1的DMA功能
}

使用特权

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

本版积分规则

4

主题

20

帖子

0

粉丝