最近对STM32 GPIO的输出端高低电平变化速率产生兴趣,于是用我所知道的控制GPIO的不同方法做了测试。
单片机CPU:STM32F103ZET6
软件平台:kEIL MDK
逻辑分析仪:金沙滩 LA2016
源程序
#include "stm32f10x.h"
#define PA0 GPIOA ->ODR
//位绑定操作开始
#define GPIOA_ODR_ADDR (GPIOA_BASE + 0x0C) //0x0C是ODR的地址偏移,见数据手册
#define GPIOA_IDR_ADDR (GPIOA_BASE + 0x08) //0x08是IDR的地址偏移
#define BitBand(Addr,BitNum) *(volatile unsigned long *)((Addr&0xF0000000)+0x02000000 + ((Addr&0xFFFFF)<<5) + (BitNum<<2) )
#define PAout(n) BitBand(GPIOA_ODR_ADDR,n)
#define PAin(n) BitBand(GPIOA_IDR_ADDR,n)
//位绑定结束,如要绑定其他IO口,只需把GPIOA换成GPIOB GPIOC.....GPIOF即可,n(0~31)表示第几个IO
u32 *PAO0 = (u32 *)(0x42000000+(0x40000000 + 0x10000 + 0x0800 + 0x0C -0x40000000 )*32+4*0);
u32 *PAI0 = (u32 *)(0x42000000+(0x40000000 + 0x10000 + 0x0800 + 0x08 -0x40000000 )*32+4*1);
int main(void)
{
GPIOA ->CRL = 0xC3; //因为要把PA.1作为输入,所以有C,如果不用可设置为 0x03
while(1)
{
//*PAO0 = !*PAO0 ;
//*PAO0=1;
//*PAO0=0;
GPIOA ->ODR = 0x1;
GPIOA ->ODR = 0x0;
//GPIO_SetBits (GPIOA,GPIO_Pin_0 );
//GPIO_ResetBits (GPIOA,GPIO_Pin_0 );
//PA0 = 0x01;
//PA0 = 0x00;
//PA0 =!PA0;
//GPIOA ->BSRR = 0x01;
//GPIOA ->BRR = 0x01;
//PAout(0)=1;
//PAout(0)=0;
}
return(1);
}
测试结果截图








从图中看出,最快的是
GPIOA ->ODR = 0x1; GPIOA ->ODR = 0x0;
和 PA0 = 0x01;PA0 = 0x00;
和 GPIOA ->BSRR = 0x01; GPIOA ->BRR = 0x01;
转换周期是220ns,4.55Mhz
最慢的是 *PAO0 = !*PAO0 ; 和 PA0 =!PA0; 取反操作浪费不少时间
转换周期是900ns 1.11Mhz
用位绑定函数操作最方便,速度稍微慢一点,是320ns,见最后一张图
如果有更快的操作方法请指教。
------解决思路----------------------
这个对比汇编指令就可以了 查看运行了多少个时钟周期
------解决思路----------------------
好好研读下,一定的
------解决思路----------------------
从汇编就知道哪些周期长了。
*PAO0 = !*PAO0
1 读PAO0
2 取反
3 写PAO0
GPIOA ->ODR = 0x1
1 写PAO0
注意 每个过程有1个或者多个机器周期
------解决思路----------------------
我还以为楼主想测波形的突变时间,这个响应时间可以看会变代码估算,就和楼上几位说的一样,倒是那个电平转换时下降沿或者上升沿的时间,那个测起来麻烦点,需要高速示波器