1.定时器
Pre
1.SFR Special Function Register 特殊功能寄存器
2.T Timer 定时器
3.TCON TimerConfig 定时器控制寄存器
4.TCON的 7个
- TF1: Timer 1 Overflow Flag
- TR1: Timer 1 Run Control Bit
- TF0: Timer 0 Overflow Flag
- TR0: Timer 0 Run Control Bit
- IE1: External Interrupt 1 Edge Flag
- IT1: Interrupt 1 Type Control Bit
- IE0: External Interrupt 0 Edge Flag
- IT0: Interrupt 0 Type Control Bit
5.TMOD Timer Mode
6.OSC Oscillator 震荡器
1.1 周期时钟
开发板晶振是 11.0592MHZ,时钟周期=1/11059200秒
1.2.机器周期
单片机完成一个操作的最短时间,汇编中、每条语句占用时间位整数倍、C语言不确定。 不同单片机的 1个机器周期等于时钟周期不同 51单片机的 1个机器周期=12个时钟周期,12/11059200秒
1.3.定时器和计数器
定时器内部的寄存器(T0\T1)在一个机器周期自动+1,即12/11059200秒+1。
定时器溢出:当计数超过寄存器能存的最大数时、定时器溢出到0。如16位寄存器计数到65535后,再+1=0。
T0\T1 寄存器
存储定时器的计数值。分为高8位和低8位 T0 分为TH0、TL0;T1 分为 TH1、TL1
TCON寄存器
定时器控制寄存器
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|
| TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
| 位 | 符号 | 描述 |
|---|---|---|
| 7 | TF1 | 定时器1溢出标志。定时器1溢出硬件置1、清零方式:软件置0、定时器中断时硬件清零 |
| 6 | TR1 | 定时器1运行控制位。软件置位 设置1时启动定时器1 |
| 5 | TF0 | 定时器0溢出标志 |
| 4 | TR0 | 定时器0运行控制位 |
| 3 | IE1 | |
| 2 | IT1 | |
| 1 | IE0 | |
| 0 | IT0 |
TMOD
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|
| GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
T0/T1定时器各占4个
| 位 | 符号 | 描述 |
|---|---|---|
| 7 | GATE | 暂时不知道干嘛的 |
| 6 | C/T | 定时器功能选择、0用作定时器 1用作计数器 |
| M0 | M1 | 工作模式/描述 |
|---|---|---|
| 0 | 0 | 不知道干嘛 |
| 0 | 1 | THn和TLn组成16位的定时器 |
| 1 | 0 | 暂时不知道干嘛的 |
| 1 | 1 | 禁用定时器1,定时器0变成两个8位定时器 |
1.4 程序实例:
目标:1秒间隔闪烁LED0灯
main.c
#include <REGX52.H>
sbit LED1=P2^0;
unsigned char count = 1;
void main(){
/*
* 控制LED灯 1秒闪一次
* 1.51单片机机器周期是 12、 时钟周期是 11.0592MHZ,一个计数=12/11059200
* TH+TL =16 位、一共记录 65536个计数
* 即 12/11059200*65536 ≈ 0.071s
* 因此 每次计时 最多 0.071s
* 可以拆成 0.05*20=1s 循环20次 每次0.05秒
* 12/11059200*x=0.05,得x=46080,
* 则 计数器从 65535-46080=19455开始计数 即4BFF 每次 TH0=4B TL0=FF开始计算 实际还要加1个数
* 所以 TH0=4C TL0=00
*/
//1.使用T0、工作模式1 0000 0001
TMOD = 0X01;
//2.赋初始值
TH0 =0X00;
TL0 =0X4C;
TF0=0;
TR0 = 1;
while(1){
//每次溢出重置定时器 计数+1
if(TF0==1){
TH0 = 0X00;
TL0 = 0X4C;
TF0=0;
count++;
}
//20次后 更改led0灯状态 计数清0
if(count>=20){
LED1 = ~LED1;
count = 0;
}
}
}
2.数码管
分为共阴极(公共端输出0)、共阳极(公共端输出1) 这里选择 LEDn段输出0 LCDn端输出1 共阴级。
要解决的问题是:
1.一共有8个数码管、选择哪个数码管显示数字
2.选择了数码管之后、该数码管显示什么数字
问题1解决.选择亮哪个数码管
如开发板原理图所示,38译码器 P22-P24 选择 LED1-LED8,如:000 选择LED1、001 选择LED2... 这就解决了亮的是哪个数码管。
问题2解决.选择显示哪个数字
数码管全亮的话显示的是数字 8.,即abcdefg+dp 都显示 要显示1时 bc亮 要显示2时 abged亮 ... 那么如何让a、b、c、d...亮呢
看图得知 a连向了LCD0、而LCD0又连向了P00
因为上面选择的是LEDn输出0、所以LCDn要输出1
由图可知LCD0和P00中间还有一个74HC573
,那么如何通过P00使得通过74HC573 使得LCD0输出1呢
由74HC573逻辑图可知 P0n输出几Qn输出几、即LCDn输出几。
这里算出来的1对应bc 需要设置为OB0000 0110=0X06称作段码。 P0=OX06时,并且选择的是LCD0 这时数码管第1位会显示1。
注
数码管需要不停的输入才能一直显示。 所以数码管数字显示要写在while(){}里,不然会一闪而过。
程序实例
目标:在开发板数码管对应位置显示对应的数字
main.c
#include <REGX52.H>
#include "Delay.h"
//0-9的段码
//0 ABCDEF 0011 1111 0X3F
//1 BC 0000 0110 0X06
//2 ABGED 0110 0011 0X5B
//3 ABGCD 0100 1111 0X4F
//4 FGBC 0110 0110 0X66
//5 AFGCD 0110 1101 0X6D
//6 AFGEDC 0111 1101 0X7D
//7 ABC 0000 0111 0X07
//8 ABCDEFG 0111 1111 0X7F
//9 ABGFCD 0110 1111 0X6F
unsigned char Dig[] = {
0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F
};
//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=0;P2_3=0;P2_2=0;break;
case 2:P2_4=0;P2_3=0;P2_2=1;break;
case 3:P2_4=0;P2_3=1;P2_2=0;break;
case 4:P2_4=0;P2_3=1;P2_2=1;break;
case 5:P2_4=1;P2_3=0;P2_2=0;break;
case 6:P2_4=1;P2_3=0;P2_2=1;break;
case 7:P2_4=1;P2_3=1;P2_2=0;break;
case 8:P2_4=1;P2_3=1;P2_2=1;break;
}
P0=Dig[Number]; //段码输出
Delay(1);//显示一段时间
P0=0x00;//段码清0,消影
}
void main(){
// 让数码管 LED1 显示1
//使用共阴极 所以LEDn输出0 ,LCDn输出1
//1.选择 LED1
// P22-P24 = 000
// 000 0,00 00
//2.选择数字1
//要让b、c亮起来 通过看电路图(74HC573)1为亮 0为灭
//a=LCD0 B=LCD1 C=LCD2 D=LCD3 E=LCD4 F=LCD5 G=LCD6 DP=LCD7
// 1=BC b = LCD1 C=LCD2,0000 0110 = 0X06
// 2=ABGED 0101 1011 = 0X5B
// 1110 0011
while(1)
{
Nixie(1,1); //在数码管的第1位置显示1
Nixie(2,2); //在数码管的第2位置显示2
Nixie(3,3); //在数码管的第3位置显示3
Nixie(4,4); //在数码管的第4位置显示4
Nixie(5,5); //在数码管的第5位置显示5
Nixie(6,6); //在数码管的第6位置显示6
Nixie(7,7); //在数码管的第7位置显示7
Nixie(8,8); //在数码管的第8位置显示8
}
}