STM32

时序在数字电路中的作用,就像通信中用到的载波,载波并不起眼,但是很重要。时钟也一样,现象上只是某种频率波峰波谷跳动,一成不变。但是有了它,就像人类的历史有了时间轴一样,什么时候该干什么事才有了可能。程序中发生的事件,能够按照自己的意愿发生。下面就以STM32开发板中最常见的STM32F103系列芯片的时钟为例,介绍一下STM32中的时钟。

时钟作用

说到时钟,你一定会问,这是用来计时的吗?没错,是用来计时的,但这只是它在STM32中的一项功能而已,下面就为你列出了时钟的具体功能。

计时作用(供给某些计数器统计时间);

控制时序(串口数据的传输,只能一位一位的传输);

控制信号(将时钟的上升下降沿作为独特的控制标志)。

STM32时钟模型

STM32内部时钟树

时钟源

时钟源就是产生时钟的电路啦,我们来一起看一下,什么样的电路可以产生时钟。

STM32中的时钟源分为以下五种:

低速内部时钟LSI:频率为40kHz ;
高速内部时钟HSI :频率为8MHz ;
低速外部时钟OSC_32:频率为32.7678kHz ;
高速外部时钟OSC:频率范围4-16MHz ;
时钟输出MCO:为其他设备提供时钟源。

在对时钟频率要求不高的情况下,我们可以选择内部RC振荡器时钟作为单片机工作的时钟源。如果对时钟精度要求较高,我们要选择外部石英晶体振荡器(晶振),作为单片机的时钟源,因为内部时钟用的是模拟电路组成的振荡器,误差较大,在实时性要求比较高的场合(串口通信、IIC通信等)容易造成不可预知的错误。

时钟相对复杂的意义主要是为不同外设提供合适的时钟频率,主要目的是为了节能、低功耗。

高速时钟:用于高速外设I/O、串口通信、SPI等等;

低速时钟:用于低速外设RTC看门狗 ;

倍频器:时钟与外设进行时钟适配。

相关寄存器讲解

PLLSRC
锁相环倍频器时钟源选择
内部高速时钟2分频
外部高速时钟

PLLMUL
锁相环时钟倍频器
将PLLSRC选择的时钟进行倍频,最大不能超过72MHz

PLLXTPRE
锁相环时钟选择
选择外部时钟作为锁相环倍频器时钟源
选择外部时钟2分频后作为锁相环倍频器时钟源

SW
系统时钟选择
选择内部高速时钟作为系统时钟
选择锁相环倍频时钟作为系统时钟
选择外部高速时钟作为系统时钟

AHB
系统时钟分频器

CSS
时钟安全监测单元
当外部时钟意外故障,CSS在短时间内切换到内部高速时钟使单片机工作不中断

RTCCLK
实时时钟时钟源选择
选择锁相环倍频器时钟源128分频作为实时时钟时钟源
选择外部低速时钟作为实时时钟时钟源
选择内部低俗时钟作为实时时钟时钟源

MCO
时钟输出控制
锁相环时钟2分频输出
内部低俗时钟输出
内部高速时钟输出
系统时钟输出

关于APB1、APB2时钟

STM32单片机外设挂接在APB1、APB2两个桥上,但两个桥允许的始终最大频率不相同,APB2最大允许72MHz,APB1最大只允许36MHz,在使用外设时应格外注意时钟,例如串口一挂接在APB2上,其余串口挂接在APB1上,在串口配置时应注意失踪频率的不同造成的波特率配置问题(库函数开发忽略此项内容)。

外部时钟晶体振荡器最好选择8MHz晶振,无论是库函数,还是Keil默认配置启动文件时钟配置均是按照外部晶体振荡器8MHz来进行的配置,系统时钟72MHz,如果采用其他型号的晶体震荡器振还需要自己配置时钟树,对于新手来说可能存在一定的困难。

来源: 无线电杂志

围观 4
1

开篇问大家一个问题:STM32F103默认最高主频为72M,那么,其主频可以达到80M吗? 假如达到80M,程序能正常运行吗?

1、关于MCU主频

首先,还是简单介绍一下MCU主频。一般我们讲的电脑CPU主频,对于MCU来说,其实道理一样,都是指的CPU内核工作的时钟频率。

对于STM8,或者STM32来说,MCU的主频由硬件(晶振)和软件编程决定。

在STM32中,MCU主频一般是通过倍频来实现的。比如72M,等于8M时钟,9倍频(8 x 9 = 72)。

在STM8、32中,我们说的主频时钟和外设时钟,其实是两种不同时钟。

