STC8系列单片机时钟

说明: STC8系列单片机系统时钟有3个时钟源可以选择:①内部高精度24MHz的IRC;②内部32kHz的IRC(误差较大);③外部晶体振荡器或者外部时钟信号源。

STC8系列单片机内部系统时钟结构

**注:**建议使用默认设置IRC主频24MHz,如果不选择24MHz时,当我们操作CLKDIV时,STC8A8K内会首先倍频,然后分频。也就是实际的分频设置应该是读者目标分频值与4的乘积。

系统时钟选择寄存器CKSEL

  • 说明: 通过配置系统时钟选择CKSEL寄存器来控制所选择的时钟源、输出主时钟的引脚,以及控制主时钟分频的分频因子
  • **XSFR地址:**0xFE00
  • 复位值: 0000 0000B
    系统时钟选择寄存器CKSEL
    系统时钟选择寄存器CKSEL

时钟分频寄存器CLKDIV

  • 说明: 通过时钟分频器内的分频因子CLKDIV[7:0]对主时钟MCLK分频,将分频后的时钟作为系统时钟
  • **XSFR地址:**0xFE01
  • 复位值: 0000 0100B
    时钟分频寄存器CLKDIV
    时钟分频寄存器CLKDIV

内部高精度IRC控制寄存器IRC24MCR

  • 说明: 内部24MHz高精度IRC控制寄存器IRC24MCR用于控制内部24MHz高精度IRC的工作状态
  • **XSFR地址:**0xFE02
  • 复位值: 1xxx xxx0B
    内部高精度IRC控制寄存器IRC24MCR

外部振荡器控制寄存器XOSCCR

  • 说明: 通过外部振荡器控制寄存器,可以控制外部振荡器的工作状态
  • **XSFR地址:**0xFE03
  • 复位值: 00xx xxx0B
    外部振荡器控制寄存器XOSCCR
    外部振荡器控制寄存器XOSCCR

内部32kHz低速IRC控制寄存器IRC32KCR

  • 说明: 内部32kHz低速IRC控制寄存器用于控制内部32kHz低速IRC的工作状态
  • **XSFR地址:**0xFE04
  • 复位值: 0xxx xxx0B
    内部32kHz低速IRC控制寄存器IRC32KCR

C语言实例

C语言控制STC8系列单片机输出时钟频率示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
由于我身边没有示波器,这个实验现象就不配套视频了,
身边有示波器的同学可以将示波器的红表笔接到单片机的P5.4管脚,
黑表笔注意共地,观察示波器波形是否为24MHz的128分频
*/
#include "reg51.h"
#define CKSEL (*(unsigned char volatile xdata*)0xFE00)//定义XSFR区域CLKSEL
sfr P_SW2=0xBA;//定义外设端口切换寄存器2的地址

void main()
{
P_SW2=0x80; //将P_SW2寄存器的最高位EAXFR置1,访问XSFR
CKSEL=0xE0; //选择内部24MHz晶振,对IRC分频128,分频后主时钟从P5.4引脚引出
P_SW2=0x80; //将P_SW2寄存器的最高位EAXFR置0,访问SFR
while(1);
}
C语言选择STC8系列单片机时钟源示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
打开示波器,将示波器通道1探头的负端和正端分别接到单片机GND和P5.4管脚上,
观察输出频率
*/

#include "reg51.h"

#define CKSEL (*(unsigned char volatile xdata *)0xFE00)
#define IRC32KCR (*(unsigned char volatile xdata *)0xFE04)

sfr P_SW2=0xBA;

void main()
{
P_SW2=0x80;//选中xsfr
IRC32KCR=0x80//使能32kHz低速IRC
while(!(IRC32KCR&1));//等待32kHz低速IRC时钟振荡器稳定
CKSEL=0x13;//选择内部32kHz振荡器
P_SW2=0x00;//选中sfr
while(1);
}
源代码附件下载:

