历史上的今天
今天是:2025年08月20日(星期三)
2019年08月20日 | stm32之TIM-高级定时器应用实例二(测量频率和占空比)
2019-08-20 来源:eefocus
实验二: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寄存器预装载 TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable); //使能定时器,计数器开始计数 TIM_Cmd(TIM2, ENABLE); //主动输出使能 TIM_CtrlPWMOutputs(TIM2,ENABLE); } 创建SystemTick.h #ifndef __SYSTEMTICK_INIT_H_ #define __SYSTEMTICK_INIT_H_ #include "core_cm3.h" void MsTick_Updata(void); int If_TimeOut(uint32_t* oldtick,uint32_t diff_tick); int Tick_Updata(uint32_t* tick); void MsTick_Updata(void); #endif //__SYSTEMTICK_INIT_H 创建SystemTick.c #include "SystemTick.h" __IO uint32_t OT_Sys_tick=0; // 系统tick 1ms void MsTick_Updata(void) // 系统滴答定时器中断里 1ms调用一次 { OT_Sys_tick++; } static uint32_t get_OT_sys_tick(void) { return OT_Sys_tick; } int Tick_Updata(uint32_t* tick) { uint32_t ticknow; *tick=get_OT_sys_tick(); return 1; } int If_TimeOut(uint32_t* oldtick,uint32_t diff_tick) // 1--超时 0--没有超时 { uint32_t ticknow; uint32_t diff; ticknow=get_OT_sys_tick(); diff=ticknow-(*oldtick); return diff > diff_tick; } 创建UartComm.h #ifndef __UARTCOMM__H_ #define __UARTCOMM__H_ #include "core_cm3.h" #define CMD_SETDUTYCYCLE 0x01 #define CMD_SETFREQUENCY 0x02 typedef struct{ u8 step; //报文解析的步调 u8 cmd; //报文的命令 u16 datalen; //报文的数据长度 u16 reccnt; //已接收的长度 u8 argbuf[50]; //报文命令参数保存的缓存 }OrderStruct; u8 OrderParser(OrderStruct* pOS,u8 ch);
史海拾趣
|
学设计第一个要认识到的就是设计不是艺术。我就是一开始没有分清这个概念,在第一次上设计课时可苦大了。设计是沟通,是传达,而艺术是表现,是创作。这并不是说设计里没有表现的成份,更不是说艺术是不在乎沟通的。但是两者放在这两项上的重视是有 ...… 查看全部问答> |
|
用L293B 驱动一个电机, 要求:电机可以正反转,有快慢。 都是自动控治的。 程序里不用写电机快慢程序, 只是通过对L293B的输入脚来控治电机这我不会接了, … 查看全部问答> |
|
1、判断极性首先将万用表拨在R×1KΩ挡,用万用表测量时,若某一极与其它两极阻值为无穷大,调换表笔后该极与其它两极的阻值仍为无穷大,则判断此极为栅极(G)。其余两极再用万用表测量,若测得阻值为无穷大,调换表笔后测量阻值较小。在测量阻值 ...… 查看全部问答> |
|
请教PB->Platform->Settings->Enable full Kernel Mode 如题:PB->Platform->Settings->Enable full Kernel Mode(no IMGNOTALLKMODE=1) 以前的工程一直选择这个选项,从来没想过是做什么的 前两天新做个工程,忘记加这个选项,编译后系统不报错,但是下到板子上,系统好象缺少explore.exe一样 后来 ...… 查看全部问答> |
|
很奇怪的问题 wince 串口测试应用程序 writefile(...)函数没有执行完就失败了,然后程序死掉了。 串口测试的writefile(...)函数没有执行完就失败了,没有任何返回结果。writefile的下一个语句做断点,没有执行到。 if(hComm!=INVALID_HANDLE_VALUE&&dwCharToWrite!=0) { &nbs ...… 查看全部问答> |
|
关于nk.bin :error opening file -no such file or directory问题 大家好。我现在在虚拟机上建立Wince系统。建立了虚拟机以后。使用USBoot将U盘以HDD(ZIP也试过)模式格式化为引导盘,将C:\\Program Files\\Microsoft Platform Builder\\6.00\\cepb\\utilities下的CepcBoot.144文件放入WinImage软件中并选择U盘,利 ...… 查看全部问答> |
|
禁产品在远古时代就已经存在,它作为人身财产安全防范的首道防线,是人们生活、工作的必备品。从一把锁、一道门等机械产品发展到网络化、集成化、智能化的现代门禁产品,可谓经历了千锤百炼,才练就出如今的本领。 今天的门禁产品,已经从单纯 ...… 查看全部问答> |
|
uboot-2009.08.tar.bz2移植到TQ2440 依据上几次搭建的环境进行uboot的移植,出现了一些错误,我特此做出一些总结,已经将编译器转换到旧一点的arm-linux-gcc-4.3.2,具体的原因是为什么,我查找了天嵌的网站说需要转换到3.4版本的编译器,因此我改用了友善之臂的uboot-2009.08.tar.bz2 ...… 查看全部问答> |
|
您知道“软文”的含义吗?什么,不知道。赶紧百度一下吧,别被OUT了 [ 本帖最后由 longxtianya 于 2011-11-6 20:19 编辑 ]… 查看全部问答> |