查看MCU「参考手册」STM8的CLK时钟控制章节,STM32的RCC复位和时钟控制章节的时钟树一目了然。

2、STM8主频时钟

在STM8「参考手册」Clock control(CLK)时钟控制章节,详细描述了STM8时钟相关的内容。

从时钟树可以清晰看的出STM8时钟大概有哪些内容。比如STM8S的时钟树:

从时钟树可以看的出,可以得出一些重要信息,如:

  • 内部高速晶振HSI默认16M,外部晶振可选择1 - 24M。
  • STM8主频只能分频,不能倍频。
  • 外设时钟是由主频时钟而来,可单独开启。
  • 时钟频率可选择多种方式输出(CCO)。

STM8主频可以大于16M吗? 这个问题是之前有朋友问过的问题。

当然,答案肯定是可以。为了提高MCU效率,很多人就是将主频进行提高来达到目的。

但是,这里需要注意一个问题:当超过16M主频时钟时,Flash /data EEPROM访问必须配置为1等待状态。

这个在STM8「参考手册」中有明确说明:

For clock frequencies above 16 MHz, Flash /data EEPROM access must be configured for 1 wait state. This is enabled by the device option byte. Refer to the datasheet option bytesection.

3、STM32主频时钟

STM32主频时钟同样也是由硬件(晶振)和软件编程决定。

(STM32F1时钟树)

STM32的时钟可以上面时钟树看得出来,相对STM8要复杂的多。以上还只是STM32F1的,像F4,F7的还更复杂。

从时钟树可以看得出,STM32外部晶振频率是一个范围值,一般硬件就要求在这个范围以内。

STM32一个显著的特点就是增加了倍频这个功能。如果没有倍频功能,我们使用的72M、168M这么高的频率,就需要直接使用上百兆的晶振。

这么能实现吗? 原理上来说,可以实现。但对MCU来说是一个不小的考验。具体原因可能就要问相关的资深工程师了。

1. STM32倍频

STM32的倍频可通过配置对应寄存器(也就是编程)来实现。但一般不建议自己直接通过配置寄存器来实现,参考官网提供例程代码即可。

标准外设库例程:在执行main函数之前,系统就会调用SystemInit函数进行初始化系统时钟(含主频)。

如果外部晶振和例程不一样,修改对应的几个参数即可。比如倍频值,HSI值等。这个阅读一下代码就能明白。

HAL库:可通过STM32CubeMX工具直接配置时钟,简单方便,时钟树勾选一目了然。

2. 主频能超过最大值吗?

如开篇所说,STM32F1主频能超过最大的72M吗?答案是可以的。

但是,超过最大主频,有可能存在潜在的风险。比如:时序紊乱,程序跑飞等。

超频工作需要考虑实际情况和环境因素。比如干扰特别大的环境,一般不建议超频。

我是亲自经历过的,之前公司产品为了提高效率,将主频超过一定值,还是能正常运行,而且投产了的。但是,应用环境相对比较好,而且产品有电源控制(接断电复位)。

3. 超频死机

如果MCU主频超过太多,就会导致程序跑飞,出现死机现象,只能通过工具重新固件。

这个时候直接下载,可能会出现错误,则可借助复位引脚来实现重新下载固件(按住复位引脚,点击下载,释放按键)。

说了这些,主要想强调,只要没有特殊要求,建议参考官网硬件和软件。

本文转自:微信号 - EmbeddDeveloper,作者:strongerHuang,转载此文目的在于传递更多信息,版权归原作者所有。

围观 5
7

STM32学习之启动代码很重要!

demi的头像

最近在写一个人机界面,由于硬件同事布板的问题,必须要用到串口4,先开始我还觉得没什么,就是把USART1改成4以及改下开启时钟和配置引脚。

但是事实证明我的想法是多么愚蠢,调了整整2天,UART4发送很好,但是就是在接收时死活的卡在中断之前,就会进入HardFaultException B HardFaultException。真是百思不得其解,我就一步步调试跟踪,也没有发现任何问题,UART4的配置都是正确的,引脚也都没问题。这两天真是调试的快崩溃了。在网上查询该问题,大家也都没有答案,有些人甚至直接说UART4不能用,说心里话我不相信,别个STM那么大的公司,会推出不能用的功能?

在我最无助的时候,我突然想起我们大学老师的一句话,中断出问题,就多看看启动代码的中断向量部分,多去理解。事实证明老师是对的,我花了半天的时间仔细的看了我的启动代码,乖乖启动代码里面居然没有

IMPORT UART4_IRQHandler

IMPORT UART5_IRQHandler

DCD UART4_IRQHandler