STC8系列单片机复位

**说明:**STC8系列单片机的复位分为硬件复位和软件复位两种

  • 硬件复位:所以寄存器的值会复位到初始值,系统会重新读取所以的硬件选项(上电复位,低压复位,复位脚复位,看门狗复位)
  • 软件复位:除与时钟相关的寄存器保持不变,其余所以寄存器的值会复位到初始值(包括写IAP_CONTR寄存器的SWRST触发的复位)

外部RST引脚复位

外部RST引脚复位
说明:(1)当选中“复位脚用作I/O口”前面的复选框时,引脚为普通I/O,不能用于RST引脚。否则,P5.4引脚为专用的复位管脚。
(2)当P5.4引脚设置为复位引脚,则当外部复位时,需要将RST复位引脚拉高并至少维持24个时钟外加20us以后,单片机就会稳定进入复位状态,当把RST复位引脚拉低后,结束复位状态,并将特殊功能寄存器IAP_CONTR中的SWBS/IAP_CONTR.6位置1,同时从系统ISP监控区启动程序

软件复位

IAP控制寄存器
  • 说明: 传统单片机上没有这个功能,用户必须通过软件模拟来实现,但STC单片机提供的软件复位功能,通过设置IAP_CONTR寄存器中的SWBS位和SWRST位实现
  • **SFR地址:**0xC7
  • 复位值: 0000 x000B
    IAP控制寄存器
    IAP控制寄存器
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
现象:如果不加IAP_CONTR=0x60;最终现象是停在了while(1)灯熄灭了
加上IAP_CONTR=0x60单片机复位,相当于始终没有执行while(1),
完成了灯亮灭的循环,现象就是灯亮一秒灭一秒
*/

#include "reg51.h"
#include "intrins.h"

sfr IAP_CONTR=0xc7;
#define LED P1 //用LED代替P1作为名字,增加程序的通用性
sfr P5=0xc8;
sbit PNP_T=P5^5;//由电路图可知PNP三极管控制管脚为P.5管脚,当P5.5=0时,PNP三极管导通

/*
说明:延时1s,由单片机小精灵生成
参数:晶振24M,指令周期STC1T
*/
void delay1s(void) //误差 -0.000000000056us
{
unsigned char a,b,c,n;
for(c=142;c>0;c--)
for(b=168;b>0;b--)
for(a=250;a>0;a--);
for(n=2;n>0;n--);
_nop_(); //if Keil,require use intrins.h
}

void main()
{
PNP_T=0;
LED=0xFF;//灭
delay1s();
LED=0x00;//亮
delay1s();
LED=0xFF;//灭
delay1s();
IAP_CONTR=0x60;//软件复位
/*
while(1)可加可不加,最好加,优秀一点,
在现在的编译器里面默认是循环的,不会跑偏
*/
while(1);
}
现象视频:

过于简单略。

  • 现象一:不加复位,最终现象LED灯熄灭
  • 现象二:加复位,最终现象灯亮一秒灭一秒无限循环
源代码附件下载:

掉电/上电复位

说明:
(1)当电源电压VCC低于掉电/上电复位检测门限电压时,单片机内所以电路会发生复位;当内部工作电压高于掉电/上电复位检测门限电压后,延迟32768个时钟后结束掉电/上电复位过程。并将特殊功能寄存器IAP_CONTR中的SWBS/IAP_CONTR.6位置1,同时从系统ISP监控区启动程序
(2)对于5V供电的单片机来说,它的掉电复位/上电复位检测门限电压为3.2V;对于3.3V系统来说为1.8V

MAX810专用复位电路

MAX810专用复位电路
说明:
(1)当选中“上电复位使用较长延时“,允许使用STC8系列单片机内的MAX810专用集成电路(注:默认勾选,这样就省得我们自己在外部设计复位电路了,非常方便而且可靠);否则,不使用该专用复位电路
(2)当使能使用该专用复位电路时,在掉电复位/上电复位后产生约180ms的复位延时,然后才结束复位过程,并将特殊功能寄存器IAP_CONTR中的SWBS/IAP_CONTR.6位置1,同时从系统ISP监控区启动程序

