​一、NOP指令的作用​

  • ​精确短延时​
    每个NOP消耗1个时钟周期(具体时间由主频决定)。例如240MHz主频下,1个NOP耗时约4.17ns。适用于信号稳定等待(如GPIO电平切换后插入1-2个NOP)
  • ​调试辅助​ 在关键代码行(如变量赋值后)插入NOP,便于设置调试断点,观察寄存器或内存变化 。
  • ​时序对齐​
    在多指令操作中填补时钟周期,避免硬件竞争(如通信协议时序调整)
    二、AT32中实现NOP的方法​
    不同编译器环境下需使用内联汇编:

二、AT32中实现NOP的方法

​Keil编译器​(常用):

__asm { 
    NOP  // 大写指令
    NOP  // 多个NOP可叠加
}

​GCC编译器​(如STM32CubeIDE):

__asm("nop");  // 小写指令
__asm volatile("nop");  // volatile防优化

​IAR编译器​:

__asm("nop");

​注意​:编译器优化可能删除无操作的NOP,需添加volatile关键字或局部关闭优化(如Keil的#pragma O0)

三、应用场景与限制

场景 示例 限制
GPIO信号稳定 写引脚后插入NOP,等待电平稳定HAL_GPIO_WritePin(PA5, SET); __asm(“nop”); 仅适合ns级延时,长延时需用定时器
调试断点定位​ 在变量修改后插入:sramVar = 0xAA; __asm(“nop”); // 断点设此处 量产时需移除
循环短延时 10个NOP实现~40ns延时(240MHz):for(int i=0; i<10; i++) { __asm(“nop”); } 受主频影响,需动态计算周期数

四、延时时间计算

延时公式:
延时时间=
CPU主频(Hz)
NOP数量×1

​举例​:

主频 ​120MHz​ → 单NOP耗时 ​8.33ns​
主频 ​240MHz​ → 单NOP耗时 ​4.17ns​
若需50ns延时(240MHz),需12个NOP:
for(int i=0; i<12; i++) { __asm(“nop”); }

五、完整代码示例(Keil环境)​

#include "at32f4xx.h"

void main() {
    // 初始化系统时钟(240MHz)
    system_clock_config(); 

    // 配置PC13为输出(LED)
    gpio_init_type gpio_init;
    gpio_init.gpio_pins = GPIO_PINS_13;
    gpio_init.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOC, &gpio_init);

    while(1) {
        // LED亮,插入短延时确保稳定
        gpio_bits_set(GPIOC, GPIO_PINS_13);
        __asm { NOP }  // 1周期延时
        __asm { NOP }  // 再延时1周期

        // LED灭
        gpio_bits_reset(GPIOC, GPIO_PINS_13);
        
        // 长延时用定时器,短延时用循环NOP
        for (int i=0; i<1000; i++) { 
            __asm { NOP }  // 总计4000ns延时
        }
    }
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