OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3047|回复: 0

pwm输入并捕获

[复制链接]

1

主题

8

帖子

0

精华

高级会员

Rank: 4

积分
748
金钱
748
注册时间
2015-9-17
在线时间
60 小时
发表于 2016-2-4 17:10:29 | 显示全部楼层 |阅读模式
最近才开始学习stm32,遇到了很多问题,今天分享一下成果
功能:  1、利用定时器2通道2输出pwm(0~256)
           2、利用串口1改变其占空比,并显示出理论正确值
           3、利用定时器3通道2捕获pwm,并在中断中显示实际测试值
           4、计算中模拟了一个16位捕获状态计数寄存器最高位为高电平状态标置位,次高位为“溢出计数器”溢出位,余下的14位低位用来计数
我用的是战舰开发版,实验中把PA1和PA7相连。

主函数
#include "stm32f10x.h"

#include "time.h"
#include "BEEP.h"
#include "LED.h"

#include "usart.h"       
#include "delay.h"

        u16 current_count=0;//当前计数值(不论是否计数溢出)
        u32 calculate_time=0;//计算高电平时间
       
        u16 capture_state_count=0;//16位模拟寄存器(捕获状态计数寄存器)
       
int main(void)
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
       
        LED_Init();
        beep_Init();//占用GPIOB管脚设置,外设若改变且在beep前使用初始化函数,beep不响       
    delay_init();
       
        uart_init(19200);//可以通过串口一改变pwm的占空比输出       
        PWM_Init(256-1,71,50);
        //TIM_Init(6000,7199);
        Capture_Init(100-1,71);
       
        beep=1;//初始化完毕提示
        delay_ms(100);
        beep=0;
        while(1)
        {
                led1=0;       
                delay_ms(500);
                led1=1;
                delay_ms(500);

        }
}


定时器相关函数文件

#include "time.h"

#include "stm32f10x.h"
#include "sys.h"

#include "delay.h"
#include "usart.h"       

extern  u16 capture_state_count;//16位模拟寄存器(捕获状态计数寄存器)
extern        u16 current_count;//当前计数值(不论是否计数溢出)
extern        u32 calculate_time;//计算高电平时间

/*定时器配置*/
//定时器2
void TIM_Init(u16 TIME_reload,u16 prescaler)     //参数1是重装载值(u16),参数2是与分频系数(u16)    Tout(溢出时间)=(reload+1)(prescaler+1)/Tclk  (Tclk是配置时钟频率,一般为phb1X2的时钟72M)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructre;
        NVIC_InitTypeDef NVIC_InitStructre;
       
        /*1、初始化定时器时钟*/
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
       
        /*2、初始化定时器时基函数*/
        TIM_DeInit(TIM2);
        TIM_TimeBaseInitStructre.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseInitStructre.TIM_Period=TIME_reload;
        TIM_TimeBaseInitStructre.TIM_Prescaler=prescaler;
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructre);
       
        /*3、打开中断并选择中断源*/
        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
        NVIC_InitStructre.NVIC_IRQChannel=TIM2_IRQn;
        NVIC_InitStructre.NVIC_IRQChannelCmd=ENABLE;
        NVIC_InitStructre.NVIC_IRQChannelSubPriority=3;
        NVIC_InitStructre.NVIC_IRQChannelPreemptionPriority=3;
        NVIC_Init(&NVIC_InitStructre);
       
        /*4、打开定时器*/
        TIM_Cmd(TIM2,ENABLE);
}




/*pwm配置*/
void PWM_Init(u16 time_reload,u16 TIM_Prescaler,u16 pluse_reload)//1、时基单元重装载值2、时基单元预分频系数3、输出比较器装载值
{
/*定时器2通道2*/
        //定义结构体变量
        GPIO_InitTypeDef GPIO_InitStructre;
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructre;
        TIM_OCInitTypeDef TIM_OCInitStructre;
        /*1、配置时钟,输出管脚时钟、定时器外设时钟*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
        /*2、管脚配置*/
        GPIO_InitStructre.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStructre.GPIO_Pin=GPIO_Pin_1;
        GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructre);
        /*3、定时器时基单元配置*/
        TIM_TimeBaseInitStructre.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseInitStructre.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseInitStructre.TIM_Period=time_reload;
        TIM_TimeBaseInitStructre.TIM_Prescaler=TIM_Prescaler;
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructre);
        /*4、定时器输出比较单元配置*/
        TIM_OCInitStructre.TIM_OCMode=TIM_OCMode_PWM2;
        TIM_OCInitStructre.TIM_OCPolarity=TIM_OCPolarity_Low;
        TIM_OCInitStructre.TIM_OutputState=TIM_OutputState_Enable;
        TIM_OCInitStructre.TIM_Pulse=pluse_reload;
        TIM_OC2Init(TIM2,&TIM_OCInitStructre);
        /*5、定时器重装值、比较寄存值允许位打开*/
        TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);//允许改变通道2的输出比较寄存器预存值(调节占空比)
        TIM_ARRPreloadConfig(TIM2,ENABLE);             //允许改变定时器的重装载值的预存值(调节周期)
        /*6、定时器打开使能*/
        TIM_Cmd(TIM2,ENABLE);
}