内部低压检测复位

内部低压检测原理说明

内部低压检测复位
**说明:**当电源电压VCC低于内部低电压检测(LVD)门限电压,可产生复位信号(注:这需要勾选”允许抵押复位(禁止低压中断)“复选框,否则将使能低电压检测中断)
内部低压检测复位
内部低压检测复位

复位配置寄存器RSTCFG
  • 说明: 复位配置寄存器RSTCFG与低电压检测有关
  • **SFR地址:**0xFFH
  • 复位值: x0x0 xx00B
    复位配置寄存器RSTCFG

看门狗复位

看门狗复位原理说明

说明:
(1)主要用于高可靠性的一些场合,防止系统在异常情况下受到干扰,故引入看门狗机制,如果CPU不在规定的时间内按规定访问看门狗,则认为系统异常,看门狗强迫CPU进行复位,使系统重新从头开始按规律执行用户程序。
(2)当看门狗复位状态结束后,不影响特殊功能寄存器IAP_CONTR中SWBS/IAP_CONTR.6位的值

看门狗控制寄存器WDT_CONTR
  • **SFR地址:**0xC1
  • 复位值: 0x00 0000B
    看门狗控制寄存器WDT_CONTR
    看门狗控制寄存器WDT_CONTR

补充说明:
看门狗控制寄存器WDT_CONTR
在STC-ISP软件中,也提供了快捷开启看门狗定时器和设置分频系数的功能。

程序示例:

**说明:**控制STC单片机看门狗定时器复位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
程序名称:看门狗测试实验
对象:STC8A8K64S4A12 松果派mini核心板
STC-ISP烧录器相关设定:
①使能上电时由硬件自动启动看门狗,
②并设置分频系数为128
③设定输入用户程序运行时的IRC频率为20M
看门狗溢出时间计算:
溢出时间=(12*预分频值*32768)/振荡器频率
溢出时间=(12*128*32768)/20000000=2.5165824s
分析:也就是大概2.52s不喂狗它就会产生复位
现象:见下方程序分析
*/
#include "reg51.h"
#include "intrins.h"

sfr WDT_CONTR=0xc1;
sfr P5=0xc8;
sbit PNP_T=P5^5;

/*
说明:延时1s,由STC-ISP生成
指令集:STC-Y6
参数:晶振20M,指令周期STC1T
(哈哈哈,实测STC-ISP的软件延时准确度还是可以的)
*/
void Delay1000ms() //@20.000MHz
{
unsigned char i, j, k;

i = 102;
j = 118;
k = 192;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}

void Delay100ms() //@20.000MHz
{
unsigned char i, j, k;

_nop_();
_nop_();
i = 11;
j = 38;
k = 92;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}

void Delay500ms() //@20.000MHz
{
unsigned char i, j, k;

_nop_();
_nop_();
i = 51;
j = 187;
k = 222;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}

void main()
{
/*
如果在STC-ISP中勾选了上电复位由硬件自动启动开门狗,
并且在STC-ISP中选择了看门狗定时器分频系数的话,
这边可以不通过写WDT_CONTR=0x36来启动开门狗,设置分频系数
(保险起见建议还是写上)
*/
WDT_CONTR=0x36;
PNP_T=0;
P1=0x00;//亮
Delay1000ms();
P1=0xFF;//灭
Delay1000ms();
Delay500ms();
/*
如果不加上下面这句Delay100ms,在喂狗之前总共延时2.5s,
也就是说狗还没有饥饿,我便立即喂狗,并不会产生复位;
(现象就是最后停在了灯熄灭的状态)
如果加上的话,总共延时2.6s,超过了狗能保持不饿的最长时间2.52s
狗就会饿了,然后它就会爆炸,产生复位;
(此时现象就是灯一亮一暗无限循环,不断的在复位)
*/
//Delay100ms();
while(1)
WDT_CONTR=0x36;//对CLR_WDT位进行清零,即进行喂狗
}
现象视频:
源代码附件下载:

STC单片机电源模式

**说明:**STC单片机提供3种运行模式

  • 低速模式
  • 空闲模式
  • 掉电模式

电源控制寄存器PCON

  • 说明: 用于控制电源单片机进去空闲模式和掉电模式
  • **SFR地址:**0x87
  • 复位值: 0011 0000B
    电源控制寄存器PCON
    电源控制寄存器PCON

电压控制寄存器VOCTRL

  • 说明: 用于控制单片机工作静态电流
  • **SFR地址:**0xBB
  • 复位值: 0xxx xx00B
    电压控制寄存器VOCTRL

低速模式

**说明:**由始终分频器CLKDIV中的分频因子控制低速模式,通过分频从而降低单片机的工作时钟频率、降低功耗和EMI

空闲模式

** 说明:**
(1)将PCON寄存器内的IDL位置1,单片机进入空闲模式
(2)空闲模式下仅CPU无时钟,但是外部中断,内部低压检测,定时器,ADC转换器等仍正常工作。可以通过寄存器和STC-ISP软件设置空闲期间看门狗定时器是否继续计数。空闲模式下,各寄存器都保持原有的数据
(3)当产生任何一个中断时,他们均可以唤醒单片机。当唤醒单片机后,CPU继续执行进入空闲模式语句的下一条指令

程序示例:

**说明:**控制STC单片机进入和退出空闲模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
这里我发现了一个现象:STC8A系列这款单片机,
当配置为空闲模式,CPU并不是立即停止工作,
而是继续运行一个时钟周期后才停止工作,
我看的书籍和资料中均为特别指出这个问题,所以这里是存在疑问的
本实验现象:下载完程序灯保持常亮,直至触发外部中断0,暂时退出外部中断,
继续运行nop后面的灯灭一秒语句->灯亮一秒->休眠(cpu停止工作),
最终又恢复到常亮状态,继续等待外部中断触发临时退出空闲模式
*/
#include "reg51.h"
#include "intrins.h"

sfr P5=0xC8;
sbit PNP_T=P5^5;
#define LED P1