DCD UART5_IRQHandler

而串口1、2、3都有。于是我加上了以上代码,串口成功的进入中断,并且接收到了数据。

  •  高人气的STM32CubeMX软件工具扩展包STM32Cube.AI可生成优化代码,在STM32微控制器(MCU)上运行神经网络
  •  STM32Cube.AI附带即用型软件函数包,包含用于识别人类活动和音频场景分类的代码示例,可立即用于意法半导体参考传感器板和移动应用程序
  •  ST合作伙伴计划和STM32 AI / ML社区的优质合作伙伴为开发者提供支持服务

横跨多重电子应用领域的全球领先的半导体供应商意法半导体 (STMicroelectronics,简称ST;纽约证券交易所代码:STM)借助STM32系列微控制器的市场领导地位,扩展了STM32微控制器开发生态系统STM32CubeMX,增加了先进的人工智能(AI)功能。

AI技术使用经过训练的人工神经网络对运动和振动传感器、环境传感器、麦克风和图像传感器的数据信号进行分类,比传统的手工信号处理方法更加快速、高效。

意法半导体微控制器和数字集成电路产品部总裁Claude Dardanne表示:“ST的新型神经网络开发工具箱正在将AI引入基于微控制器的智能边缘和节点设备,以及物联网、智能楼宇、工业和医疗应用中的深度嵌入式设备。”

现在开发人员可以用STM32Cube.AI将预先训练的神经网络转成可在STM32 微控制器上运行的C代码,调用经过优化的函数库。

STM32Cube.AI附带即用型软件功能包,其中包括用于识别人类活动和音频场景分类的代码示例,可在ST SensorTile参考板和ST BLE Sensor mobile app移动应用程序上立即使用这些代码示例。

ST合作伙伴计划和人工智能(AI)和机器学习(ML)专用社区STM32在线社区内的资质合作伙伴将为开发人员提供技术支持,例如,工程服务。

在2019年1月8日 - 12日拉斯维加斯世界消费电子展CES期间,意法半导体将在酒店包间内使用STM32微控制器演示采用STM32Cube.AI开发的应用程序。

详细技术信息

用户可以在意法半导体的STM32CubeMX MCU配置和软件代码生成生态系统内下载STM32Cube.AI扩展包(型号:X-Cube-AI)

今天,该工具支持Caffe、Keras(带有TensorFlow后台)、Lasagne、ConvnetJS框架和Keil、IAR、System Workbench等IDE开发环境。

FP-AI-SENSING1软件功能包提供支持基于神经网络的端到端运动(人类活动识别)和音频(音频场景分类)应用代码示例。该功能包利用意法半导体的SensorTile参考板在训练之前捕获和标记传感器数据,然后,电路板运行优化神经网络的推论。

ST BLE传感器移动应用可以用作SensorTile的遥控器和显示器。

综合工具箱包括STM32Cube.AI映射工具、在电池供电的小型SensorTile硬件上运行的应用软件示例,以及合作伙伴计划,人工智能和机器学习专用社区为在STM32上实现神经网络提供一条快速、简便的开发途径。

详情访问www.st.com/STM32CubeAI

若想了解AI/ML人工智能机器学习社区,请访问STM32在线社区

若想申请AI/ML ST 合作伙伴计划,请访问ST 合作伙伴计划

若想了解最新的关于STM32神经网络工具集的博客文章,请访问https://blog.st.com/stm32cubeai-neural-networks/

围观 5
21

一、背景

如果你正为项目的处理器而进行艰难的选择:一方面抱怨16位单片机有限的指令和性能,另一方面又抱怨32位处理器的高成本和高功耗,那么,基于 ARM Cortex-M3内核的STM32系列处理器也许能帮你解决这个问题。使你不必在性能、成本、功耗等因素之间做出取舍和折衷。

即使你还没有看完STM32的产品手册,但对于这样一款融合ARM和ST技术的“新生儿”相信你和我一样不会担心这款针对16位MCU应用领域 的32位处理器的性能,但是从工程的角度来讲,除了芯片本身的性能和成本之外,你或许还会考虑到开发工具的成本和广泛度;存储器的种类、规模、性能和容量;以及各种软件获得的难易。

对于在16位MCU领域用惯专用在线仿真器(ICE)的工程师可能会担心开发工具是否能够很快的上手?开发复杂度和整体成本会不会增加?产品上市时间会不会延长?

没错,对于32位嵌入式处理器来说,随着时钟频率越来越高,加上复杂的封装形式,ICE已越来越难胜任开发工具的工作,所以在32位嵌 入式系统开发中多是采用JTAG仿真器而不是你熟悉的ICE。

