今天在调试STM32F103c8t6单片机定时器功能时,突然想看看定时器输出最大的频率是多少?为了方便验证在定时器中断中用LED灯翻转来判断定时器的频率。为了保证测试准确性,先测试测试LED直接用IO口驱动时的最大翻转速度。
测试代码如下:

#define LED PCout(13)     // PC13
void LED_Init(void)
{GPIO_InitTypeDef GPIO_InitStucture;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitStucture.GPIO_Pin = GPIO_Pin_13;GPIO_InitStucture.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStucture.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStucture);   GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
int main(void)
{LED_Init();         //初始化与LED连接的硬件接口while(1){LED = !LED;}
}

PC13口为LED控制口,低电平LED亮,高电平LED灭。在循环中翻转LED电平。用示波器测试LED波形如下:

LED的翻转频率为 1.38MHz,初始化的时候IO口频率设置的是50MHz,主程序中就一行代码,为什么LED翻转速度最快才1M多,什么原因造成的?会不会和代码有关系。将LED翻转改为直接给LED赋值试试。

while(1){LED = 0;LED = 1;}

直接给IO口赋值,这时在看看LED的波形。

从波形可以看到LED的频率变成了3MHz多,看来指令不同,执行速度差别很大。
那还没不能再改快点,LED用的是位操作,要更快就直接操作寄存器。直接给输出寄存器赋值来控制PC13口的电平。
重新修改代码如下:

 while(1){GPIOC->ODR=0x0000;GPIOC->ODR= 0x2000;}

测试波形如下:

LED翻转频率变成了4.24MHz,但是波形发生了变化,可以看到低电平的时间28ns,高电平的时间208ns。说明将PC13口置为高电平后,程序执行其他代码花费了180ns的时间。看来要提高LED的翻转速度,代码还有很大的优化空间。但是今天主要是测试定时器,所以在这块就不深究了。下来测试定时器代码。
这块用的是定时器3,在定时器3中断中翻转LED,然后测试波形。看看定时器的速度有多快。
定时器代码如下:


//APB1时钟分频为2  TIM2-7 时钟数为APB1 2倍
// Tout= (arr+1)*(psc+1) / Tclk
void TIM3_Init(u16 arr, u16 psc)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);TIM_TimeBaseInitStructure.TIM_Period = arr;TIM_TimeBaseInitStructure.TIM_Prescaler = psc;TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);TIM_Cmd(TIM3, ENABLE);
}void TIM3_IRQHandler(void)
{if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){TIM_ClearITPendingBit(TIM3, TIM_IT_Update);LED = !LED;}
}int main(void)
{LED_Init();         //初始化与LED连接的硬件接口TIM3_Init(4999,7199);  // 5000 * 7200 /72M =500mswhile(1){}
}

定时器3定时500ms,在定时中断中翻转LED电平。测试波形如下:

由波形可以看出LED的翻转频率为1K,周期500ms。说明定时器定时是比较准确的。
下来缩短定时器时间,定时器初始化代码改为:

TIM3_Init(1,7199);       // 2 * 72 /72M = 0.2ms

继续测试,波形如下:

频率为2.5K,周期为200us。下来将预分频值缩小百分之一。初始化改为:

TIM3_Init(1,71);      // 2* 72 / 72M =2us

测试波形如下:

频率为250K,周期为2us。看来设置理论计算的实际输出一样。
下来再将预分频值缩小十分之一:

TIM3_Init(1,7);           // 2* 9 / 72M = 200ns

测试波形如下:

频率为313K,周期为1.6us,频率并不是刚才的10倍,什么原因引起的?根据刚才测试LED经验来看,应该是代码的问题引起的。那么在中断中将LED翻转改为寄存器操作看看。

void TIM3_IRQHandler(void)
{if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){TIM_ClearITPendingBit(TIM3, TIM_IT_Update);GPIOC->ODR=0x0000;GPIOC->ODR= 0x2000;}
}


可以看出优化代码后,频率有提高,但是变化还是不大。继续优化代码,由于程序中只用了定时器3一个中断,所以在中断函数中就不判断标志位了,直接将标志位清0。清标志位代码也改为直接操作寄存器。

void TIM3_IRQHandler(void)
{TIM3->SR=0x0000;GPIOC->ODR=0x0000;GPIOC->ODR= 0x2000;
}

测试波形如下:

可以看出,这次频率有了明显得提高,频率2.4MHz,高电平时间388ns,低电平时间28ns。低电平时间和刚测IO直接翻转测试的时间一样,说明将PC13口置高后程序执行其他代码花费了时间。

TIM3_Init(1,71);      // 2* 72 / 72M =2us
TIM3_Init(1,7);          // 2* 9 / 72M = 200ns

