定时器更新事件触发ADC采样

2019-07-20 03:17发布

如题,小弟在探索者的开发板上采集一路频率为1K,上升/下降沿时间均为10uS,占空比可变的,幅度为5V的方波波形,因要求计算此方波的周期,频率,占空比,和上升下降时间,所以设成定时器2定时2uS产生溢出更新事件触发ADC,ADC总转换时间设为0.7uS(3+12个时钟周期,ADC时钟为21M),但是硬件搭好后调试,发现串口调试助手发回来的原始采集数据如图,从图中的数据分析,会不会是STM32根本就不能每1uS采集一次电压,如果要是能的话,根据参考手册中的说法,定时器溢出更新事件产生的上升沿触发ADC,此上升沿上升时间是多少呀,超没超出1uS?如果没超出,那可能是哪里的原因呢?望大侠指教。[mw_shl_code=c,true]#include "sys.h"
#include "delay.h"  
#include "usart.h"   
#include "adc.h"
#include "timer.h"

   
int main(void)
{      
        u16 adcx;
        float voltage_show;
         
        Stm32_Clock_Init(336,8,2,7);    //设置时钟,168Mhz
        delay_init(168);                  //延时初始化  
        uart_init(84,115200);          //初始化串口波特率为115200   
        ADC1_Init();                   //初始化ADC1,单次转换时间60/84uS
          delay_ms(2);
//设置单次溢出时间为2uS,  
          TIM2_Init(1,83);                //初始化TIM2:1分频,84个计数个数
                                          //设置ARR值时,此值要在计数个数的基础上减一,
                                          //因为0也算一个数(参考手册中计数脉冲图)。     

         
  while(1)
      {
         
         
             adcx=Get_ADC1();
             voltage_show=(float)adcx*(3.3/4096);
             voltage_show=15-12*voltage_show;
             printf("%d,V:%f ",adcx,voltage_show);
               
           
         
      }

}[/mw_shl_code]
下面是ADC和TIM2的设置函数,[mw_shl_code=c,true]#include "adc.h"         

//初始化ADC
//以 规则通道 的 不连续 采样模式设置 ADC1_CH5
//以 外部触发->定时器2_TRGO事件 触发ADC采样                                                                                                                                          
void  ADC1_Init(void)
{   
        //先初始化IO口
        RCC->APB2ENR|=1<<8;            //使能ADC1时钟
        RCC->AHB1ENR|=1<<0;            //使能PORTA时钟          
        GPIO_Set(GPIOA,PIN5,GPIO_MODE_AIN,0,0,GPIO_PUPD_NONE);        //   PA5模拟输入,不带上下拉电阻   
                                                                    
         
        RCC->APB2RSTR|=1<<8;           //ADCs复位
        RCC->APB2RSTR&=~(1<<8);        //复位结束         
        ADC->CCR|=1<<16;                //ADCPRE: ADC时钟 ADCCLK=PCLK2/4=84/4=21Mhz
                                        //ADC挂载到APB2总线上,ADC时钟最好不要超过36Mhz
       
          ADC1->CR1=0;                   //CR1设置清零
        ADC1->CR2=0;                   //CR2设置清零
       
          ADC1->CR1&=~(3<<24);          //RES:12位分辨率模式,(15个时钟周期总转换时间)
      
                                        //ADC1->CR1|=(1<<23);     //AWDEN: 在 规则通道 上使能模拟看门狗
                                        //ADC1->CR1|=(1<<9);      //AWDSGL: 在 某单一通道 上使能模拟看门狗
                                        //ADC1->CR1|=(1<<6);      //AWDIE:使能 模拟看门狗中断
                                        //ADC1->CR1|=(5<<0);      //AWDCH:看门狗模拟通道选择:ADC1_CH5
         
          ADC1->CR1&=~(7<<13);          //DISCNUM:设置不连续采样模式下 每次触发 转换的通道数为1
          ADC1->CR1|=1<<11;             //DISCEN: 规则通道的不连续采样使能
                 
  
       
        ADC1->CR2&=~(1<<11);           //ALIGN:右对齐       
        ADC1->CR2|=1<<28;            //EXTEN:上升沿触发
          ADC1->CR2|=6<<24;            //EXTSEL:选择外部触发为定时器2 TRGO事件
          //ADC1->CR2|=1<<10;             //EOCS:设置规则通道 每 单次转换 完成EoC标志 置位;
                                       
                                       
         
        ADC1->SQR1&=~(15<<20);        //L:设置规则通道序列总数为1
        ADC1->SQR3|=5<<0;             //SQ1:设置规则序列第一次转换为通道5                          
         
         
          //设置通道5的采样时间及通道5的看门狗阈值
        ADC1->SMPR2=0;                //所有通道采样时间清空          
        ADC1->SMPR2|=7<<(3*5);         //SMP5:通道5采样时间:3个周期         
                                        //ADC1->HTR|=0xB4C;         //通道5 看门狗高阈值 对应-13V
                                        //ADC1->LTR|=0xd3;                   //通道5 看门狗低阈值 对应+13V
         
         
          ADC1->CR2|=1<<0;                   //ADON: 开启AD转换器
         
         
}                                  
//获得ADC值
//返回值:转换结果
u16 Get_ADC1(void)   
{       
         
        while(!(ADC1->SR&(1<<1)));      //等待转换结束
          return ADC1->DR;                  //返回adc值同时硬件自动清除EoC标志位
         
                  
}[/mw_shl_code]
[mw_shl_code=c,true]


#include "timer.h"


void TIM2_Init(u16 arr,u16 psc)
{
        RCC->APB1ENR|=1<<0;                  //TIM2时钟使能   
        TIM2->ARR=arr;                    //设定计数器自动重装值
        TIM2->PSC=psc;                    //预分频器          
        TIM2->CR1|=1<<7;              //ARPE:设置TIM2_ARR寄存器为缓冲模式
          TIM2->CR1&=~(3<<5);           //CMS:选择计数模式为边沿模式(center-aligned mode selection)
          TIM2->CR1&=~(1<<4);           //DIR:选择计数方向为增加方向
          TIM2->CR1|=1<<2;              //URS: 设置只有计数器溢出才能产生更新
          TIM2->CR1&=~(1<<1);           //UDIS:使能 更新事件
         
         
         
          TIM2->CR2|=2<<4;              //MMS:定时器2配置为主模式,将 更新事件 作为触发输出
          TIM2->CR1|=1<<0;              //CEN:使能定时器2:
         
}
[/mw_shl_code]



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
edmund1234
1楼-- · 2019-07-20 04:22
 精彩回答 2  元偷偷看……
HXYDJ
2楼-- · 2019-07-20 09:09
printf函数会消耗单片机大量时间,把printf函数去掉,把采集的数据存到数组中,然后打断点观察。
济颠进京
3楼-- · 2019-07-20 10:58
本帖最后由 济颠进京 于 2018-10-23 10:21 编辑
HXYDJ 发表于 2018-10-22 15:47
printf函数会消耗单片机大量时间,把printf函数去掉,把采集的数据存到数组中,然后打断点观察。

大神,我按你说的改了程序,程序正常了,谢谢,好人一生平安。就是printf函数的事,
江东猛虎
4楼-- · 2019-07-20 14:56
 精彩回答 2  元偷偷看……

一周热门 更多>