实验二: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寄存
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』