刚才预分频值为71的时候时候,频率为250K,我们将预分频值缩小为1/10,那么频率应该增大10倍。所以预分频值设置为7的时候,频率理论值应该为2.5MHz,实际测试值为2.4MHz,说明理论计算的值是正确的,定时器应该实际上也能输出这么高的频率,但是由于代码的原因导致不能正真观察到输出的频率。所以想要真正观察到实际输出频率,代码就得直接用汇编来实现了。
这块可以理论计算下最大输出频率,假如高电平的时间和低电平的时间一样是28ns,那么周期就是56ns,频率就为17.86MHz。说明理论上定时器输出频率可以达到十几MHz。但是由于代码原因我们不能验证这个,以后有机会了可以在验证下。
看来在实际应用中想要定时器输出更高频率,在写代码的时候就得好好优化.通过上面测试也发现,同样的功能,不同的操作方法对代码的执行效率影响很大。在以后写程序的时候不能仅仅实现功能就行,还要注意代码的执行效率。

STM32F103定时器输出频率测试相关推荐

  1. STM32F103定时器解码PT2262

    STM32F103定时器解码PT2262 项目场景: 问题描述: 解决方案: 项目场景: 使用PT2262作为遥控器,VS838红外管接收信号,STM32F103解码 问题描述: PT2262遥控器如 ...

  2. STC15f2k60s2C语言定时器2,STC15F2K60S2 定时器2测试C.doc

    STC15F2K60S2 定时器2测试C //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译 //假定测试芯片的工作频率为18.432MHz #include "stc ...

  3. 国产 MCU AT32F403A 替换 STM32F103 can通讯测试

    第九章AT32F403A替换stm32f103 can通讯测试 前言 此文章是使用AT32F403A的开发板去跑stm32f103的can通讯功能的测试情况 硬件 硬件方面使用的是自己画的板子,使用的 ...

  4. STM32F103定时器详解

    STM32F103系列的单片机一共有11个定时器,其中: 2个高级定时器 4个普通定时器 2个基本定时器 2个看门狗定时器 1个系统嘀嗒定时器 除去看门狗定时器和系统滴答定时器的八个定时器列表; 8个 ...

  5. STM32F103定时器输入捕获功能

      STM32F103单片机的定时器不仅能输出PWM波,而且还能捕获输入的PWM波.可以通过定时器的捕获功能测量输入PWM波的周期和占空比.其中定时器的输入捕获功能如下:   在输入捕获模式下,当检测 ...

  6. [转]stm32 sdio写入速度 SD卡【好文章】[F1开发板通用] 战舰STM32F103开发板 SDIO写入速度测试(使用FATFS)

    http://www.openedv.com/forum.php?mod=viewthread&tid=94284 http://www.openedv.com/forum.php?mod=v ...

  7. 数字电路使用555定时器,74163,74194设计跑马灯电路

    设计内容: (1) 以555定时器为核心器件,自主设计一套时钟脉冲发生电路(推荐学生设计基于多谐振荡器的时钟发生电路): (2) 以移位寄存器为核心器件,自主设计一套基于时钟信号的跑马灯控制系统,其时 ...

  8. STM8单片机定时器驱动的深度解析

    上一节给大家介绍了基于标准库STM8单片机GPIO的驱动,本节课主要给大家介绍一下STM8定时器的驱动. 我们先打开STM8L10x单片机的规格书,简单的了解一下STM8L10X单片机的定时器功能. ...

  9. MFC Timer定时器

    知识点:定时器Timer创建定时器销毁定时器代码测试一. 创建定时器 UINT SetTimer(HWND hWnd, // 指定关联定时器的窗口句柄,在MFC版将省略此参数 UINT nIDEven ...

最新文章

  1. 在 PHP 中养成 7 个面向对象的好习惯
  2. python工具是什么-python有什么好用的持续集成工具么?
  3. GraphPad Prism:如何在轴上放置一个或多个缺口?
  4. Hibernate第一次课(1)
  5. ajax联系人数,setInterval定时调用ajax实现在线人数统计
  6. 【OS学习笔记】三十五 保护模式十:中断描述符表、中断门和陷阱门
  7. 【转】Microsoft Cloud全新认证体系介绍
  8. 【leetcode】104. Maximum Depth of Binary Tree
  9. mysql 太多字段 排除某一列_Atitit 数据库排除某一列 字段 显示
  10. 数据库-结构化查询语言SQL概述
  11. android局部布局替换,android – 子片段替换父片段根布局
  12. 将截断字符串或二进制数据。
  13. IE9以下不支持placeholder属性
  14. 为什么使用MATLAB的imnoise函数添加高斯噪声时要将方差除以255^2
  15. distpicker动态赋值问题
  16. ELK抓取AWS-ELB日志的logstash配置文件
  17. MFC对话框/控件下属性中的事件变成空白?
  18. 天耀18期 -09.数组-排序【作业】.doc
  19. 两个年月日怎么相减_(excle可以计算日期差值吗)excel表中,两个日期相减如何得出相差年月...
  20. CTF中Crypty(密码类)入门必看

热门文章

  1. VS.NET(C#)--1.4项目与解决方案
  2. 【总结】实现点击累加效果的几种方式对比
  3. Codeup1085: 阶乘的和
  4. 守住你自己的“沉香”
  5. 【Java】身份证的验证
  6. ApiPost报TypeError: Cannot read property ‘oauth‘ of undefined的解决方案
  7. app测试过程和重点关注内容
  8. dbutils mysql_使用DBUtils控制mysql事务
  9. api 另一窗体 之上_12 个设计 API 的安全建议,不要等出事儿了“捶胸顿足”
  10. CSS 布局 - Overflow