【单片机】— {STC15}—{期末复习笔记}

二、编程题

(二)中断

      外部中断

(一)定时器

可能是定时器T1/T0方式0(16位可自动重装初值)或者定时器T2(只有16位可自动重装初值)
T1/T0与T2除了控制寄存器的配置有些不一样,其余定时初值等都是一样的.

1、定时器T2(16位可自动重装初值)

(1)、查询法
(2)、中断法
①定时器初始化函数流程:

在这里插入图片描述

//---------------定时器2初始化函数-----&中断方法------//
void T2_Init(void)   //50毫秒@12Hz
{
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0xB0;		 //设置定时初值
	T2H = 0x3C;		 //设置定时初值
	EA = 1;        //开总中断
	IE2 |= 0X04;    //开定时器2中断允许控制位 
	AUXR |= 0x10;	//定时器2开始计时
}
②定时初值计算

  ●12分频:

t=(2na)12fsyst=\frac{(2^n-a)*12}{f_{sys}}

  ●不分频:

t=(2na)1fsyst=\frac{(2^n-a)*1}{f_{sys}}

时间t的单位位秒; (举例为50ms)
定时器应该只会考16位的,所以n=16;
系统时钟fsysf_{sys}应该是12MHz,即 12×10612×10^6Hz
若采用12分频,可算得计数初值十进制数a=15536,换算成二进制数位a=(11110010110000)2a=(‭‭11 1100 1011 0000‬‬)_2
在这里插入图片描述

③系统时钟fsysf_{sys}

课本P31
系统时钟fsysf_{sys} =主时钟foscf_{osc} / N
N为分频系数,可以通过时钟分频寄存器CLK_DIV进行改变,默认为1.

  ●
在这里插入图片描述
在这里插入图片描述
  ●方法一:
    代码:

#include<STC15.H>

#define uchar unsigned char
#define uint unsigned int
	
uchar i=0;
uchar j;

void GPIO(void);  //IO口初始化函数
void T2_Init(void); //定时器2初始化函数50毫秒@12Hz
	
void main(void)
{
	GPIO();  //IO口初始化
	T2_Init();//定时器2初始化
	while(1); //用原地踏步模拟主程序
}

void GPIO(void)  //IO口初始化函数
{
	P0M1=0;
	P0M0=0;
	P1M1=0; 
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
}

//---------------定时器2初始化函数-----&中断方法------//
void T2_Init(void)   //50毫秒@12Hz
{
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0xB0;		 //设置定时初值
	T2H = 0x3C;		 //设置定时初值
	EA = 1;        //开总中断
	IE2 |= 0X04;    //开定时器2中断允许控制位 
	AUXR |= 0x10;	//定时器2开始计时
}
//------定时器二中断服务函数0----------//
void T2_ISR(void) interrupt 12 
{
	i++;
	j=i/20;
	if(j==0||j==1) 
	{
		P46=0;
	}
	if(j==2)
	{
		P46=1;
	}
	if(j==3) i=0;
}

运行结果:
(波形图占空比,周期符合要求,但不是水平的原因可能是IO口内部RC充放电)
在这里插入图片描述
  ●方法二:
方法二改变了系统时钟fsysf_{sys} ,来获得较长的时间.定时初值的计算方法与上边所说一样,只是需要提前将系统时钟fsysf_{sys}按照公式算出.可以得到定时初值a=(3036)10(3036)_{10}

 #define x 3036  //定时1秒的初值

老师在程序中直接将3036用#define宏定义为x,(不加前缀声明数字类型时,默认为10进制数,编辑器在运行时统一将数字转化为二进制)

    T2L = x;		   //设置定时初值
	T2H = x>>8;		 //设置定时初值

T2L和T2H都是8位状态寄存器,只有8位,只能存8个数.上边第一句将x赋值给T2L,运行时编辑器自动将x转化为二进制数1011 1101 1100‬,T2L寄存器只能保存二进制数的低八位.
x右移8位,高位用0补齐,x>>8的结果位0000 1011,再将右移的结果赋值给T2H.
这种通过宏定义来赋值,是为了后续该程序容易改,考试没太有必要用,直接对T2L和T2H赋十六进制值就行.

#define uchar unsigned char
#define uint unsigned int
#define x 3036  //定时1秒的初值	
uchar i=0;

void GPIO(void);  //IO口初始化函数
void T2_Init(void); //定时器2初始化函数50毫秒@12Hz

void main(void)
{
	GPIO();  //IO口初始化
	T2_Init();//定时器2初始化
	while(1); //用原地踏步模拟主程序
}
void GPIO(void)  //IO口初始化函数
{
	P0M1=0;
	P0M0=0;
	P1M1=0; 
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
}

