今天第一次使用 aicube 生成stc8H的程序,打算仅仅先做一个led闪烁,从点灯开始。
发现一个问题:timer0的时间周期没法改,始终是32,改成200回车也变回去。输入200后,不回车,直接点保存也自动改回去!!!
先看一下main.c,主程序部分
- void main(void)
- {
- //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
- // 在此添加用户主函数初始化代码
- //<<AICUBE_USER_MAIN_INITIAL_END>>
-
- SYS_Init();
-
- //<<AICUBE_USER_MAIN_CODE_BEGIN>>
- // 在此添加主函数中运行一次的用户代码
- //<<AICUBE_USER_MAIN_CODE_END>>
-
- while (1)
- {
- //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
- // 在此添加主函数中用户主循环代码
- //<<AICUBE_USER_MAIN_LOOP_END>>
- }
- }
复制代码 其中这个 SYS_Init()函数
- void SYS_Init(void)
- {
- EnableAccessXFR(); //使能访问扩展XFR
- IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
-
- //<<AICUBE_USER_PREINITIAL_CODE_BEGIN>>
- // 在此添加用户预初始化代码
- //<<AICUBE_USER_PREINITIAL_CODE_END>>
-
- PORT2_Init(); //P2口初始化
- TIMER0_Init(); //定时器0初始化
-
- //<<AICUBE_USER_INITIAL_CODE_BEGIN>>
- // 在此添加用户初始化代码
-
- //<<AICUBE_USER_INITIAL_CODE_END>>
- }
复制代码 首先是第一个EnableAccessXFR函数
EnableAccessXFR()函数定义在 stc8h_def.h文件中
<code>#define EnableAccessXFR() SET_REG_BIT(P_SW2, EAXFR_MSK)</code>
以下是GLM的解释
这是一个在 STC8H 系列单片机编程中非常核心且常用的宏定义。它的作用是开启对扩展特殊功能寄存器(XFR)的访问权限。
下面为您详细解析这个宏定义的背景、作用以及使用时的注意事项:
1. 宏定义拆解
#define EnableAccessXFR() SET_REG_BIT(P_SW2, EAXFR_MSK)
SET_REG_BIT(reg, bit): 这是一个底层宏,作用是将某个寄存器的某一位置 1(通常实现为 reg |= bit)。
P_SW2: 这是 STC8H 单片机内的外设功能切换寄存器 2。
EAXFR_MSK: 这是 EAXFR 位的掩码(通常是 0x80,即最高位)。EAXFR 的全称是 Enable Access XFR(允许访问扩展 RAM 区的特殊功能寄存器)。
结论:这个宏的执行效果就是将 P_SW2 寄存器的最高位(EAXFR 位)置 1。
2. 为什么需要这个宏?(背景知识)
传统的 8051 单片机特殊功能寄存器(SFR)只分布在 0x80~0xFF 的地址空间内,数量非常有限。STC8H 系列单片机增加了大量高级外设(如高级 PWM、比较器、增强型串口、USB 等),传统的 SFR 空间已经装不下了。
因此,STC 扩展了一块位于扩展 RAM 区域的寄存器,称为 XFR(eXtended Function Register),地址通常分布在 0xFE00~0xFEFF。
为了防止普通 RAM 读写操作意外修改这些扩展寄存器,STC 设计了一个安全锁,即 P_SW2 寄存器的 EAXFR 位:
当 EAXFR = 0 时,单片机无法修改 XFR 区的寄存器(写操作无效)。
当 EAXFR = 1 时,单片机解锁 XFR 区,可以正常读写。
3. 如何在代码中使用?(重要规范)
在配置 STC8H 的高级外设时,必须先调用 EnableAccessXFR()。为了安全,配置完成后通常建议将其关闭(恢复为 0)。
对应的,头文件中通常也会有关闭的宏:
// 通常在 stc8h_def.h 中也会有这个定义
#define DisableAccessXFR() CLR_REG_BIT(P_SW2, EAXFR_MSK)
标准使用范例(以配置 GPIO 模式为例):
void GPIO_Init(void)
{
// 1. 开启 XFR 访问权限
EnableAccessXFR();
// 2. 配置扩展寄存器(P0M0, P0M1 在 STC8H 中被映射到了 XFR 区)
P0M0 = 0x00;
P0M1 = 0x00; // 准双向口模式
// 3. 关闭 XFR 访问权限(良好编程习惯,防止后续误操作)
DisableAccessXFR();
}
4. 注意事项
中断安全:如果你的主程序和中断服务函数(ISR)都需要操作 XFR 区的寄存器,需要注意竞争条件。如果在主程序中开启了 EAXFR,中断发生时可能会干扰当前状态。建议在 ISR 中也独立使用 EnableAccessXFR() 和 DisableAccessXFR(),或者在整个程序运行期间保持 EAXFR=1(如果对安全性要求不高)。
忘记开启的后果:如果忘记调用 EnableAccessXFR() 就去配置扩展寄存器(如 PWM 相关寄存器),代码不会报错,但寄存器的值根本写不进去,导致外设无法正常工作。这是 STC8H 开发中最常见的“坑”之一。 发现aicube给出的程序中没有 DisableAccessXFR();这句。
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
其实就是stc8h_def.h中的一个宏
#define IAP_SetTimeBase() IAP_TPS = ((SYSCLK) / 1000000UL)
IAP_TPS — IAP 等待时间控制寄存器
简单理解为
IAP_TPS = “当前 CPU 主频(MHz)”的数值,硬件用它来算出擦除/写 EEPROM 需要等多久。
|