在keil MDK中定义非初始化(noini)变量

具体

可以参考ARM官方资料:ARM: Uninialized Variables Get Initialized
这里是对上述资料的总结, 该方法已在项目中得到验证。

方法:

分散加载文件如下:
定义了一个 UNINIT 段,并指定它不允许被初始化。

LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 UNINIT 0x00000100  { ;no init section
        *(NoInit)
   }
  RW_IRAM2 0x20000100 0x0000FFF0  {                ;all other rw data
        .ANY(+RW +ZI)
  }
}

使用方法

// Arm Compiler 5
unsigned long NI_longVar attribute( ( section( "NoInit"), zero_init) ) ;

// Arm Compiler 6
unsigned long NI_longVar attribute( ( section( ".bss.NoInit")) ) ;
//also modify one line of the scatterfile from:
// *(NoInit)
//to:
// *(.bss.NoInit)

注意

这里在 Arm Compiler 5 中使用的是 zero_init, 在 Arm Compiler 6 中使用的是 ".bss.NoInit"。
添加它的原因是:
首先,只有具有 UNINIT 属性的执行区域中的 ZI 数据保持未初始化状态。如果属性是 RW,那么数据依然会被初始化。
而,出于优化原因,Arm 编译器 5 默认将 8 字节或更小的全局 ZI 变量放入 RW 数据部分。如果代码中的变量小于 8 个字节,它将从 ZI 更改为 RW,从而导致初始化发生
所以,这里直接添加 zero_init 或者 ".bss.NoInit" ,避免发生上述问题。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
查看文章 STM32 keil mdk启动代码发分析_转2010年01月29日 星期五 13:50 ;// Stack Configuration ;// Stack Size (in Bytes) ;// Stack_Size EQU 0x00000200 ;//定义堆栈大小 AREA STACK, NOINIT, READWRITE, ALIGN=3 ;//定义一个数据段 按8字节对齐 ;AREA 伪指令用于定义一个代码段或数据段 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0 Stack_Mem SPACE Stack_Size ;//保留Stack_Size大小的堆栈空间 分 配连续 Stack_Size 字节的存储单元并初始化为 0 __initial_sp ;//标号,代表堆栈顶部地址,后面有用 ;// Heap Configuration ;// Heap Size (in Bytes) ;// Heap_Size EQU 0x00000020 ;//定义堆空间大小 AREA HEAP, NOINIT, READWRITE, ALIGN=3 ;//定义一个数据段,8字节对齐 __heap_base Heap_Mem SPACE Heap_Size ;//保留Heap_Size的堆空间 __heap_limit ;//标号,代表堆末尾地址,后面有用 PRESERVE8 ;//指示编译器8字节对齐 THUMB ;//指示编译器为THUMB指令 ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY ;//定义只读数据段,其实放在CODE区,位于0地址 EXTERN NMIException EXTERN HardFaultException EXTERN MemManageException EXTERN BusFaultException EXTERN UsageFaultException EXTERN SVCHandler EXTERN DebugMonitor EXTERN PendSVC EXTERN SysTickHandler ;//声明这些符号在外部定义,同C ;//在××it.c实现这些函数 ,断就能自动调用了 EXPORT __Vectors EXPORT __initial_sp ;EXPORT:在程序声明一个全局的标号__Vectors,该标号可在其他的文件引用;I
直流电机的初始化、正反转和刹车控制在Keil5环境通常是通过编写C语言代码来实现的。这里是一个简化版的例子,展示了如何使用Keil MDK(μVision)和STM32Cube库来管理直流电机: ```c #include "stm32f10x.h" // 包含STM32 HAL库 // 定义电机相关的结构体和全局变量 typedef struct { TIM_HandleTypeDef htim; // 定时器句柄 GPIO_TypeDef *GPIOx; // GPIO引脚定义 uint16_t PinA, PinB; // A和B相的GPIO引脚 } DCMotor; DMotor motor; // 初始化电机参数 void MotorInit(void) { // 初始化GPIO GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = motor.PinA | motor.PinB; GPIO_InitStruct.Mode = GPIO_MODE_AF_HighSpeed; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF2_TIM(motor.GPIOx); // 使用TIMx的通道 HAL_GPIO_Init(motor.GPIOx, &GPIO_InitStruct); // 初始化定时器 TIM_TimeBaseInitTypeDef.TIM_InitStruct; TIM_InitStruct.Prescaler = ...; // 根据系统时钟和所需的PWM频率计算预分频值 TIM_InitStruct.CounterMode = TIM_COUNTERMODE_UP; TIM_InitStruct.Period = ...; // 计算出的周期长度 TIM_InitStruct.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&motor.htim, &TIM_InitStruct); HAL_TIM_Base_Start(&motor.htim); } // 正转/反转控制函数 void MotorChangeDirection(uint8_t direction) { if (direction == LEFT) { HAL_GPIO_WritePin(motor.GPIOx, motor.PinA, GPIO_PIN_SET); HAL_GPIO_WritePin(motor.GPIOx, motor.PinB, GPIO_PIN_RESET); } else { // 右转 HAL_GPIO_WritePin(motor.GPIOx, motor.PinA, GPIO_PIN_RESET); HAL_GPIO_WritePin(motor.GPIOx, motor.PinB, GPIO_PIN_SET); } } // 刹车函数(停止电机) void MotorBrake(void) { HAL_GPIO_WritePin(motor.GPIOx, motor.PinA | motor.PinB, GPIO_PIN_SET); // 断开所有电源 motor.htim.Instance->CR1 &= ~(TIM_CR1_CEN); // 关闭定时器通道 } // 主函数调用这些函数 int main(void) { MotorInit(); while (1) { // 在主循环里切换方向或刹车 MotorChangeDirection(MOTOR_LEFT); // ...执行其他任务... MotorBrake(); // 刹车 // ...等待一段时间再恢复运行... } return 0; } ``` 请注意,这个示例假设你已经为电机接口配置了正确的硬件,并且你需要根据实际的STM32系列型号替换`GPIOx`,以及调整定时器预分频值和周期长度。此外,这里的LEFT和RIGHT只是代表正转和反转两个方向,你可以根据自己的需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值