//---------------定时器2初始化函数-----&中断方法------//
void T2_Init(void)   //50毫秒@12Hz
{
	CLK_DIV=0x04;    //系统时钟为主时钟的16分频
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = x;		   //设置定时初值
	T2H = x>>8;		 //设置定时初值
	EA = 1;        //开总中断
	IE2 |= 0X04;    //开定时器2中断允许控制位 
	AUXR |= 0x10;		//定时器2开始计时
}

void T2_ISR(void) interrupt 12
{
	i++;
	if(i==1||i==2)
	{
		P46=0;
	}
	if(i==3)
	{
		P46=1;
		i=0;
	}
}
	

运行结果:
多次改变时钟分频寄存器CLK_DIV的值,运行结果并未产生肉眼可见的变化.不知道是代码问题还又是仿真的BUG.
在这里插入图片描述
  ●方法一,二对比
方法一是先定时一个比较小的时间,之后定时器溢出,触发中断,进入定时器中断服务函数,循环变量i再中断函数里累加.判断循环变量i是否达到预定值,多次执行中断服务函数,产生误差时间.如果定时器定时时间比较小,需要较多次数地执行中断服务函数,误差时间就会肉眼可见.
所以在使用方法一时定时器定时时间应该尽可能的大,以减小误差.
方法二,多配置一个寄存器,增加犯错概率.😷
可提前将常用定时时间准备好

2、定时器T1/T0方式0(16位可自动重装初值)

(1)、查询法
(2)、中断法
①定时器T1/T0初始化函数流程:

在这里插入图片描述

#include<STC15.H>

#define uchar unsigned char
#define uint unsigned int
	
void GPIO(void);  //IO口初始化函数
void T1_Init(void);   //定时器1初始化函数10毫秒@12MHz
	
void main(void)
{
	GPIO();   //IO口初始化
	T1_Init();//定时器1初始化
}

void GPIO(void)  //IO口初始化函数
{
	P0M1=0;
	P0M0=0;
	P1M1=0; 
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
}

//---------------定时器1初始化函数-----&中断方法------//
void T1_Init(void)   //10毫秒@12MHz
{
	AUXR &= 0xBF;	  //定时器时钟12T模式
	TMOD &= 0x0F;	  //设置定时器模式
	TL1 = 0xF0;		 //设置定时初值
	TH1 = 0xB8;		  //设置定时初值
	TF1 = 0;		  //清除TF1标志
	EA = 1;          //开总中断
	ET1 = 1;        //开定时器1中断允许控制位 
	TR1 = 1;		 //定时器1开始计时
}

void T1_ISR(void) interrupt 3
{
	
}

一、选择题

在这里插入图片描述

 ●第一章、(2)

1、在系统编程(In System Programming,ISP)
  在应用编程(In Application Programming,IAP)P14
2、STC单片机命名规则P15
 ●工作电压:F、L、W
 ●程序空间大小(程序储存器)

 ●第三章、(6)

1、任何一个中央处理单元CPU都包含有控制器运算器两大基本模块
2、通过程序计数器(Program Counter,PC)从程序存储器中源源不断地取出所要执行的代码。因此,程序计数器PC是CPU中最基本的控制部分。PC的特点就是总是指向下一条所要执行的指令的地址空间。P22
3、程序计数器的宽度为16位。也就是说,地址深度为216,地址的范围为0~65535,即64K。因此,程序存储器的深度最大为64K。
4、数据指针(Dual Data Pointer,DPTR)是一个16位的专用寄存器。
由DPL(低8位)和DPH(高8位)组成,其地址为82H(DPL,低字节)和83H(DPH,高字节)。DPTR是8051中唯一可以直接进行16位操作的寄存器。此外,也可以按照字节分别对DPH和DPL进行操作。P25
5、在STC单片机中,用于控制指向存储空间位置的是一个堆栈指针(Stack Pointer,SP)它实际上就是一个8位的专用寄存器。该寄存器的内容就是栈顶的地址,也就是用于表示当前栈顶在内部RAM块中的位置。其作用主要用于保存现场先进后出,后进先出P25
6、指针类寄存器3个,SP;DPTR;PC
7、运算器:8位算术逻辑单元ALU(核心);累加器ACC;B寄存器;程序状态字PSW P21
8、指令通道???
9、在这里插入图片描述
10、程序存储器16位的PC指向下一条要执行的指令。
CPU只能通过使用MOVC指令,从程序空间读取数据。
当单片机复位后,程序计数器(PC)的内容为0x0000。
因此,从程序存储器地址为0x0000的地方开始执行程序。另外,中断服务程序的入口地址(也称为中断向量)也放在程序存储单元。
11、STC系列单片机内部提供了大容量的数据Flash存储器,用于实现电可擦除的**只读存储器(EEPROM)**功能。
数据Flash存储器和程序Flash存储器空间是分开的。
12、在这里插入图片描述

 ●第五章、(4)

1、中断请求,中断响应,中断服务,中断返回
2、在这里插入图片描述
3、在这里插入图片描述
4、在这里插入图片描述
5、在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章