历史上的今天
今天是:2025年02月03日(星期一)
2020年02月03日 | STM8S IO最快翻转速度
2020-02-03 来源:eefocus
需求: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。
史海拾趣
|
最近我使用IWOW的TR800来做一个无线数传的项目,我在想移动既然分配给模块的ip是内网ip,那是否意味着两个模块连上GPRS网络之后,他们都是获得同一内网里的ip,就像连接到同一路由器里面的两台机器一样? 另外共享一下我觉得不错的技术QQ群 群5 ...… 查看全部问答> |
|
1,请问现在做一个LED驱动(大小功率)安规费用 第一次做个安规完,如果没过,对方提建议,也要收相同费用吗? 有没有过了才收费的; 2,过安规应该包含有电磁兼容项目吧… 查看全部问答> |
|
请问: ATM64中的PB4脚的第二功能是如何开启的? 是不是把T/C0控制寄存器TCCR0中的CS02、CS01、CS00位置0就可以了???(TCCR0=0X00) 大家一定要指点一下啊!!!!… 查看全部问答> |
|
原来用的6416的片子,现在用的2407,想问下怎么能一上电就让dsp芯片运行我的程序?小弟新手希望各位大侠教的详细点,有资料发我邮箱也可以hljlishen0517@gmail.com 多谢各位了… 查看全部问答> |
|
小弟最近遇到个问题: 在vxworks中包含usb mass storage的相关组件,启动目标板后,插入U盘,读写操作都正确,但是拔掉后,再插入,就报告dosFsDevCreate失败,查看错误号,说是设备已存在,使用 hdr = iosDevFind(\"/usb/bd\", 0); iosDevDelet ...… 查看全部问答> |
|
74系列芯片功能大全 这里是常用74系列芯片功能大全很有收藏价值 7400 TTL 2输入端四与非门7401 TTL 集电极开路2输入端四与非门7402 TTL 2输入端四或非门7403 TTL 集电极开路2输入端四与非门7404 TTL 六反相器7405 TTL 集电极开路六反相 ...… 查看全部问答> |
|
这个电路在很多网站都有 对它解释也是相同 “这是一种用于三相三线制电源缺相保护电路,A、B、C缺任何一相,光耦器输出电平低于比较器的反相输入端的基准电压,比较器输出低电平,封锁PWM驱动信号,关闭电源。比较器输入极性稍加变动 ...… 查看全部问答> |
|
TPS5430DDAR芯片过回流焊后无法正常工作,重新焊接上正常工作 如题,TPS5430DDAR芯片经过热风回流焊,峰值温度230℃左右,测试电源无法工作,将两片TPS5430DDAR用烙铁取下,交换下重新焊接上去,电源正常工作,请问这是什么原因??????… 查看全部问答> |