但是STM32采用串行单线调试和JTAG,通过JTAG调试器你可以直接从CPU获取调试 信息,从而将使你的产品设计大大简化,而且开发工具的整体价格要低于ICE,何乐而不为?

有意思的是STM32系列芯片上印有一个蝴蝶图像,据ST微控制器产品部Daniel COLONNA先生说,这是代表自由度,意在给工程师一个充分的创意空间。

我则“曲解”为预示着一种蝴蝶效应,这种蝴蝶效应不仅会对方案提供商以及终端产品供应商带来举足轻重的影响,而且会引起竞争对手策略的改变……翅膀已煽动,让我们一起静观其变!

二、STM32系列的作用

ARM公司的高性能”Cortex-M3”内核

1.25DMips/MHz,而ARM7TDMI只有0.95DMips/MHz

一流的外设

1μs的双12位ADC,4兆位/秒的UART,18兆位/秒的SPI,18MHz的I/O翻转速度

低功耗

在72MHz时消耗36mA(所有外设处于工作状态),待机时下降到2μA

最大的集成度

复位电路、低电压检测、调压器、精确的RC振荡器等

三、STM32F10x重要参数

  •  2V-3.6V供电

  •  容忍5V的I/O管脚

  •  优异的安全时钟模式

  •  带唤醒功能的低功耗模式

  •  内部RC振荡器

  •  内嵌复位电路

  •  工作温度范围:-40℃至+85℃或105℃

四、性能特点

基本型STM32F101:36MHz CPU,多达16K字节SRAM,1x12位ADC温度传感器

增强型STM32F103:72MHz CPU,多达20K字节SRAM,2x12位ADC 温度传感,PWM定时器,CAN,USB。

来源:网络

围观 23
66

波特率的计算

STM32下的波特率和串口外设时钟息息相关,USART 1的时钟来源于APB2,USART 2-5的时钟来源于APB1。在STM32中,有个波特率寄存器USART_BRR,如下:

STM32串口波特率通过USART_BRR进行设置,STM32的波特率寄存器支持分数设置,以提高精确度。USART_BRR的前4位用于表示小数,后12位用于表示整数。但是它还不是我们想要设置的波特率,想要设置我们串口的波特率大小还需要进行计算。

其实有关波特率的计算是下面这一条表达式:

从上面的表达式,我们引入了一个新量USARTDIV,它表示对串口的时钟源fck进行分频。假设我们已知道了波特率和fck时钟频率的大小,那么通过上式便可以计算出USARTDIV的具体大小,然后再通过USART的值大小对波特率寄存器进行设置。

USARTDIV通过上面的表达式得出,是一个带有小数的浮点数(如27.75)。将小数部分和整数部分分开,分别得到一个整数值n(如27)和一个小数值m(如0.75)。有了这两个值我们便可以填写USART_BRR寄存器进而设置我们串口波特率大小了。

将整数部分m(27 = 0x1B)直接写入USART_BRR的后12位部分;将小数部分n乘以16后得到的整数值(如0.75 x 16 = 12 = 0xC)写入USART_BRR前4位部分,最后USART_BRR的值为0x1BC。

注意:如果小数部分乘以16之后仍带有小数,则要四舍五入去除小数部分得到一个新的整数,再将其写入USART_BRR的前四位。

为什么在计算波特率的公式中要乘以16?

​我们知道串口通信是通过TXD和RXD这两条线进行通信的,当接收器的RXD连接着发送器的TXD,接收器的TXD连接着发送器的RXD,接收器和发送器可以通过RXD和TXD互传数据。当接收器检测到RXD这条线的电平被拉为低电平,立即开始接收发送器发送过来的数据,刚刚那个低电平只是一个告知接收器可以接收数据的起始位而已。

在数据的传输中,信号可能受到一些干扰而产生一些抖动,如下图。如果接收端只对这些信号数据采样一次,那么它有可能采样到的是抖动的不准的数据,进而使数据传输不准确,所以接收端在采样数据线上的数据,通常都要采样多次,然后通过比较获得准确的数据。

前面已经说过,USARTDIV,它表示对串口的时钟源fck进行分频,而这16表示的正是1bit数据的采样次数。为什么呢?

,将这个表达式的分子分母倒过来,可以得到下面这条表达式

每一位的传输时间只有1/TX_baud,这个总时间除以16,所以每采样一次的时间正好是T1,即新分频后的周期。而初始的串口时钟信号来自于APBx,APBx时钟信号需要经过分频才会等于T1,所以才需要分频USARTDIV。

