打印
[STM32F7]

求助:STM32F746IG GPIO翻转频率只有不到15MHz!

[复制链接]
4756|47
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xzrsh|  楼主 | 2017-10-1 15:26 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 xzrsh 于 2017-10-1 17:31 编辑

开发板:野火746核心板(STM32F746IGT6两个双排针引出IO + SDRAM + SPI Flash W25Q128)
开发环境: IAR EWARM V7.50 + JLinkV9 SWD模式
测试代码: 使用STM32Cube_FW_F7_V1.4.0里面的STM32F746ZG-Nucleo --- Examples --- GPIO --- GPIO_IOToggle --- EWARM工程

其中代码略微做了修改,IO口使用PH13作为输出。代码如下:

GPIO_InitTypeDef  GPIO_InitStruct;

int main(void)
{
        /* 1. Enable the CPU Cache */
        CPU_CACHE_Enable();

       /* 2. STM32F7xx HAL library initialization:        */
        HAL_Init();

        /* 3. Configure the system clock to 216 MHz */
        SystemClock_Config();

        /* 4. Enable GPIO Clock (to be able to program the configuration registers) */
       //__HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_GPIOH_CLK_ENABLE();

       /* 5. Configure IO in output push-pull mode to drive external LEDs */
        GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull  = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Pin = GPIO_PIN_13;//GPIO_PIN_0;
        //HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
        HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

       /* 6. Toggle IO in an infinite loop */
        while (1)
        {
                //HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
                HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_13);
                /* 中间有很多这样的翻转语句 */
                HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_13);                /* Insert delay 100 ms */
                //HAL_Delay(100);
        }
}
main函数中所使用的系统初始化配置函数就不贴出来了,各个样例工程中都有,MDK使用的也是一样的函数。

下载到MCU中后,运行结果是翻转频率只有15MHz不到,如图所示:

(大概频率略有差异,但波形基本如此)

修改翻转代码,不使用库函数HAL_GPIO_TogglePin(),而使用寄存器直接赋值:
       /* 6. Toggle IO in an infinite loop */
        while (1)
        {
                 GPIOH->BSRR = GPIO_PIN_13;                GPIOH->BSRR = (GPIO_PIN_13 << 16);
                /* 中间有很多这样的翻转语句 */
                GPIOH->BSRR = GPIO_PIN_13;
                GPIOH->BSRR = (GPIO_PIN_13 << 16);
                /* Insert delay 100 ms */
                //HAL_Delay(100);
        }


这个输出就很怪异了,大部分是中间电平1.6V左右),偶尔蹦出个高电平或低电平的脉冲出来,如下两图:


对其中的中间电平部分(就是比较密集的看起来像杂波)拉宽后,如下图:


可以看出,其波动频率大约为50MHz。

对翻转代码的寄存器赋值后,都增加一条读寄存器指令:
       /* 6. Toggle IO in an infinite loop */
        while (1)
        {
                 GPIOH->BSRR = GPIO_PIN_13;                (void)GPIOH->IDR;
                GPIOH->BSRR = (GPIO_PIN_13 << 16);   (void)GPIOH->IDR;
                /* 中间有很多这样的翻转语句 */
                GPIOH->BSRR = GPIO_PIN_13;                 (void)GPIOH->IDR;
                GPIOH->BSRR = (GPIO_PIN_13 << 16);   (void)GPIOH->IDR;
                /* Insert delay 100 ms */
                //HAL_Delay(100);
        }



上述代码就可以得到正常翻转的波形,但频率仍和使用库函数HAL_GPIO_TogglePin()时差不多,也不到15MHz。

根据ST的数据手册和参考手册以及宣传资料可知,STM32F7的GPIO挂在AHB下,可以做到每2个HCLK改变一次IO的状态,216/2 = 108MHz,方波频率 = 54MHz。
从实际情况来看,好像指令也执行了,但相应的上下MOS管并没有适时彻底开通从而输出高/低电平,只是偶尔才会彻底打开一下驱动MOS管,大部分情况都是处于没彻底导通的情形。

有谁知道这是怎么回事儿吗?




沙发
598330983| | 2017-10-1 22:48 | 只看该作者
应该是时钟频率太快了

使用特权

评论回复
板凳
zhangxiyi5277| | 2017-10-2 08:39 | 只看该作者
之前见有人拿树莓派的io直接发调频广播

使用特权

评论回复
评论
aizaixiyuanqian 2018-2-28 11:48 回复TA
这个厉害了 
地板
戈卫东| | 2017-10-2 10:28 | 只看该作者
示波器太渣。。。。。。

使用特权

评论回复
5
戈卫东| | 2017-10-2 10:31 | 只看该作者
换个示波器看看吧

使用特权

评论回复
6
xzrsh|  楼主 | 2017-10-2 13:02 | 只看该作者
戈卫东 发表于 2017-10-2 10:31
换个示波器看看吧

