Discuz! REAL TIME TECHNOLOGY
标题: STM32F207单片机时钟 [打印本页]
作者: ahwwq 时间: 2013-5-17 11:52
标题: STM32F207单片机时钟
在HID固件中,有一个延时函数,如下:
/*
* usbd_stm32_delay
* Parameters: delay: Delay
* Return Value: None
*/
void usbd_stm32_delay (U32 delay) {
delay *= SystemCoreClock / 100000;
while (delay--) {
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
}
}
调用时,参数为1000时延时10毫秒,这样计算出的SystemCoreClock是否就是最快时钟信号
作者: ahwwq 时间: 2013-5-17 11:57
这个在定义时,显示:
uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
作者: Wjianw 时间: 2013-5-17 13:05
ahwwq 发表于 2013-5-17 11:57 
这个在定义时,显示:
[mw_shl_code=c,true]uint32_t SystemCoreClock; /*!< System Clock Frequency (Core ...
不是调用延时函数
是对IO进行设置1和0,比如对A口bit0进行设置
while(1)
{ IOA |= 0x01;
IOA &=0xFE;
}
或者
while(1)
{
IOA ^= 0x01;
}
作者: Wjianw 时间: 2013-5-20 10:50
Wjianw 发表于 2013-5-17 13:05 
不是调用延时函数
是对IO进行设置1和0,比如对A口bit0进行设置
while(1)
STM32 GPIO 置位 复位 功能实现
[tr][td] GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); |
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
GPIOX=GPIOA~GPIOG;
GPIO_Pin=GPIO_Pin_0 ~ GPIO_Pin_15;
例:
GPIO_ResetBits(GPIOB,GPIO_Pin_5);//将PORTB.5 = 0;
GPIO_SetBits(GPIOB,GPIO_Pin_8);//将PORTB.8 = 1;
作者: Wjianw 时间: 2013-5-20 11:12
Wjianw 发表于 2013-5-20 10:50 
STM32 GPIO 置位 复位 功能实现
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
STM32 入门之 GPIO 置位复位
作者: Wjianw 时间: 2013-5-20 11:25
Wjianw 发表于 2013-5-20 11:12 
STM32 入门之 GPIO 置位复位
2篇关于GPIO编程的
作者: DXiaoFei 时间: 2013-5-20 20:07
说明:
1,这个是目前用于STM32F107芯片的、调试GPIO的翻转频率的一个程序。主要是在开发板中的“LED灯闪烁实验(裸机)”基础上做了相应修改。我所做的修改主要是添加了GPIO的P13口作为测试脚。其他的修改在程序中使用汉语注释了。
2,经过调试,发现IO口的输出频率总是在2M ~ 2.5M左右。并且在LED上输出测试的时候,波形的周期会比在Pin 13上输出的略大,稍微大40~50ns(估算)。
3,目前,将问题锁定在 main.c中的main 程序的“System_Setup( ) 函数的设置上”。也就是system32f107.h文件夹中的System_Setup( )函数,其中所调用的 “SystemInit()”函数是 system_stm32f10x.c 文件中的一个设置函数,目前我们还没有深入了解。问题很可能就出现在这个函数中。
4,在傍晚王老师调试之后,为了寻找方便,我在main.c 中添加“#include "stm32f107.h"”语句。
5,简单提示,使用Keil uVision 4 运行本程序的步骤为:首先压缩包 >>> 打开文件夹 >>> 打开“Project”文件夹 >>> 打开“RVMDK”文件夹 >>> 打开“Project.uvproj”文件 >>> 编写或修改程序 >>> 组建 >>> 点击“Start Debug Session”(如果没有调试器的话,只能软件仿真,点击“Use Simulator”即可)。
作者: DXiaoFei 时间: 2013-5-20 20:13
对了,补充一点:
如果把System_Setup( ) 函数 注释掉之后,测量引脚上的输出,此时周期变为 5K 左右。
当把这个函数恢复之后,引脚输出的周期大概为 2M ~2.5M。所以,几乎是5倍关系。
然而,在外设端口的时钟枚举中,只有2M、10M、50M三个参数可选。它们也是5倍关系。具体原因,暂时不明。
作者: Wjianw 时间: 2013-5-20 21:36
DXiaoFei 发表于 2013-5-20 20:13 
对了,补充一点:
如果把System_Setup( ) 函数 注释掉之后,测量引脚上的输出,此时周期变为 5K 左右。 ...
研究STM32的时钟构成了SystemInit()函数
作者: ahwwq 时间: 2013-5-21 10:34
工程修改:GPIO的赋值语句修改:
这是移位后或运算赋值对应的汇编
[attach]1079[/attach]
这是移位直接赋值对应的汇编
[attach]1080[/attach]
这是直接赋值十六进制对应的汇编
[attach]1081[/attach]
利用上述最后一种赋值方式,最新测的STM32F207 I/O翻转频率
[attach]1078[/attach]
作者: ahwwq 时间: 2013-5-21 15:49
Wjianw 发表于 2013-5-20 10:50 
STM32 GPIO 置位 复位 功能实现
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
在STM32F207中尝试使用这种方法,无法编译成功(开发板提供的文件缺少且目录结构和官方描述有差),但是通过阅读源代码,调用下面的函数:
GPIO_SetBits( GPIOD, GPIO_Pin_13);函数内部是 GPIOx->BSRRH = GPIO_Pin_13;
而GPIO_Pin_13定义为0x2000.
所以本质上是一样的。
如下图所示:
[attach]1088[/attach]
[attach]1087[/attach]
这个文件时STM32F2XX系列的标准库文件
[attach]1089[/attach]
作者: DXiaoFei 时间: 2013-5-24 00:02
A,如果要操作GPIO,必须经历的2个步骤:
1,配置RCC,设置系统时钟、使能总线时钟、外设时钟。
2,选择GPIO端口的引脚号、驱动频率、输入输出模式
之前代码为:
GPIOE_P13_OFF; //先低电平
GPIOE_P13_ON; //高电平
这个代码执行的结果是:25M外部晶振,72M系统时钟条件下,输出最大2.5M
后来经过修改,采用直接操作寄存器的方式进行赋值:
GPIOE->ODR=0<<13; //在删掉上面的Delay函数之后,12M (系统时钟为72M)
GPIOE->ODR=1<<13; //
与上述同样条件下的测试结果是:输出10.28M。但是,当我再次精简主程序的代码的时候,得到12M输出。
B,下面是倍频之后的结果:外部时钟25M
3倍频时(即75M系统时钟),输出 12M (这个结果有点原因,使用的是另一个倍频设置方式,暂时只能这样)
4倍频时(即100M系统时钟),输出14.28M,去掉Delay()函数后,得到16.66M稳定输出。(可能是编译器在优化的过程中的一些不同,导致的结果)
5倍频时(即125M系统时钟),输出17.85M,去掉Delay()函数后,得到20.83M稳定输出。
更高的倍频还不敢尝试。以上测试,芯片的温度都没有大的变化,基本保持在37℃左右。
关于更多的GPIO翻转速度的论证资料可以参考一下链接:
http://www.mcuzx.net/thread-517-1-1.html 。
这个网站中的第9楼中有关于GPIO速率的详细的论证:以及相关的资料。
http://www.amobbs.com/thread-5463674-1-1.html
以下是我手画的系统时钟配置的路径图:(关于我对系统时钟的库函数的注解文件,在压缩包中,有兴趣的可以看一下。凡是英文的都是原来官方注解,凡是中文的都是我个人做的注解(可能会有些错误)。)
作者: DXiaoFei 时间: 2013-5-24 11:50
今天早上再次做了一下实验,并且将所有实验结果截图保存了。(实验过程中,将一个探头探针折断,但是还能使用。现在的实验结果是在探头套上了一个保护套之后的测量结果。总的感觉波形正确,但是毛刺电压稍大。希望师兄们引以为戒。)
图SCR04 ~ SCR09,分别代表72M(不带delay())
[attach]1120[/attach]
72M (带有2个Delay()函数),输出10.28M
[attach]1123[/attach]
100M (不带Delay())16.66M
[attach]1124[/attach]
125M (不带Delay())20.85M
[attach]1122[/attach]
作者: DXiaoFei 时间: 2013-5-24 15:52
中午又修改了一下程序,使GPIO输出频率达到18M。实际上,采取一下形式:
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
GPIOE->ODR=0<<13;
GPIOE->ODR=1<<13;
............
............
............
大概有100行,(越长越好,越能接近18M)。这样的作用就是将“While(1)”这条指令的执行时间影响消除。
如下图:
[attach]1127[/attach]
其中,可以看到有一个亮度很弱的一个脉冲,实际上就是 While(1),跳转语句造成的移位,如果上面的置0置1程序越多,那么这个阴影显然会越淡。
作者: DXiaoFei 时间: 2013-5-24 15:54
得到18M的结果,可以推测我们的输出指令是占掉2个系统时钟。这样 72/4=18.所以,18M是暂时的一个极限。如果需要更大的,那么只能再进一步优化代码。有兴趣的话可以一试。
作者: DXiaoFei 时间: 2013-5-24 19:34
关键点:1)代码优化。
2),设置路径优化。(如下图)可以参考《STM32参考手册》的“GPIO的结构”章
[attach]1128[/attach]
作者: DXiaoFei 时间: 2013-5-24 23:35
经过深入学习BSRR、BRR、ODR寄存器的区别、特性,发现,BSRR与ODR的速度是一样的。所不同的是:BSRR和BRR适用于中断函数对端口的操作,而如果直接对ODR可能会引起竞争。我们可以直接对ODR进行操作,也可以通过BSRR或者BRR来进行操作。这只是两种方式,并且后者会更安全些。
BSRR的优点在于,可以一次性对不同的位进行“位”置位和复位(也即两个不同引脚的置位复位可以并行操作)。而BRR用来专门的进行“位”复位,它的作用和BSRR的高16位是相同的。但是,有了BRR这个16位的“复位器”,我们就可以快速的进行一个IO口(16根引脚)的“复位”,而不用进行移位(因为如果要使用BSRR的“位”复位功能,那么要对这个16位的操作数移位至BSRR的高16位)。综合起来,我们应这样理解BSRR(一个32位的寄存器)与BRR(一个16位的寄存器):起初,我们为了方便对GPIO的16根引脚进行位操作,所以设计了“BSR” 和BRR这两个16位的寄存器,用来分别进行置位和复位操作,后来,为了能使不同引脚的置位/复位操作能并行执行,所以让“BSR (Bit Set Register )”寄存器设计成一个32位的寄存器(命名为BSRR,Bit Set and Reset Register),其中它的高16位用来进行“位”复位,所以最后GPIO 一共有了 BSRR 和 BRR 这两个特殊的寄存器。(注意,BSRR和BRR都是“只写型”的寄存器,也就是说,它们每次设置的时候只起一次作用。)
之所以之前采用了看起来一样的GPIO置位复位命令,却得到2.5M的输出频率,很可能是我们的编译器编译的结果,使得我们在进行“置位/复位”时,隐含的调用了一下寄存器操作指令(后来我们就是直接用的这个寄存器操作指令,所以得到12M输出),所以多耗去几个系统时钟。另外,我在调试过程中,将
GPIOE->BSRR=0x00002000;
GPIOE->BSRR=0x20000000;
这两个代码换一下顺序,就导致输出的频率不一样,一个为10.28M一个为12M。具体原因不详。可能是编译器的原因。但是,“有输出”,就意味着,BSRR寄存器中如果对同一根引脚置1和置0,那么它只会置1,但是,如果分两次对同一位进行置1或置0,则会有高、低两个电平的输出变化。所以,从这可以推测,BSRR寄存器是非记忆型的(一次性使用)。
当然,这些也只是以我目前所掌握的知识量来做的推测,也许以后的应用中有了更深刻的认识,会发现其中真正的问题。综合起来看,吴文庆师兄的24M已经是STM32F207的上限频率了,但是,如果使用一个技巧(就是不断写100行置0置1代码),也许能看到36M的输出(但本质上是没有变的)。
作者: ahwwq 时间: 2013-6-4 12:51
利用F2xx官方的库和自带的GPIO翻转例子,测得翻转频率有60MHz。
作者: Wjianw 时间: 2013-6-4 15:25
ahwwq 发表于 2013-6-4 12:51 
利用F2xx官方的库和自带的GPIO翻转例子,测得翻转频率有60MHz。
good,把工程传上来
作者: DXiaoFei 时间: 2013-6-4 22:54
貌似这个达到了官方给的 STM32F207 最大GPIO速度了,不错! 以前为什么是24M ,有哪些地方做过改进?师兄把工程传上来看看。
作者: ahwwq 时间: 2013-6-5 09:02
DXiaoFei 发表于 2013-6-4 22:54 
貌似这个达到了官方给的 STM32F207 最大GPIO速度了,不错! 以前为什么是24M ,有哪些地方做过改进?师兄把 ...
代码本质上没有什么区别,
[attach]1152[/attach]
下面是main函数代码:
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f2xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f2xx.c file
*/
/* GPIOD Periph clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* Configure PG6 and PG8 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;// | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* To achieve GPIO toggling maximum frequency, the following sequence is mandatory.
You can monitor PG6 or PG8 on the scope to measure the output signal.
If you need to fine tune this frequency, you can add more GPIO set/reset
cycles to minimize more the infinite loop timing.
This code needs to be compiled with high speed optimization option. */
while (1)
{
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
/* Set PG6 and PG8 */
GPIOD->BSRRL = GPIO_Pin_13;// | GPIO_Pin_8;
/* Reset PG6 and PG8 */
GPIOD->BSRRH = GPIO_Pin_13;// | GPIO_Pin_8;
}
}
欢迎光临 Discuz! REAL TIME TECHNOLOGY (http://lodetech.ustc.edu.cn/bbs/) |
Powered by Discuz! X2.5 |