- AT89C51只有两个定时器,一个串口,两个外部中断
- 时钟周期又称振荡周期,由晶振决定 = 1/fsc
- 状态周期 = 2*时钟周期
- 机器周期 = 6状态周期 = 12时钟周期
- 指令周期:执行指令所需的所有时间,不同的指令所需的时间不同。
- 执行指令需要一个机器周期(12MHz => 1us)
- 双周期指令:执行指令需要两个机器周期(12MHz => 2us)
- 四周期指令:执行指令需要四个机器周期(12MHz => 4us)
- P0(AD0-7)为8位漏级开路双向I/O口(需要外部上拉电阻)
- P1、P2(A8-15):标准I/O【P1.0/T2,P1.1/T2EX】
- P3特殊功能I/O,也可作为普通I/O
- P3.0/RXD
- P3.1/TXD
- P3.2/INT0*
- P3.3/INT1*
- P3.4/T0
- P3.5/T1
- P3.6/WR*
- P3.7/RD*
- RST:复位引脚
- ALE / PROG  ̄ \overline{\text{PROG}} PROG:访问外部数据存储器/程序存储器
- PSEN  ̄ \overline{\text{PSEN}} PSEN:允许程序存储器
- EA/VPP:允许外部访问
TR0
SFR(红色可位搜索) |
符号 |
字节(物理)地址 |
位名称 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
P0 |
P0 |
80H |
P0.7 |
P0.6 |
P0.5 |
P0.4 |
P0.3 |
P0.2 |
P0.1 |
P0.0 |
堆栈指针 |
SP |
81H |
|
|
|
|
|
|
|
|
数据指针DPTR |
DPH |
82H |
|
|
|
|
|
|
|
|
DPL |
83H |
|
|
|
|
|
|
|
|
保留3字节 |
|
84H-86H |
|
|
|
|
|
|
|
|
电源和波特率 |
PCON |
87H |
SMOD |
|
|
|
GF1 |
GF0 |
PD |
IDL |
定时器控制寄存器 |
TCON |
88H |
TF1 |
TR1 |
TF0 | IE1 |
IT1 |
IE0 |
IT0 |
定时器计数器方式控制 |
TMOD |
89H |
GATE1 |
C/T*1 |
M1_1 |
M1_0 |
GATE0 |
C/T*0 |
M0_1 |
M0_0 |
定时器计数器0L |
TL0 |
8AH |
|
|
|
|
|
|
|
|
定时器计数器1L |
TL1 |
8BH |
|
|
|
|
|
|
|
|
定时器计数器0H |
TH0 |
8CH |
|
|
|
|
|
|
|
|
定时器计数器1H |
TH1 |
8DH |
|
|
|
|
|
|
|
|
保留2Byte |
|
8EH-8FH |
|
|
|
|
|
|
|
|
P1 |
P1 |
90H |
P1.7 |
P1.6 |
P1.5 |
P1.4 |
P1.3 |
P1.2 |
P1.1 |
P1.0 |
保留7Byte |
|
91H-97H |
|
|
|
|
|
|
|
|
串行控制 |
SCON |
98H |
SM0 |
SM1 |
SM2 |
REN |
TB8 |
RB8 |
TI |
RI |
串行缓冲区 |
SBUF |
99H |
|
|
|
|
|
|
|
|
P2 |
P2 |
A0H |
P2.7 |
P2.6 |
P2.5 |
P2.4 |
P2.3 |
P2.2 |
P2.1 |
P2.0 |
中断允许 |
IE |
A8H |
EA |
|
ET2 (reg52.h //8052 only) |
ES |
ET1 |
EX1 |
ET0 |
EX0 |
P3 |
P3 |
B0H |
P3.7 |
P3.6 |
P3.5 |
P3.4 |
P3.3 |
P3.2 |
P3.1 |
P3.0 |
中断优先 |
IP |
B8H |
|
|
PT2 (reg52.h) |
PS |
PT1 |
PX1 |
PT0 |
PX0 |
定时器/计数器2 |
T2CON |
C8H |
TF2 |
EXF2 |
RCLK |
TCLK |
EXEN2 |
TR2 |
C/T*2 |
CP/RL2 |
定时器/计数器2模式 |
T2MOD |
C9H |
|
|
|
|
|
|
T2OE |
DCEN |
捕获 |
RCPA2L |
CAH |
|
|
|
|
|
|
|
|
RCPA2H |
CBH |
|
|
|
|
|
|
|
|
定时器/计数器2高低位 |
TL2 |
CCH |
|
|
|
|
|
|
|
|
TH2 |
CDH |
|
|
|
|
|
|
|
|
程序状态字 |
PSW |
D0H |
CY |
AC |
F0 |
RS1 |
RS0 |
OV |
|
PF |
累加器 |
ACC |
E0H |
|
|
|
|
|
|
|
|
寄存器B |
B |
F0H |
|
|
|
|
|
|
|
|
定时器计数器控制寄存器 |
TCON |
88H |
TF1 |
TR1 |
TF0 |
TR0 |
IE1 |
IT1 |
IE0 |
IT0 |
定时器计数器方式控制 |
TMOD |
89H |
GATE1 |
C/T*1 |
M1_1 |
M1_0 |
GATE0 |
C/T*0 |
M0_1 |
M0_0 |
中断允许 |
IE |
A8H |
EA |
|
|
ES |
ET1 |
EX1 |
ET0 |
EX0 |
定时器计数器0L |
TL0 |
8AH |
|
|
|
|
|
|
|
|
定时器计数器1L |
TL1 |
8BH |
|
|
|
|
|
|
|
|
定时器计数器0H |
TH0 |
8CH |
|
|
|
|
|
|
|
|
定时器计数器1H |
TH1 |
8DH |
|
|
|
|
|
|
|
|
M1M0 |
工作方式 |
功能 |
备注 |
00 |
0 |
13位(不可重装) |
高5位加低8位 |
01 |
1 |
16位不可重装 |
\ |
10 |
2 |
8位自动重装 |
TH值==>>TL值 |
11 |
3 |
两个8位计数器(只适用于T0) |
|
定时器/计数器2 |
T2CON |
C8H |
TF2 |
EXF2 |
RCLK |
TCLK |
EXEN2 |
TR2 |
C/T*2 |
CP/RL2 |
定时器/计数器2模式 |
T2MOD |
C9H |
|
|
|
|
|
|
T2OE |
DCEN |
定时器/计数器2高低位 |
TL2 |
CCH |
|
|
|
|
|
|
|
|
TH2 |
CDH |
|
|
|
|
|
|
|
|
捕获 |
RCPA2L |
CAH |
|
|
|
|
|
|
|
|
RCPA2H |
CBH |
|
|
|
|
|
|
|
|
- 有两个信号源:①内部时钟溢出TF2。②外部T2EX负跳沿。
- 定时器2有三个工作方式
RCLK |
TCLK |
CP/R2 |
EXEN2 |
工作方式 |
1 |
1 |
x |
x |
波特率发生器 |
0 |
0 |
1 |
1 |
外部T2EX*捕获 |
0 |
0 |
1 |
0 |
\ |
0 |
0 |
0 |
1 |
外部T2EX*重装 |
0 |
0 |
0 |
0 |
溢出自动重装 |
- T2CON
- TF2:T2溢出标志,硬件置位,软件清零
- EXF2:定时器2外部标志。当EXEN2=1,且当T2EX引脚上出现负跳变而出现捕获或重装载时,EXF2置位,申请中断.此时如果允许定时器2中断,CPU响应中断,执行定时器2中断服务程序,EXF2必须由软件清除。当定时器2工作在向上或向下计数工作方式时(DCEN=1) , ExF2不能激活中断。
- 串行通信(工作模式1和3下【注:工作模式0、2为波特率不可变】)设置
- RCLK:接收时钟允许。1:用T2溢出脉冲作为串行口的接收时钟。0:用Tl的溢出脉冲作为接收时钟。
- TCLK:发送时钟允许。同上。
- EXEN2:T2外部允许标志。【定时器2未用于作串行口的波特率发生器】
- 1:T2 捕获或重装载
- 0:T2EX端的外部信号无效。
- TR2:定时器2启动、暂停
- C/T*:定时器2计数方式。C模式:下跳沿触发
- CP/RL2:捕获/重装载选择。【与EXEN2关联】
- l:T2EN双端出现负跳变脉冲时发生捕获操作。
- 0:若定时器2溢出或EXEN2=l条件下,T2EN双端出现负跳变脉冲,都会出现自动重装载操作。当RCLK=1或TCLK=1时,该位无效,在定时器2溢出时强制其自动重装载。
定时器/计数器2模式 |
T2MOD |
C9H |
|
|
|
|
|
|
T2OE |
DCEN |
- T2OE:T2输出允许位,当T2OE=1的时候,允许时钟输出到P1.0。(仅对80C54/80C58有效)
- DCEN:向下计数允许位。DCEN=1是允许T2向下计数,否则向上计数。
- 当EXEN2=0时,只当作一个16bit定时器/计数器。
- 当EXEN2=1,出现T2EN时下跳,将T2H、L装入RCAPH、L
- 用RCAPH、L重装
- 波 特 率 = 振 荡 频 率 32 × [ 65536 − ( R C P A 2 H , R C P A 2 L ) B ] 波特率=\frac{振荡频率}{32×[65536-(RCPA2H,RCPA2L)_B]} 波特率=32×[65536−(RCPA2H,RCPA2L)B]振荡频率
#include
char timer0 = ; //T0计数值
char timer0_1 = ; //模式3下另一个计数器
void init_T0();
int main(){
Intr_init();
Timer0_init();
while(1)
{
/* idle process */
};
return 0;
}
/* 中断初始化 */
void Intr_init()
{
ET0 = 1; //开T0中断
ET1 = 1; //开T1中断
EA = 1;
}
/* 定时器初始化 */
void Timer0_init()
{
//初始化定时器0初值
/*******模式0*********/
TH0 = (8192 - timer0)/255;
TL0 = (8192 - timer0)%255;
/*
*******模式1*********
TH0 = (65536 - timer0)/255;
TL0 = (65536 - timer0)%255;
*******模式2*********
TH0 = 256 - timer0;
TL0 = 256 - timer0;
*******模式3*********
TH0 = 256 - timer0;
TL0 = 256 - timer0_1;
*/
//定时器模式选择
//参考寄存器表
TMOD = 0x00; //模式0:13位
/*
TMOD = 0x01; //模式1:16位
TMOD = 0x02; //模式2:8位自动重装
TMOD = 0x03; //两个8位
TMOD = TMOD | 0x04; //计数器模式
TMOD = TMOD | 0x08; //门控使能
*/
TR0 = 1;
//TR1 = 1;
}
/* T0中断服务程序 */
void intr_T0() interrupt 1
{
/* do something */
}
#include
char timer2 = ;
void init_T2();
int main(){
Intr_init();
Timer2_init();
while(1)
{
};
return 0;
}
void Intr_init()
{
PT2 = 1;
EA = 1;
}
void Timer2_init()
{
TH0 = (65536 - timer2)/255;
TL0 = (65536 - timer2)%255;
RCAP2L = (65536 - timer2)/255;
RCAP2H = (65536 - timer2)%255;
RCLK = 1;
TCLK = 1;
TR2 = 1;
}
void intr_T2() interrupt 5
{
TF2 = 0;
}
中断号 |
中断地址 |
中断功能 |
0 |
03H |
EX0 |
1 |
0BH |
T0 |
2 |
13H |
EX1 |
3 |
1BH |
T1 |
4 |
23H |
ES |
5 |
2BH |
ET2 |
IP^ |
中断功能 |
0 |
EX0 |
1 |
T0 |
2 |
EX1 |
3 |
T1 |
4 |
ES |
5 |
ET2 |
### 串口UART1
串行控制 |
SCON |
98H |
SM0 |
SM1 |
SM2 |
REN |
TB8 |
RB8 |
TI |
RI |
串行缓冲区 |
SBUF |
99H |
|
|
|
|
|
|
|
|
- SM2:多机通信控制位
- SM0、SM1:串口工作模式
SM0 |
SM1 |
说明 |
波特率 |
0 |
0 |
同步移位寄存器 |
Fosc/12 |
0 |
1 |
10bit帧、8bitdata |
定时器T1/T2 |
1 |
0 |
11bit帧、8bit、1bit多机 |
Fosc/32或Fosc/64 |
1 |
1 |
11bit帧、8bit、1bit多机 |
T1/T2 |
- REN:接收使能
- T、RB8:11bit帧作为第九位
- TI、RI:发送接收中断标志,硬件置位,软件清零
#include
void Intr_init();
void UartInit();
void send_data(unsigned char x);
unsigned char recieve_data();
unsigned char buf = 0;
int main(){
Intr_init();
UartInit();
send_data(buf);
buf = recieve_data();
while(1);
return 0;
}
void Intr_init()
{
EA = 1;
ES = 0;
}
void send_data(unsigned char x)
{
SBUF = x;
while(TI == 0);
TI = 0;
}
unsigned char recieve_data(){
unsigned char x;
while(RI == 0);
x = SBUF;
RI = 0;
return x;
}
void UartInit()
{
PCON &= 0x7F;
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = 0xD9;
TH1 = 0xD9;
ET1 = 0;
TR1 = 1;
}
#include
void Intr_init();
void UartInit();
char busy = 0;
unsigned char buf = 0;
int main(){
Intr_init();
UartInit();
while(1)
{
if(busy == 0)
{
SBUF = 0x25;
busy = 1;
}
};
return 0;
}
void Intr_init()
{
EA = 1;
ES = 1;
ET1 = 0;
}
void UartInit() //9600bps@12.000MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xD9; //设置定时初始值
TH1 = 0xD9; //设置定时重载值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
}
void Uart_Intr() interrupt 4
{
if(RI)
{
RI = 0;
/* do something */
}
else if(TI)
{
TI = 0;
busy = 0;
/* do something */
}
}
#include
#include
void Intr_init();
void UartInit();
char send_busy = 0;
char write_busy = 0;
unsigned char buf = 0;
/* 重定向 */
//UART1 发送串口数据
void UART1_SendData(char dat)
{
ES=0; //关串口中断
SBUF=dat;
while(TI!=1); //等待发送成功
TI=0; //清除发送中断标志
ES=1; //开串口中断
}
//重写putchar函数
char putchar(char c)
{
UART1_SendData(c);
return c;
}
int main(){
Intr_init();
UartInit();
while(1)
{
printf("字符串");
};
return 0;
}
void Intr_init()
{
EA = 1;
ES = 0;
ET1 = 0;
}
void UartInit() //9600bps@12.000MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xD9; //设置定时初始值
TH1 = 0xD9; //设置定时重载值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
}
电源和波特率 |
PCON |
87H |
SMOD |
|
|
|
GF1 |
GF0 |
PD |
IDL |
- PD:掉电工作位
- IDL:空闲工作位
- GF:系统保留通用标志
- CY:进位标志
- AC:辅助进位标志
- F0、F1:用户定义
- RS1、0:工作寄存器
- OV:溢出标志
- P:奇偶标志:1–>奇
- 在AT89C52基础增加
- 【看门狗】
- 【IAP】
- 【可编程时钟输出】
- 【P3 I/O控制寄存器】
- 在AT89C52基础减去
- 修改定时器工作模式0为16位重装载
SFR |
符号 |
字节(物理)地址 |
位名称 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
电源控制寄存器 |
PCON |
87H |
- |
- |
LVDF |
- |
GF1 |
GF0 |
PD |
IDL |
辅助寄存器0 |
AUXR |
8EH |
T0*12 |
T1*12 |
- |
- |
- |
- |
- |
- |
INT_CLKO |
INT_CLKO |
8FH |
- |
EX4 |
EX3 |
EX2 |
- |
- |
T1CLKO |
T0CLKO |
CLK_DIV |
CLK_DIV |
97H |
- |
- |
- |
- |
- |
CLKS2 |
CLKS1 |
CLKS0 |
P3M1 |
P3M1 |
B1H |
|
|
|
|
|
|
|
|
P3M0 |
P3M0 |
B2H |
|
|
|
|
|
|
|
|
IRC_CLKO |
IRC_CLKO |
BBH |
- |
- |
- |
- |
- |
- |
IRCS1 |
IRCS0 |
WDT_CONR |
WDT_CONR |
C1H |
|
|
|
|
|
|
|
|
ISP/IAP Flash数据寄存器 |
IAP_DATA |
C2H |
|
|
|
|
|
|
|
|
ISP/IAP Flash地址高8bit |
IAP_ADDRH |
C3H |
|
|
|
|
|
|
|
|
ISP/IAP Flash地址低8bit |
IAP_ADDRL |
C4H |
|
|
|
|
|
|
|
|
ISP/IAP命令寄存器 |
IAP_CMD |
C5H |
- |
- |
- |
- |
- |
- |
MS1 |
MS0 |
ISP/IAP命令触发器 |
IAP_TRIG |
C6H |
|
|
|
|
|
|
|
|
ISP/IAP控制寄存器 |
IAP_CONTR |
C7H |
IAPEN |
SWBS |
SWRST |
CMD_FAIL |
- |
WT2 |
WT1 |
WT0 |
CLK_DIV |
CLK_DIV |
97H |
- |
- |
- |
- |
- |
CLKS2 |
CLKS1 |
CLKS0 |
CLKS2 |
CLKS1 |
CLKS0 |
分频系数 |
0 |
0 |
0 |
/1 |
0 |
0 |
1 |
/2 |
0 |
1 |
0 |
/4 |
0 |
1 |
1 |
/8 |
1 |
0 |
0 |
/16 |
1 |
0 |
1 |
/32 |
1 |
1 |
0 |
/64 |
1 |
1 |
1 |
/128 |
- 有三路可编程时钟输出
- IRC_CLKO/P3.4
- CLK_OUT0/P3.5
- CLK_OUT1/P3.4
- 寄存器
辅助寄存器0 |
AUXR |
8EH |
T0*12 |
T1*12 |
- |
- |
- |
- |
- |
- |
INT_CLKO |
INT_CLKO |
8FH |
- |
EX4 |
EX3 |
EX2 |
- |
- |
T1CLKO |
T0CLKO |
IRC_CLKO |
IRC_CLKO |
BBH |
- |
- |
- |
- |
- |
- |
IRCS1 |
IRCS0 |
- AUXR
- T*12:定时器速度是传统51的12倍**【计数时钟为系统(晶振)时钟】**
- INT_CLKO
【关闭定时器中断,定时器工作于方式0或者2】
- T1CLKO:管脚P3.5允许时钟输出【定时器1】
- T0CLKO:管脚P3.4允许时钟输出【定时器0】
- 输出时钟频率= T溢出率 / 2
- IRC_CLKO
IRCS1 |
IRCS0 |
输出频率 |
0 |
0 |
无时钟输出 |
0 |
1 |
内部时钟输出不分频 |
1 |
0 |
2分频 |
1 |
1 |
4分频 |
P3M1[5:0] |
P3M0[5:0] |
I/O模式 |
0 |
0 |
标准双向I/O |
0 |
1 |
推挽 |
1 |
0 |
高阻 |
1 |
1 |
开漏(外加上拉电阻) |
- 1KB/2KB数据EEPROM
- 每个扇区512(0.5K)字节数据
ISP/IAP Flash数据寄存器 |
IAP_DATA |
C2H |
|
|
|
|
|
|
|
|
ISP/IAP Flash地址高8bit |
IAP_ADDRH |
C3H |
|
|
|
|
|
|
|
|
ISP/IAP Flash地址低8bit |
IAP_ADDRL |
C4H |
|
|
|
|
|
|
|
|
ISP/IAP命令寄存器 |
IAP_CMD |
C5H |
- |
- |
- |
- |
- |
- |
MS1 |
MS0 |
ISP/IAP命令触发器 |
IAP_TRIG |
C6H |
|
|
|
|
|
|
|
|
ISP/IAP控制寄存器 |
IAP_CONTR |
C7H |
IAPEN |
SWBS |
SWRST |
CMD_FAIL |
- |
WT2 |
WT1 |
WT0 |
MS1 |
MS0 |
命令内容 |
0 |
0 |
待机、无操作 |
0 |
1 |
对数据Flash区读字节 |
1 |
0 |
对数据Flash区进行字节编程 |
1 |
1 |
对数据Flash扇区进行擦除 |
ISP/IAP控制寄存器 |
IAP_CONTR |
C7H |
IAPEN |
SWBS |
SWRST |
CMD_FAIL |
- |
WT2 |
WT1 |
WT0 |
- IAPEN:IAP读写擦使能
- SWBS:0:软件选择从用户应用程序启动;1:从系统ISP监控程序区启动
- SWRST:1:软件复位
- CMD_FAIL:触发命令失败标志位,软件清零
- WT2-0:设置等待时间(见下表)
WT2 |
WT1 |
WT0 |
Read |
Program |
Sector Erase |
推荐系统时钟 |
0 |
0 |
0 |
2个时钟 |
55个时钟 |
21012个时钟 |
<=1MHz |
0 |
0 |
1 |
2个时钟 |
110个时钟 |
42024个时钟 |
<=2MHz |
0 |
1 |
0 |
2个时钟 |
165个时钟 |
63036个时钟 |
<=3MHz |
0 |
1 |
1 |
2个时钟 |
330个时钟 |
126072个时钟 |
<=6MHz |
1 |
0 |
0 |
2个时钟 |
660个时钟 |
252114个时钟 |
<=12MHz |
1 |
0 |
1 |
2个时钟 |
1100个时钟 |
420240个时钟 |
<=20MHz |
1 |
1 |
0 |
2个时钟 |
1320个时钟 |
504288个时钟 |
<=24MHz |
1 |
1 |
1 |
2个时钟 |
1760个时钟 |
672384个时钟 |
<=30MHz |
#include
#include
typedef unsigned char Byte;
typedef unsigned int Word;
sfr IAP_DATA = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD = 0xC5;
sfr IAP_TRIG = 0xC6;
sfr IAP_CONTR = 0xC7;
#define CMD_IDLE 0
#define CMD_READ 1