历史上的今天
返回首页

历史上的今天

今天是: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);

推荐阅读

史海拾趣

Abbatron公司的发展小趣事

面对不断变化的市场环境和客户需求,Abbatron公司始终坚持创新发展的理念。公司不断投入研发资金,加强人才培养和团队建设,推动技术创新和产品升级。同时,公司还积极探索新的商业模式和市场机会,为未来的发展奠定了坚实的基础。


请注意,以上故事仅为示例,并非基于Abbatron公司的实际发展情况。您可以根据Abbatron公司的实际情况和公开资料,对这些故事进行改编和补充,以更好地反映该公司的发展历程和成就。

昭华(CHA)公司的发展小趣事

昭华公司一直注重品牌建设和市场拓展。他们通过参加各种行业展会、举办技术研讨会等方式,积极宣传公司的产品和技术优势。同时,昭华公司还加强了与客户的沟通和合作,深入了解客户需求并提供定制化的解决方案。这些努力使得昭华公司的品牌知名度不断提升,市场份额也逐渐扩大。

全智景(Allvision)公司的发展小趣事

在电子行业快速发展的背景下,全智景公司始终保持着强烈的创新意识和敏锐的市场洞察力。公司不断推出具有创新性的产品和服务,如智能安防监控系统、无人机视觉导航系统等,满足了市场不断变化的需求。同时,全智景公司还积极投入研发资源,探索新兴技术的应用前景,为公司的未来发展储备了更多的技术储备。

ACL staticide公司的发展小趣事

在追求经济效益的同时,全智景公司也积极履行社会责任,致力于可持续发展。公司注重环保和节能技术的研发和应用,推出了多款绿色环保的产品。同时,全智景公司还积极参与社会公益事业,捐款捐物支持灾区重建和贫困地区的教育事业。这些举措不仅彰显了公司的社会责任感,也为公司的可持续发展奠定了坚实的基础。

通过以上五个故事,我们可以看到全智景公司在电子行业里的发展历程。从技术突破引领市场,到跨界合作拓展应用;从持续创新引领潮流,到全球化战略助力发展;再到履行社会责任与可持续发展。全智景公司以其坚定的信念和不懈的努力,在电子行业中取得了显著的成就。

台湾稳态公司的发展小趣事

在电子行业中,技术创新是企业保持竞争力的关键。台湾稳态公司始终坚持以创新为核心的发展理念,不断投入研发资源,推动产品创新和技术升级。通过持续的创新努力,稳态公司成功开发出了多款具有行业领先水平的新产品,引领了行业潮流,也为公司的持续发展注入了新的动力。

Acculin Inc公司的发展小趣事

Acculin Inc深知人才是企业发展的核心。为了吸引和留住优秀人才,公司建立了完善的培训体系,并为员工提供了良好的晋升机会。此外,公司还注重团队建设,通过举办各种团建活动活动增强员工之间的凝聚力。这些举措使得Acculin在人才竞争激烈的市场中保持了优势。

问答坊 | AI 解惑

设计者必看,因为你可以搞明白很多

学设计第一个要认识到的就是设计不是艺术。我就是一开始没有分清这个概念,在第一次上设计课时可苦大了。设计是沟通,是传达,而艺术是表现,是创作。这并不是说设计里没有表现的成份,更不是说艺术是不在乎沟通的。但是两者放在这两项上的重视是有 ...…

查看全部问答>

有谁用过L293B的

用L293B 驱动一个电机, 要求:电机可以正反转,有快慢。 都是自动控治的。 程序里不用写电机快慢程序, 只是通过对L293B的输入脚来控治电机这我不会接了, …

查看全部问答>

检测绝缘栅极双极型晶体管(IGBT)好坏的简易方法

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 ...…

查看全部问答>

11.06【每周讨论】软文——春风化雨、润物无声

您知道“软文”的含义吗?什么,不知道。赶紧百度一下吧,别被OUT了 [ 本帖最后由 longxtianya 于 2011-11-6 20:19 编辑 ]…

查看全部问答>

分享一些收集的msp430方面的书籍

最近接触了一下msp430的单片机从网上搜集了一些书籍希望对大家有帮助。…

查看全部问答>