IAP15单片机内存管理与NE555频率测量笔记
作者:777
最后更新:2026-02-03
一、内存管理指南
1.1 四种存储区域(Figure 3)
IAP15单片机主要有以下四种存储区域:
| 区域类型 | 关键字 | 地址范围 | 特点说明 |
|---|---|---|---|
| data | 默认(Small模型) | 0x00-0x7F | 内部RAM,访问速度最快 |
| idata | idata | 0x80-0xFF | 间接寻址内部RAM |
| pdata | pdata | 分页外部RAM | 256字节页,速度较快 |
| xdata | xdata | 外部RAM | 容量大但速度慢 |
- 特别注意

使用串口功能(如printf、sscanf)时会占用较多内存,建议合理分配变量到不同存储区。
二、NE555频率测量
2.1 测量原理
频率 = 1秒内脉冲上升沿的个数
通过计数器对脉冲进行计数,1秒读取一次计数值。
接线方法(Figure 4)
- 使用跳线帽连接 Net_SIG 和 SIG_OUT (对应P34引脚)
- 引脚对应关系:P34 ←→ 脉冲信号
- 重要提醒 :
不能使用定时器1作为计数器 !
定时器0的C/T位必须置1(计数模式)。
2.3 程序实现
2.3.1 定时器0初始化(16位计数器)
void Timer0_Init(void) // 计数器模式@12.000MHz
{
AUXR &= 0x7F; // 定时器时钟12T模式
TMOD &= 0xF0; // 清除定时器0模式位
TMOD |= 0x05; // 设置为计数器,16位不自动重载
//这边要自己修改
TL0 = 0x00; // 计数器从0开始
TH0 = 0x00;
TF0 = 0; // 清除溢出标志
TR0 = 1; // 启动计数器
}
2.3.2 定时器1初始化(1ms定时器)
unsigned int time_all_1s; // 注意:必须用unsigned int!
// unsigned char最大255,这里需要1000
void Timer1_Init(void) // 1毫秒@12.000MHz
{
AUXR &= 0xBF; // 定时器时钟12T模式
TMOD &= 0x0F; // 清除定时器1模式位
TL1 = 0x18; // 定时初值(1ms)
TH1 = 0xFC;
TF1 = 0;
TR1 = 1; // 启动定时器
ET1 = 1; // 使能定时器1中断
EA = 1; // 开总中断
}
2.3.3 定时器1中断服务程序
void Timer1_Isr(void) interrupt 3
{
if(++time_all_1s == 1000) // 累计1000ms = 1s
{
time_all_1s = 0;
// 读取计数值:高8位左移8位 + 低8位
Freq = (TH0 << 8) | TL0;
TH0 = TL0 = 0; // 计数器清零
}
}
注:取的时候是TH0和TL0都要拿出来,TH0是高八位,数据取完后,我们就可以将TL0和TH0归0
三、常见问题与解决方案
3.1 接线问题
- 问题 :测量不到频率
- 解决 :确认跳线帽正确连接 P34 和 SIGNAL 线
3.2 按键干扰问题
矩阵键盘的最后一列使用P34,会导致测量误差:
unsigned char Key_Read()
{
unsigned char temp = 0;
// 原代码:P44=0;P42=1;P35=1;P34=1;
// 修改:注释掉P34相关操作
P44 = 0; P42 = 1; P35 = 1; // P34=1; // 这行被注释
// ... 其余按键扫描代码
/* 完全注释掉使用P34的按键扫描部分
P44=1;P42=1;P35=1;P34=0;
if(P33==0) temp=16;
... // 其他按键判断
*/
return temp;
}
3.3 初始化顺序问题
必须严格按照以下顺序初始化 :
void main()
{
Timer0_Init(); // 先初始化计数器
Timer1_Init(); // 再初始化定时器
while(1)
{
// 主循环代码
}
}
3.4 第一次测量误差问题
使用标志位延迟显示,避免第一次测量值不准确:
bit show_flag_first = 0; // 显示标志位
void Seg_Proc() // 数码管显示处理
{
if(show_flag_first) // 只有标志位为1才显示
{
// 进行频率显示
}
}
void Timer1_Isr(void) interrupt 3
{
if(++time_all_1s == 1000)
{
show_flag_first = 1; // 第一次1秒后置1,之后一直为1
time_all_1s = 0;
Freq = TH0 << 8 | TL0;
TH0 = TL0 = 0;
}
}
四、总结要点
- 内存管理 :
* 优先使用Small模型
* 关键变量放data区
* 大数组可放xdata区 - 频率测量 :
* 定时器0:计数器模式(TMOD |= 0x05)
* 定时器1:1ms定时器产生1秒基准
* 注意屏蔽按键对P34的干扰 - 易错点 :
* 初始化顺序:Timer0 → Timer1
* 第一次测量需要延迟显示
* 按键扫描要避开P34引脚
