你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

求大神帮忙stm32中为什么用TIM3生成的PWM,再用tim5去检测,频...

[复制链接]
不过四级不改头像 提问时间:2017-7-7 10:46 /
为什么在几十k的频率误差都有几k,希望大神给点建设性指导

收藏 评论5 发布时间:2017-7-7 10:46

举报

5个回答
MrJiu 回答时间:2017-7-7 11:05:20
你这里的频率是一段时间内固定???还是任意时间都是变化的???
david10000 回答时间:2017-7-7 13:04:03
可以把程序贴出来,你要用TImer5来检测,你Timer5 检测的cycle要比timer3快才行的
不过四级不改头像 回答时间:2017-7-8 12:13:53
MrJiu 发表于 2017-7-7 11:05
你这里的频率是一段时间内固定???还是任意时间都是变化的???

固定的,用输入捕获去测
不过四级不改头像 回答时间:2017-7-8 12:14:14
david10000 发表于 2017-7-7 13:04
可以把程序贴出来,你要用TImer5来检测,你Timer5 检测的cycle要比timer3快才行的 ...

嗯嗯,这个我知道
不过四级不改头像 回答时间:2017-7-8 12:15:25
时钟:#include "timer.h"
#include "usart.h"
          
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
        GPIO_InitTypeDef         GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef        TIM_OCInitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);                             //①使能定时器3时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);                       //Timer3部分重映射  TIM3_CH2->PB5   

  //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形        GPIOB.5
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                     //TIM_CH2
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;               //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);                        //初始化GPIO

  //初始化TIM3
        TIM_TimeBaseStructure.TIM_Period = arr;                       //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =psc;                     //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;                  //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //TIM向上计数模式
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);               //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
       
        //初始化TIM3 Channel2 PWM模式         
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;             //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高
        TIM_OC2Init(TIM3, &TIM_OCInitStructure);                      //根据T指定的参数初始化外设TIM3 OC2

        TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);             //使能TIM3在CCR2上的预装载寄存器
        TIM_Cmd(TIM3, ENABLE);                                        //使能TIM3
       

}

/******************************************************************************
定时器5通道1输入捕获配置:
①时钟,IO口使能,配置PA0为下拉输出
②配置定时器5,确定捕获参数,上升沿捕获,不分频
③中断分组初始化,使能时钟
④编写中断服务函数:
   定义捕获标志位:完成标志(1位)+捕获上升沿标志(2位)+溢出次数(6位)
         其功能前两位主要判断上升沿和下降沿触发中断,后六位主要是进行定时器溢出后的处理
         当溢出时间长时进行溢出次数计算。
********************************************************************************/
TIM_ICInitTypeDef  TIM5_ICInitStructure;

void TIM5_Cap_Init(u16 arr,u16 psc)
{         
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);         //使能TIM5时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
       
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;             //PA0 清除之前设置  
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;          //PA0 输入  
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        GPIO_ResetBits(GPIOA,GPIO_Pin_0);                                                           //PA0 下拉
       
        //初始化定时器5 TIM5         
        TIM_TimeBaseStructure.TIM_Period = arr;                      //设定计数器自动重装值
        TIM_TimeBaseStructure.TIM_Prescaler =psc;                          //预分频器   
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;      //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);              //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
  
        //初始化TIM5输入捕获参数
        TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1;                //CC1S=01         选择输入端 IC1映射到TI1上
        TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;           //上升沿捕获
        TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
        TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;                 //配置输入分频,不分频
        TIM5_ICInitStructure.TIM_ICFilter = 0x00;                        //IC1F=0000 配置输入滤波器 不滤波
        TIM_ICInit(TIM5, &TIM5_ICInitStructure);

        //中断分组初始化
        NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;              //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //先占优先级2级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;           //从优先级0级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);                              //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器        
        TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);          //允许更新中断 ,允许CC1IE捕获中断       
  TIM_Cmd(TIM5,ENABLE );                                              //使能定时器5
}

u8  TIM5CH1_CAPTURE_STA=0;        //输入捕获状态        完成标志+捕获上升沿标志+溢出次数(6位)                                           
u16        TIM5CH1_CAPTURE_VAL;          //输入捕获值

//定时器5中断服务程序         
void TIM5_IRQHandler(void)
{
        if((TIM5CH1_CAPTURE_STA&0X80)==0)                          //还未成功捕获       
        {          
                if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)         
                {            
                                if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
                                {
                                        if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                                        {
                                                TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
                                                TIM5CH1_CAPTURE_VAL=0XFFFF;
                                        }
                                        else
                                        {
                                                TIM5CH1_CAPTURE_STA++;
                               
                                        }
                                }         
                }
                       
          if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)             //捕获1发生捕获事件
                {       
                                if(TIM5CH1_CAPTURE_STA&0X40)                                        //捕获到第二个上升沿                
                                {                                 
                                        TIM5CH1_CAPTURE_STA|=0X80;                                        //标记成功捕获到一次高电平脉宽
                                        TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
                                        TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);    //CC1P=0 设置为上升沿捕获
                                }
                                else                                                                  //还未开始,第一次捕获上升沿
                                {
                                        TIM5CH1_CAPTURE_STA=0;                        //清空
                                        TIM5CH1_CAPTURE_VAL=0;
                                        TIM_SetCounter(TIM5,0);
                                        TIM5CH1_CAPTURE_STA|=0X40;                                        //标记捕获到了上升沿
                                        //TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);                //CC1P=1 设置为下降沿捕获
                                }                    
                }                                                                                   
        }

    TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}


主函数
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
/*
实现功能:通过WE_UP按键输出高电平,利用TIM5的通道1(PA0)做为输入捕获,
          通过串口打印出高电平时间
*/

extern u8   TIM5CH1_CAPTURE_STA;                //输入捕获状态                                                   
extern u16        TIM5CH1_CAPTURE_VAL;          //输入捕获值       
int main(void)
{               
        u32 temp=0;
        float Hz=0;
        delay_init();                     //延时函数初始化          
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);         //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        uart_init(115200);                                     //串口初始化为115200
        TIM3_PWM_Init(899,35);                            //产生2分频,频率40khz的脉冲波  F=72M/(arr+1)*(psc+1)
        TIM5_Cap_Init(0XFFFF,0);                                //以72Mhz的频率计数
           while(1)
        {
                TIM_SetCompare2(TIM3,500);       
                delay_ms(10);                          
                if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿
                {
                        temp=TIM5CH1_CAPTURE_STA&0X3F;
                        temp*=65536;                       //溢出时间总和
                        temp+=TIM5CH1_CAPTURE_VAL;         //得到总的时间
             temp/=72;
                        Hz=1000.0/temp;
                        printf("HIGH:%d us\r\n",temp);     //打印总的时间
                        printf("f:%f khz\r\n",Hz);     //打印总的时间       
                        TIM5CH1_CAPTURE_STA=0;             //开启下一次捕获
                }
        }
}

欢迎指导、、

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版