转自:博客园,转载此文目的在于传递更多信息,版权归原作者所有。
原文链接:
http://www.cnblogs.com/cposture/p/4268910.html

围观 6
57

  •   继意法半导体收购Draupner Graphics后,TouchGFX套件现已紧密集成在STM32Cube生态系统中
  •   高端图形界面开发工具和软件框架,支持STM32微控制器,与STM32Cube软件轻松协同操作
  •   免使用费和版税,可通过ST组织在全球获取软件和技术支持

通过免费提供图形用户界面设计软件,帮助开发者创建功能丰富、画面流畅、色彩丰富、用户体验出色的图形界面,横跨多重电子应用领域的全球领先的半导体供应商意法半导体 (STMicroelectronics,简称ST;纽约证券交易所代码:STM)正在扩大STM32 *微控制器(MCU)对物联网产品和其它智能设备的开发人员的吸引力。

STM32是世界上人气最高的Arm® Cortex®微控制器。STM32产品家族有800多款微控制器。为简化产品开发,加快产品上市时间,STM32还配备强大的开发生态系统,其中包括开发工具、中间件、软件库、示例代码和评估板。在收购了TouchGFX的开发者Draupner Graphics公司后,现在意法半导体为STM32 MCU设备制造商和经销商免费提供备这套好评如潮的图形用户界面开发软件。

意法半导体微控制器产品部市场总监Daniel Colonna表示:“有许多客户已经成功地在基于STM32微控制器的新产品上,应用TouchGFX,给用户带来了媲美智能手机的图形界面体验。通过将最新版本引入我们的STM32Cube生态系统,不收取使用费和版权费,并提供10年供货保证承诺,我们正在让全球的开发者都能轻松获取这一强大、创新的解决方案。”

TouchGFX是与STM32微控制器配合使用,包含一个让用户界面代码只占用10KB的 SRAM空间和20KB的闪存空间的C ++软件框架。TouchGFX可将STM32 MCU的Chrom-ART Accelerator™控制器的先进图形功能发挥到极致,渲染算法可使要更新像素的数量最小化,在低内存占用率和低功耗预算条件下,实现更好的图形处理性能和更流畅的动画效果。TouchGFX支持每像素1,2,4,16或24位(bpp)色深的用户界面,有无实时操作系统(RTOS)均可运行。

该开发套件的TouchGFX Designer工具支持简单的鼠标拖放操作,让用户能够快速开发图形界面,并具有自动代码生成以及字体、文本和图像转换功能。

通过与STM32Cube软件包完全整合在一起,TouchGFX与STM32CubeMX配置工具及初始化代码生成器协同操作,为无缝开发GUI和主应用程序创建一个统一的项目环境。为了帮助图形设计项目顺利运行,意法半导体为STM32CubeMX增加了新功能,包括帮助筛选适合微控制器的增强版MCU Finder、图形性能评估计算器、显示图形界面在目标硬件上的运行表现的模拟器。

现在从www.st.com/stm32gui网址下载STM32Cube固件,即可免费获得TouchGFX 4.10版。

围观 8
97

STM32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。(TIM1和TIM8是能够产生3对PWM互补输出的高级登时其,常用于三相电机的驱动,时钟由APB2的输出产生;TIM2-TIM5是普通定时器;TIM6和TIM7是基本定时器,其时钟由APB1输出产生)

本实验要实现的功能是:用普通定时器TIM2每一秒发生一次更新事件,进入中断服务程序翻转LED1的状态。

预备知识:

① STM32通用定时器TIM2是16位自动重装载计数器。

② 向上计数模式:从0开始计数,计到自动装载寄存器(TIMx_ARR)中的数值时,清0,依次循环。

需要弄清楚的两个问题:

1. 计数器的计数频率是什么?

这个问题涉及到RCC时钟部分,如下图所示:

STM32通用定时器TIM2的使用方法解析

定时器的时钟不是直接来自APB1或APB2,而是来自于输入为APB1或APB2的一个倍频器。

下面以定时器2~7的时钟说明这个倍频器的作用:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1的频率两倍。

假定AHB=36MHz,因为APB1允许的最大频率为36MHz,所以APB1的预分频系数可以取任意数值;当预分频系数=1时,APB1=36MHz,TIM2~7的时钟频率=36MHz(倍频器不起作用);当预分频系数=2时,APB1=18MHz,在倍频器的作用下,TIM2~7的时钟频率=36MHz。

有人会问,既然需要TIM2~7的时钟频率=36MHz,为什么不直接取APB1的预分频系数=1?答案是:APB1不但要为TIM2~7提供时钟,而且还要为其它外设提供时钟;设置这个倍频器可以在保证其它外设使用较低时钟频率时,TIM2~7仍能得到较高的时钟频率。