/*
由STC-ISP生成
*/
void Delay1000ms() //@24.000MHz
{
unsigned char i, j, k;

_nop_();
_nop_();
i = 122;
j = 193;
k = 128;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/*
外部中断0,P3.2管脚
对应按键K2
*/
void wakeup() interrupt 0
{

}


void main()
{
IT0=1;//只允许下降沿触发,根据实际电路配置
EX0=1;//允许外部中断0
EA=1;//CPU允许相应中断
PNP_T=0;//三极管导通,因为实际电路需要

while(1)
{
LED=0x00;//亮
Delay1000ms();
/*
使用位或操作只改动PCON.IDL位为1,屏蔽其它位,进入空闲模式,
比写PCON=xxx更加方便
*/
PCON|=0x01;//单片机进入空闲模式
/*
不知道为什么它竟然不是立即进入空闲模式,
必须加一个nop等待才进入
*/
_nop_();
LED=0xFF;//灭
Delay1000ms();
}
}

**补充原因说明:**STC8具有迟滞现象
补充原因说明

现象视频:

过于简单略。
见程序中的现象描述。

源代码附件下载:

掉电模式

说明:
(1)将PCON寄存器的PD位置1,则STC单片机进入掉电模式,也叫停机模式
(2)进入掉电模式后,单片机所使用的时钟停止振荡,包括内部系统时钟、外部晶体振荡器和外部时钟,由于没有时钟振荡,CPU、看门狗、定时器、串行口、ADC等模块停止工作,外部中断继续工作。如果允许低压检测电路产生中断,则低压检测电路可以继续工作
(3)进入掉电模式后,STC单片机的所以端口、特殊功能寄存器维持进入掉电模式前一时刻的状态不变。如果在掉电前,打开i掉电唤醒定时器,则进入掉电模式后,掉电唤醒专用定时器开始工作
(4)进入掉电模式后,可以用于唤醒的引脚资源有INT0/P3.2、INT1/P3.3(INT0/INT1上升沿和下降沿均可产生中断)、INT2/P3.6、INT3/P3.7、INT4/P3.0(仅可以下降沿产生中断)、引脚CCP0/CCP1/CCP2、引脚RxD/RxD2/RxD3/RxD4、引脚T0/T1/T2/T3/T4(前提是进入掉电模式前已经允许相应的定时器中断)、低压检测中断(前提是低压检测中断被允许,且STC-ISP中不选择“允许低压复位/禁止低压中断”)、内部低功耗掉电唤醒专用定时器

掉电唤醒专用寄存器
  • 说明: 用于管理和控制内部低功耗掉电唤醒专用定时器
  • **SFR地址:**WKTCL寄存器地址位0xAA、WKTCH寄存器地址为0xAB
  • 复位值: WKTCL复位值为1111 1111B、WKTCH复位值为0111 1111B
    掉电唤醒专用寄存器
掉电唤醒专用寄存器工作原理

说明:
(1)使能掉电唤醒专用定时器,内部掉电唤醒专用定时器{WKTCH_CNT,WKTCL_CNL}就从7FFFH开始计数,直到与{WKTCH,WKTCL}寄存器所设置的值相等后,唤醒系统振荡器。
(2)当使用内部振荡器后,MCU将在64个时钟周期后开始稳定工作;如果使用外部晶体振荡器或者时钟,则在等待1024个周期后,开始稳定工作。
(3)当CPU获得时钟后,程序从上次设置掉电模式语句的下一条语句开始往下执行。
(4)当掉电唤醒后,WKTCH_CNT寄存器和WKTCL_CNL寄存器的内容保持不变。

**注:**在设置寄存器{WKTCH,WKTCL}计数值时,按照需要的计数次数,在计数次数的基础上减去1所得到的值才是{WKTCH,WKTCL}的计数值。

补充说明:
(1)内部掉电唤醒寄存器有自己专用的内部时钟,频率约为32768Hz。对于16引脚以上封装的单片机,可以通过读取RAM区域F8和F9单元的内容获取内部掉电唤醒专用定时器常温下的时钟频率。
(2)在进入掉电模式前,CPU 会执行进入掉电模式语句的下一条语句。

计数实际计算公式:
计数实际计算公式

程序示例:

**说明:**控制STC单片机进入和退出掉电模式
(使用掉电唤醒专用寄存器实现掉电模式的唤醒)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
实验名称:STC8掉电模式测试
实验现象:小灯快速闪烁,更改后小灯闪烁速度变慢,
说明掉电唤醒专用定时器确实起到了作用
*/
#include "reg51.h"
#include "intrins.h"

sfr WKTCL=0xAA;
sfr WKTCH=0xAB;
sfr P5=0xC8;
sbit PNP_T=P5^5;
#define LED P1

void main()
{
/*
计时时间(唤醒周期)=(10^6 * 16 * (255+1))/32768 us=114.688ms
*/
WKTCL=255;
/*
设置使能掉电唤醒定时器,
将下面WKTCH=0x80改位WKTCH=0x8F会发现唤醒周期明显边长
*/
WKTCH=0x80;
PNP_T=0;
LED=0x00;
while(1)
{
LED=~LED;
PCON|=0x02;//进入掉电模式
_nop_();//必须包含1~2个NOP,STC8具有迟滞
_nop_();
//114.688ms后唤醒CPU继续循环
}
}
现象视频:

过于简单略。
见程序中的现象描述。

源代码附件下载: