最近对STM32 GPIO的输出端高低电平变化速率产生兴趣,于是用我所知道的控制GPIO的不同方法做了测试。
单片机CPU:STM32F103ZET6
软件平台:kEIL MDK
逻辑分析仪:金沙滩 LA2016
源程序
[code=c]#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);
}
[/code]
测试结果截图
[img=http://img.bbs.csdn.net/upload/201409/27/1411816978_892218.jpg][/img][img=http://img.bbs.csdn.net/upload/201409/27/1411816988_521927.jpg][/img][img=http://img.bbs.csdn.net/upload/201409/27/1411816994_977527.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411818811_796766.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411817009_187454.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411817412_266003.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411819250_623082.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/28/1411865232_445626.jpg][/img]
从图中看出,最快的是
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,见最后一张图
如果有更快的操作方法请指教。
单片机CPU:STM32F103ZET6
软件平台:kEIL MDK
逻辑分析仪:金沙滩 LA2016
源程序
[code=c]#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);
}
[/code]
测试结果截图
[img=http://img.bbs.csdn.net/upload/201409/27/1411816978_892218.jpg][/img][img=http://img.bbs.csdn.net/upload/201409/27/1411816988_521927.jpg][/img][img=http://img.bbs.csdn.net/upload/201409/27/1411816994_977527.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411818811_796766.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411817009_187454.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411817412_266003.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/27/1411819250_623082.jpg][/img]
[img=http://img.bbs.csdn.net/upload/201409/28/1411865232_445626.jpg][/img]
从图中看出,最快的是
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,见最后一张图
如果有更快的操作方法请指教。