/*捕获配置*/
void Capture_Init(u16 time_reload,u16 TIM_Prescaler)
{
        /*定时器3通道2*/
        GPIO_InitTypeDef GPIO_InitStructre;
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructre;
        TIM_ICInitTypeDef TIM_ICInitStructre;
        NVIC_InitTypeDef NVIC_InitStructre;
        /*1、打开外设时钟及输入管脚时钟*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
        /*2、配置输入管脚*/
        GPIO_InitStructre.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_InitStructre.GPIO_Pin=GPIO_Pin_7;
        GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructre);
        /*3、配置时基单元*/
        TIM_TimeBaseInitStructre.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseInitStructre.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseInitStructre.TIM_Period=time_reload;
        TIM_TimeBaseInitStructre.TIM_Prescaler=TIM_Prescaler;
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructre);
        /*4、配置输入捕获单元*/
        TIM_ICInitStructre.TIM_Channel=TIM_Channel_2;
        TIM_ICInitStructre.TIM_ICPolarity=TIM_ICPolarity_Rising;
        TIM_ICInitStructre.TIM_ICPrescaler=TIM_ICPSC_DIV1;
        TIM_ICInitStructre.TIM_ICFilter=0x00;
        TIM_ICInitStructre.TIM_ICSelection=TIM_ICSelection_DirectTI;
        TIM_ICInit(TIM3,&TIM_ICInitStructre);
        /*5、打开并配置通道2的输入捕获中断*/
        TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC2,ENABLE);//开启更新中断,用于检测电平时间较长,计数器已经重装载的情况
        NVIC_InitStructre.NVIC_IRQChannel=TIM3_IRQn;
        NVIC_InitStructre.NVIC_IRQChannelCmd=ENABLE;
        NVIC_InitStructre.NVIC_IRQChannelSubPriority=3;
        NVIC_InitStructre.NVIC_IRQChannelPreemptionPriority=2;
        NVIC_Init(&NVIC_InitStructre);
        /*6、打开定时器3*/
        TIM_Cmd(TIM3,ENABLE);
       
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2|TIM_IT_Update); //清除中断标志位
}




/*中断服务函数计算高电平时间,其中定义了u16 capture_state_count来模拟一个寄存器,运用位操作来主动捕获*/
void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3, TIM_IT_Update)!= RESET)//计数器跟新溢出
        {
                if(capture_state_count&0x8000)//检测出是在高电平期间溢出,记录溢出次数
                        capture_state_count++;
                if(capture_state_count&0x4000)//“溢出次数“计数器也溢出,提示打印,并清空模拟寄存器
                {
                        printf("溢出错误!!!\n");
                        capture_state_count=0;
                }
        }
        if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!= RESET)//检测出跳变
        {
                if(capture_state_count&0x8000)//前一个状态是高电平,现在已跳变为低电平
                {
                        current_count=TIM_GetCapture2(TIM3);//获取当前计数器值
                        TIM_OC2PolarityConfig(TIM3,TIM_ICPolarity_Rising);//为检测下一个高电平做准备
                        calculate_time=((capture_state_count&0x3fff)*100)+current_count; //计算高电平占用时间,单位微秒
                    printf("高电平实际占用时间:%d us\n",calculate_time);//显示
                        delay_ms(500);
                        capture_state_count=0;//捕获状态计数寄存器清零,为下次检测做准备
                }
                else                                                        //前一个状态是低电平,现在已跳变为高电平
                {
                        TIM_SetCounter(TIM3,0);//清零,以进入高电平为起点,便于计算
                        capture_state_count|=0x8000;//置15位为1,标记现在已经处于高电平阶段
                        TIM_OC2PolarityConfig(TIM3,TIM_OCPolarity_Low);////为检测下一个低电平做准备
                }
        }
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2|TIM_IT_Update); //清除中断标志位
}

第一次发贴,有什么问题请大家指出来

输入pwm并捕获单通道.zip

7.1 MB, 下载次数: 126

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-21 07:50

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表