再举个例子:当AHB=72MHz时,APB1的预分频系数必须大于2,因为APB1的最大频率只能为36MHz。如果APB1的预分频系数=2,则因为这个倍频器,TIM2~7仍然能够得到72MHz的时钟频率。能够使用更高的时钟频率,无疑提高了定时器的分辨率,这也正是设计这个倍频器的初衷。

注意:APB1和APB2上挂的外设如图所示:

STM32通用定时器TIM2的使用方法解析

定时器的计数频率有个公式:

TIMx_CLK = CK_INT / (TIM_Prescaler + 1)

其中:TIMx_CLK 定时器的计数频率

CK_INT 内部时钟源频率(APB1的倍频器送出时钟)

TIM_Prescaler 用户设定的预分频系数,取值范围0~65535。

例如:RCC中AHB=72MHZ、APB1=36MHZ、APB2=72MHZ,则CK_INT=72MKZ。

2. 如何计算定时时间?

上述公式中TIM_Prescaler涉及到寄存器TIMx_PSC

STM32通用定时器TIM2的使用方法解析

STM32通用定时器TIM2的使用方法解析

如果TIM_Prescaler设为36000,由上面公式可知:

定时器的计数频率 TIMx_CLK = 72MKZ / 36000 = 2000HZ,则定时器的计数周期=1/2000HZ=0.5ms.

如果要定时1秒,则需要计数2000次,这也是自动重装载的值。又涉及到TIMx_ARR

STM32通用定时器TIM2的使用方法解析

STM32通用定时器TIM2的使用方法解析

只要上述两个问题搞清楚了,剩下的就是设置相应寄存器的对应位了。

LED硬件连接如下图所示:高电平点亮LED。

STM32通用定时器TIM2的使用方法解析

第一步:配置系统时钟。见STM32F103x RCC寄存器配置

除此之外,还需将GPIO和TIM2外设时钟打开。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

注意:TIM2是挂在APB1上的,打开时钟时别写错了,调用RCC_APB1PeriphClockCmd函数,而不是RCC_APB2PeriphClockCmd。

第二步:配置中断向量表。见stm32_exti(含NVIC)配置及库函数讲解

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

#ifdef VECT_TAB_RAM

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

该函数完成两个功能

1. 决定将程序下载到RAM中还是FLASH中

2. 配置中断分组。(NVIC中断分组只能设置一次)

3. 选择中断通道号,抢占式优先级和响应优先级,使能中断

第三步:配置GPIO的模式。输入模式还是输出模式。点亮LED已讲过,见STM32_GPIO配置及库函数讲解——LED跑马灯

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOC, &GPIO_InitStructure);

}

第四步:定时器配置,本章重点!

void TIM2_Configuration(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

//重新将Timer设置为缺省值

TIM_DeInit(TIM2);

//采用内部时钟给TIM2提供时钟源

TIM_InternalClockConfig(TIM2);

//预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz

TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;

//设置时钟分割

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

//设置计数器模式为向上计数模式

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

//设置计数溢出大小,每计2000个数就产生一个更新事件

TIM_TimeBaseStructure.TIM_Period = 2000;

//将配置应用到TIM2中

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

//清除溢出中断标志

TIM_ClearFlag(TIM2, TIM_FLAG_Update);

//禁止ARR预装载缓冲器

TIM_ARRPreloadConfig(TIM2, DISABLE); //预装载寄存器的内容被立即传送到影子寄存器

//开启TIM2的中断

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

}

该函数完成两个功能

1. 设定预分频系数TIM_Prescaler = 36000 - 1

2. 设定自动重装载值TIM_Period = 2000

注意:上述只是配置好了TIM2,但还没有开启TIM2。

下面给出timer2.c的完整代码

#include “stm32f10x_lib.h”

void RCC_Configuration(void);

void NVIC_Configuration(void);

void GPIO_Configuration(void);

void TIM2_Configuration(void);

void Delay(vu32 nCount);

int main(void)

{

#ifdef DEBUG

debug();

#endif

RCC_Configuration();

NVIC_Configuration();

GPIO_Configuration();

TIM2_Configuration();

TIM_Cmd(TIM2, ENABLE); //开启定时器2

while (1)

{

}

}

void RCC_Configuration(void)

