完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
需求:IO产生最快的翻转脉冲。
结论:最快速度5MHz. 第一次尝试: IRC使能16M,不分频。 IO设置为推挽高速输出。 While(1)死循环翻转。 代码如下: void main(void) { CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //16M GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_SLOW); while(1) { GPIO_WriteReverse(GPIOD, GPIO_PIN_3); } } 实际波形如下 结果是只有463KHz,达不到要求。 反思是有一层函数调用的原因,没有及时翻转。 第二次尝试: 把函数去掉直接操作。 代码如下: void main(void) { CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //16M GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_SLOW); while(1) { GPIOD->ODR ^= (uint8_t)GPIO_PIN_3; } } 实际波形如下 结果已经有好转,翻转有1.311MHz。离目标还是有点远。 反思通过结构体访问寄存器,使用的是间接寻址,消耗了时间。 第三次尝试: 直接对硬件地址操作。 代码如下: void main(void) { CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //16M GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_SLOW); while(1) { *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; } } 实际波形如下 结果已经又有了进步,翻转速度是3.143Mhz.还是没有达到理想效果。 反思为什么是高电平比低电平多,是置高然后循环跳转回去指令耗时了。跳转指令有没有办法精简。 第四次尝试: 改循环语句。 代码如下: void main(void) { CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //16M GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_SLOW); /* while(1) { *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; } */ /* for(;;) { *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; } */ _LoopWrite: *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; goto _LoopWrite; } 实际汇编翻译效果: 这三种循环汇编跳转都是JRA,所以没有达到提速的效果。尝试失败。 反思是跳转耽误了时间,那尽可能的翻转,少跳转。 第五次尝试: 用空间换速度,多重复几次翻转,然后才循环。 代码如下: void main(void) { CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //16M GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_SLOW); while(1) { *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; *((uint8_t *)GPIOD_BaseAddress) = 0; *((uint8_t *)GPIOD_BaseAddress) = 0x08; } } 实际波形图如下 结果已经又有了进步,翻转速度是5.266Mhz.但是可以看到中间因为循环跳转指令带来的延时非常明显。 反思那足够多的重复指令,然后才接一次循环,就可以无限接近于没有跳转的效果。 尝试的结果是不会。当重复到一定次数,ROM存储空间存在跨页,跳转的时候会编译变长跳转,长跳转的指令周期比当前跳转机器周期长。 如果只是使用IO翻转,最大的速度只能到这么多了。 反思如果是有程序参与导致翻转速度受指令限制,那么硬件自己反应,应该比这个快。 第六次尝试: 使用PWM翻转。 代码如下: void main(void) { CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //16M GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_SLOW); TIM2_DeInit(); TIM2_TimeBaseInit(TIM2_PRESCALER_1, 0x0001); TIM2_OC2Init(TIM2_OCMODE_TOGGLE, TIM2_OUTPUTSTATE_ENABLE, 0x0000, TIM2_OCPOLARITY_HIGH); TIM2_Cmd(ENABLE); while(1) { } } 实际波形图如下 结果是3.943MHz,没有比IO直接翻转来得快。 反思是比较器比较的时候消耗了时间。 结论,IO最大的翻转速度是访问硬件地址直接操作IO。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1866 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1656 浏览 1 评论
1133 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
755 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1717 浏览 2 评论
1963浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
785浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
608浏览 3评论
627浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
589浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-9 15:58 , Processed in 0.737249 second(s), Total 45, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号