示波器是有点渣,但基本波形还是没错的。因为我一开始用IO模拟595的 SCK和RCK 输入,595根本得不到正确结果。但如果加入(void)GPIOH->IDR,或(void)GPIOH->ODR这样的语句,就有正确结果。后来用示波器看IO输出,才发现IO的输出电平大部分是1.6V左右的中间值。

使用特权

评论回复
7
xzrsh|  楼主 | 2017-10-2 13:05 | 只看该作者
598330983 发表于 2017-10-1 22:48
应该是时钟频率太快了

看那个密集的中间电平波形拉宽后,其波动频率在50MHz,说明IO已经响应了指令,只不过驱动MOS管还没完全导通就又切换到下一个状态了。难道我买到了假的746了吗?

使用特权

评论回复
8
xzrsh|  楼主 | 2017-10-2 13:15 | 只看该作者
zhangxiyi5277 发表于 2017-10-2 08:39
之前见有人拿树莓派的io直接发调频广播

这应该是IO工作在AF模式的吧。根据其FMC或者PWM功能来看,工作频率的确能达到100MHz。但如果只单纯操作GPIO电平翻转,估计频率最大只能到54MHz(理论上)。

就像现在我遇到的这个问题,操作BSRR寄存器,翻转完电平后,如果不读一下IDR或ODR,它的物理输出好像就没有反应过来。

使用特权

评论回复
9
FAQ| | 2017-10-4 13:48 | 只看该作者
不要用toggle函数,直接操作寄存器试试。

使用特权

评论回复
10
xzrsh|  楼主 | 2017-10-5 15:34 | 只看该作者
FAQ 发表于 2017-10-4 13:48
不要用toggle函数,直接操作寄存器试试。

多谢回复,我在上面也试验了直接操作寄存器的方法。不过,出来的结果很奇怪,大多数情况是在1.5V左右的电平上晃悠,偶尔才有一个真正的高或低电平出来。但如果在操作寄存器BSRR之后,再读一下IDR或ODR或BSRR寄存器,就可以实现翻转,但翻转速度只有不到15MHz。

使用特权

评论回复
11
FAQ| | 2017-10-5 21:45 | 只看该作者
xzrsh 发表于 2017-10-5 15:34
多谢回复,我在上面也试验了直接操作寄存器的方法。不过,出来的结果很奇怪,大多数情况是在1.5V左右的电 ...

会不会有被优化的风险

使用特权

评论回复
12
xzrsh|  楼主 | 2017-10-6 10:27 | 只看该作者
FAQ 发表于 2017-10-5 21:45
会不会有被优化的风险

我注意看了汇编窗口,没有被优化掉。

使用特权

评论回复
13
ihafd| | 2017-10-6 10:44 | 只看该作者
我也碰到类拟的问题。这与I/O有关。你要这I/O输出这么高的频率。要对它作相应的处理才行.

使用特权

评论回复
14
xzrsh|  楼主 | 2017-10-6 11:44 | 只看该作者
本帖最后由 xzrsh 于 2017-10-6 13:32 编辑
ihafd 发表于 2017-10-6 10:44
我也碰到类拟的问题。这与I/O有关。你要这I/O输出这么高的频率。要对它作相应的处理才行. ...

要做怎样的特别处理呢?

一开始我怀疑是板子上没有4.7uF的电容引起的瞬间电流达不到要求,从而导致上下MOS管不能完全导通,但是我试验了PWM输出,结果发现能输出36MHz的波形(示波器有点渣,看起来不是方波)。这就说明不是电流不够。



使用特权

评论回复
15
xinpian101| | 2017-10-6 11:51 | 只看该作者
那个翻转函数貌似是好几条语句操作实现的,应该有位操作。。

使用特权

评论回复
16
xzrsh|  楼主 | 2017-10-6 12:04 | 只看该作者
xinpian101 发表于 2017-10-6 11:51
那个翻转函数貌似是好几条语句操作实现的,应该有位操作。。

就是位操作:
GPIOH->BSRR = GPIO_PIN_13;
GPIOH->BSRR = ((unit32_t)GPIO_PIN_13 << 16);

但这样操作的结果是输出电平大部分在1.5V上下晃悠,偶尔才有一个正常的高电平或低电平出来。

使用特权

评论回复
17
xinpian101| | 2017-10-11 11:42 | 只看该作者
这就不太懂了,是电路问题吧,是不是有什么电容导致的,被平滑了。

使用特权

评论回复
18
yjlong5| | 2018-1-4 19:18 | 只看该作者
楼主,搞定了吗?我也遇到相同的问题。请问是怎么解决的?
谢谢!

使用特权

评论回复
19
l4157| | 2018-1-5 09:11 | 只看该作者
我猜是没有设置I/O的速度模式,GPIO port output speed register

使用特权

评论回复
20
yjlong5| | 2018-1-5 10:07 | 只看该作者
l4157 发表于 2018-1-5 09:11
我猜是没有设置I/O的速度模式,GPIO port output speed register

楼主代码中已经设置了,GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

17

帖子

1

粉丝