{

ErrorStatus HSEStartUpStatus;

RCC_DeInit();

RCC_HSEConfig(RCC_HSE_ON);

HSEStartUpStatus = RCC_WaitForHSEStartUp()

if (HSEStartUpStatus == SUCCESS)

{

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

FLASH_SetLatency(FLASH_Latency_2);

RCC_HCLKConfig(RCC_SYSCLK_Div1);

RCC_PCLK2Config(RCC_HCLK_Div1);

RCC_PCLK1Config(RCC_HCLK_Div2);

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

RCC_PLLCmd(ENABLE);

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

while(RCC_GetSYSCLKSource() != 0x08) {}

}

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

}

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

#ifdef VECT_TAB_RAM

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOC, &GPIO_InitStructure);

}

void TIM2_Configuration(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

//重新将Timer设置为缺省值

TIM_DeInit(TIM2);

//采用内部时钟给TIM2提供时钟源

TIM_InternalClockConfig(TIM2);

//预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz

TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;

//设置时钟分割

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

//设置计数器模式为向上计数模式

转自:电子发烧友网

围观 33
119

题目

(1)测量脉冲信号频率fo,频率范围为10Hz~2MHz,测量误差的绝对值不大于0.1%。

(2)测量脉冲信号占空比D,测量范围为10%~90%,测量误差的绝对值不大于2%。

使用官方STM32F429 Discovery开发板,主频180MHz,定时器频率90MHz。

思路一、外部中断

这种方法是很容易想到的,而且对几乎所有MCU都适用(连51都可以)。方法也很简单,声明一个计数变量TIM_cnt,每次一个上升沿/下降沿就进入一次中断,对TIM_cnt++,然后定时统计即可。如果需要占空比,那么就另外用一个定时器统计上升沿、下降沿之间的时间即可。

缺陷显而易见,当频率提高,将会频繁进入中断,占用大量时间。而当频率超过100kHz时,中断程序时间甚至将超过脉冲周期,产生巨大误差。同时更重要的是,想要测量的占空比由于受到中断程序影响,误差将越来越大。

笔者当时第一时间就把这个方案PASS了,没有相关代码(这个代码也很简单)。不过,该方法在频率较低(10kHz以下)时,可以拿来测量频率。在频率更低的情况下,可以拿来测占空比。

思路二、PWM输入模式

翻遍ST的参考手册,在定时器当中有这样一种模式:

如何使用STM32测量频率和占空比?

简而言之,理论上,通过这种模式,可以用硬件直接测量出频率和占空比。当时我们发现这一模式时欢欣鼓舞,以为可以一步解决这一问题。

但是,经过测量之后发现这种方法测试数据不稳定也不精确,数据不停跳动,且和实际值相差很大。ST的这些功能经常有这种问题,比如定时器的编码器模式,在0点处频繁正负跳变时有可能会卡死。这些方法虽然省事,稳定性却不是很好。

经过线性补偿可以一定程度上减少误差(参数在不同情况下不同):

freq=Frequency×2.2118-47.05

这种方法无法实现要求。所以在这里笔者并不推荐这种方法。

思路三、输入捕获

一般来说,对STM32有一定了解的人在测量频率的问题上往往都会想到利用输入捕获。

首先设定为上升沿触发,当进入中断之后(rising)记录与上次中断(rising_last)之间的间隔——周期,其倒数就是频率。

再设定为下降沿,进入中断之后与上升沿时刻之差即为高电平时间(falling-rising_last),高电平时间除周期即为占空比。

如何使用STM32测量频率和占空比?

该方法尤其是在中低频(

缺点是该方法仍然会带来极高的中断频率。在高频之下,首先是CPU时间被完全占用,此外,更重要的是,中断程序时间过长往往导致会错过一次或多次中断信号,表现就是测量值在实际值、实际值×2、实际值×3等之间跳动。实测中,最高频率可以测到约400kHz。

该方法在低频率(

改进方案

前述问题,限制频率提高的主要因素是过长的中断时间,一般应用情景之下,还有其它程序部分的限制。所以需要进行改进。

方案一

1.使用2个通道,一个只测量上升沿,另一个只测量下降沿。这样可以减少切换触发边沿的延迟,缺点是多用了一个IO口。

2.使用寄存器,简化程序

之所以改用TIM2是因为TIM5的CH1(PA0)还是按键输入引脚。本来想来这应当也没什么,按键不按下不就是开路嘛。所以,当使用别人的程序之前,请一定仔细查看电路图。

如何使用STM32测量频率和占空比?

这样,最高频率能够达到约1.1MHz,是一个不小的进步。但是,其根本问题,中断太频繁,仍然存在。

解决思路也是存在的。本质上,实际只需要读取CCR1和CCR2寄存器。而在内存复制过程中,面对大数据量的转移时,会想到什么?

显然,很容易想到——利用DMA。所以,笔者使用输入捕获事件触发DMA来搬运寄存器而非触发中断即可,然后将这些数据存放在一个数组当中并循环刷新。这样,可以随时来查看数据并计算出频率。

方案二

1. 可以设定仅有通道2进行下降沿捕获并触发中断,而通道1捕获上升沿不触发中断。在中断函数当中,一次读取CCR1和CCR2。这样可以节省大量时间。

2. 可以先进行一次测量,根据测量值改变预分频值PSC,从而提高精度

3. 间隔采样。例如每100ms采样10ms.

这样的改进应当能够将最高采样频率增加到2M.但是频率的进一步提高仍然不可能。

因为这时的主要矛盾是中断函数时间过长,导致CPU还在处理中断的时候这一次周期就结束了,使得最终测量到的频率为真实频率的整数倍左右。示意图如下:

如何使用STM32测量频率和占空比?

结语

外部中断:编写容易,通用性强。缺点是中断进入频繁,误差大。

PWM输入:全硬件完成,CPU负载小,编写容易。缺点是不稳定,误差大。

输入捕获:可达到约400kHz。低频精度高,10kHz可达到0.01%以下,400kHz也有3%。缺点是中断频繁,无法测量高频,幅值必须在3.3~5V之间。

转自:玩转单片机,本文内容来源于网络,转载此文目的在于传递更多信息,版权归原作者。

围观 23
784

STM32基本系统主要有下面几个部分:

电源

  •  无论是否使用模拟部分和AD部分,MCU外围出去VCC和GND,VDDA、VSSA、Vref(如果封装有该引脚)都必需要连接,不可悬空
  
  •  对于每组对应的VDD和GND都应至少放置一个104的陶瓷电容用于滤波,并接该电容应放置尽量靠近MCU

  •  用万用表测试供电电压是否正确,调试时最好用数字电源供电,以便过压或过流烧坏板子,电压最好一步一步从进线端测试到芯片供电端

复位、启动选择

  •  Boot引脚与JTAG无关。其仅是用于MCU启动后,判断执行代码的起始地址

  •  在电路设计上可能Boot引脚不会使用,但要求一定要外部连接电阻到地或电源,切不可悬空; STM32三种启动模式对应的存储介质均是芯片内置的,它们是:
   - 用户闪存 = 芯片内置的Flash
   - SRAM = 芯片内置的RAM区,就是内存
   - 系统存储器 = 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序,这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM区

在每个STM32的芯片上都有两个管脚BOOT0和BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序,见下表:

一文读懂STM32的基本系统

  •  BOOT1=x BOOT0=0 从用户闪存启动,这是正常的工作模式。
  •  BOOT1=0 BOOT0=1 从系统存储器启动,这种模式启动的程序功能由厂家设置。
  •  BOOT1=1 BOOT0=1 从内置SRAM启动,这种模式可以用于调试。
  •  用JTAG口或SWD模式烧写 选择从用户闪存启动。
  •  用串口ISP模式烧写程序时时选择从系统存储启动

烧写接口

如果要减小插座的数量,就用SWD模式的仿真,在这个模式下,如果用JLINK只要四根线就可以了,这四根线分别是:3.3V、GND、SWDIO、SWCLK
  
其中STM32的JTMS/SWDIO接JTAG口的TMS,STM32的JTCK/SWCLK接JTAG口的TCK。如果要用ULINK2,则再加多一条“NRST”,即5条。这个接口你可自行定义,在使用时用杜邦线跳接或做块转换接口板联接仿真器与目标板即可。
  
在烧写时出现了IDCODE如图有序列号,证明烧写接口是好的!也就是硬件调试通了。如没有也许焊接不过关,从新加固焊接芯片。

调试烧录失败的常见原因

1. 目标芯片没有正确连接,不能正常工作 —— 解决方法:确保目标板的最小系统正确连接,芯片能正常工作:VDD、VDDA及VSS 、VDDS已全部正确连接,复位电路能够可靠复位,各复位源不互相影响。
  
2. 芯片内原先烧录的代码影响了新的调试操作,芯片内原先烧录的代码出错,芯片上电运行,进入未定义状态,不能进入调试模式。芯片内原先烧录的代码启动了某些外设,或者将SWJ引脚配置为普通I/O口 —— 解决方法:选择芯片的BOOT0/BOOT1引脚从RAM启动,或先擦除芯片内代码。

3. 芯片已被读/写保护,调试工具不能读写芯片内置的Flash —— 解决方法:先使用调试工具解除芯片的读/写保护。

来源:网络

围观 14
409

页面

订阅 RSS - STM32