×
单片机 > 单片机程序设计 > 详情

stm32之TIM-高级定时器应用实例二(测量频率和占空比)

发布时间:2020-06-09 发布时间:
|

实验二:PWM输入捕捉实验

实验要求:

高级定时器TIM1接收TIM2产生的PWM,TIM1测量PWM的频率和占空比,并将数据从UART1上发送到上位机,同时上位机通过发送命令改变PWM的占空比和频率。


硬件设计:

       用杜邦线连接TIM2通道一(PA.0)引脚与TIM1通道一(PA.8)引脚。PA.9是USART1的输出引脚,PA.10是USART1的接收引脚,分别接到串口转接板的RXD、TXD。


实验步骤:

初始化USART1,用于与PC端通信

初始化通用定时器TIM2和高级定时器TIM1,前者产生PWM,后者捕获PWM,杜邦线桥接。

初始化SysTick系统滴答计时器,用于任务周期管理

创建一个数据接收队列,接收来自PC端的串口数据

根据报文的格式,解析接收队列里面的数据

         1) H[0x55aa]+LEN[1]+CMD[1]+ARG[1]  //设置占空比

                  example:55 aa 02 01 32      //将占空比设置为50%       

          2) H[0x55aa]+LEN[1]+CMD[1]+ARG[2] //设置频率

                  example:55 aa 03 02 00 0a  //将频率设置为10Hz   


创建USART1.h


#ifndef __USART1_INIT_H__

#define __USART1_INIT_H__

 

#include "stm32f10x.h"

#include

 

int fputc(int ch, FILE *f); //重定向库函数,调用printf时将从串口输出

void USART1_Configuration(void);//打印输出串口初始化

 

#endif

创建USART1.c


#include "USART1.h"

 

 void USART1_Configuration(void)//打印输出串口初始化

 {

    GPIO_InitTypeDef GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

    

    //配置串口1 (USART1) 时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

     //配置串口1接收终端的优先级

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); 

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;             

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

 

    //配置串口1 发送引脚(PA.09)

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);    

    //配置串口1 接收引脚 (PA.10)

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    

    //串口1工作模式(USART1 mode)配置 

    USART_InitStructure.USART_BaudRate = 9600;//一般设置为9600;

    USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位为8个字节

    USART_InitStructure.USART_StopBits = USART_StopBits_1; //一位停止位

    USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位

    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不需要流控制

    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //接收发送模式

    USART_Init(USART1, &USART_InitStructure);

    

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断

    USART_Cmd(USART1, ENABLE);//使能串口

}

 

int fputc(int ch, FILE *f) //重定向c库里面的fputc到串口,那么使用printf时就能将打印的信息从串口发送出去,在PC上同串口助手接收信息

{

//将Printf内容发往串口

USART_SendData(USART1, (unsigned char) ch);

while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);

return (ch);

}

创建TIM.h


#ifndef __TIM_INIT_H

#define __TIM_INIT_H

#include "stm32f10x.h"

 

void GPIO_Configuration(void);//IO口配置

void TIM1_Configuration(void);//高级定时器配置

void TIM2_Configuration(void);//通用定时器配置

 

#endif

创建TIM.c


#include "TIM.h"

 

void GPIO_Configuration(void)//IO口配置

{

    GPIO_InitTypeDef GPIO_InitStructure;

 

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOC的外设时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启TIM1时钟

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置引脚模式为通用推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8; //PA.0:TIM2_CH1 波形输出  PA.8:TIM1_CH1 接收波形

    GPIO_Init(GPIOA, &GPIO_InitStructure); //调用库函数,初始化GPIOC

}

 

#define ADVANCE_TIM TIM1

void TIM1_Configuration(void)//高级定时器配置 捕获PWM

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_ICInitTypeDef  TIM_ICInitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //开启TIM1时钟

 

    /*配置定时器捕获中断的优先级*/

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 

    NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; 

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    TIM_TimeBaseStructure.TIM_Period = 0xFFFF-1; 

    TIM_TimeBaseStructure.TIM_Prescaler =(720-1); //计数器时钟频率为100kHz   72MHz/720=100kHz  

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不需要分频

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数方式 向上计数

    TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复计数器

    TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure); //调用库函数,初始化TIM1

    //捕获通道IC1

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择CH1 PA.8 作为输入信号通道

    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    TIM_ICInitStructure.TIM_ICFilter = 0x00;

    TIM_PWMIConfig(ADVANCE_TIM,&TIM_ICInitStructure);

    //当工作在PWM输入模式时,只需要设置触发信号的那一路即可(用于测量周期)

    //另外一路(用于测量占空比)会有硬件自动设置

    //捕获通道IC2

     /*

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;

    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    TIM_ICInitStructure.TIM_ICFilter = 0x00;

    TIM_PWMIConfig(ADVANCE_TIM,&TIM_ICInitStructure);

    */

    //选择输入捕获的触发信号

    TIM_SelectInputTrigger(ADVANCE_TIM,TIM_TS_TI1FP1);

    //选择从模式:复位模式

    //PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT会被复位

    TIM_SelectSlaveMode(ADVANCE_TIM,TIM_SlaveMode_Reset);

    TIM_SelectMasterSlaveMode(ADVANCE_TIM,TIM_MasterSlaveMode_Enable);

    //使能定时器,计数器开始计数

    TIM_Cmd(ADVANCE_TIM, ENABLE);  

    //使能捕获中断

    TIM_ITConfig(ADVANCE_TIM,TIM_IT_CC1,ENABLE);

}

 

 

void TIM2_Configuration(void)//通用定时器配置

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_OCInitTypeDef TIM_OCInitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2时钟

 

    TIM_TimeBaseStructure.TIM_Period = 1000-1; //从0开始计数 一个周期1000次

    TIM_TimeBaseStructure.TIM_Prescaler =(3600-1); //定时器时钟频率为20kHz  72MHz/3600=20kHz  注意:这个频率不等于pwm的频率   

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不需要分频

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数方式 向上计数

    TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //不使用重复计数器

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //调用库函数,初始化TIM2

    //PWM模式配置

    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

    TIM_OCInitStructure.TIM_Pulse = 300-1;

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

    //初始化输出比较通道一

    TIM_OC1Init(TIM2,&TIM_OCInitStructure);

//使能ARR寄存


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
PIC单片机的多路AD切换程序设计