STC15系列学习

Posted 拖孩_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STC15系列学习相关的知识,希望对你有一定的参考价值。

51系列

  • 参考资料为各芯片数据手册,可在STC官网获取

AT89C52基础模块

  • 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\\textPROG PROG:访问外部数据存储器/程序存储器
  • PSEN ‾ \\overline\\textPSEN PSEN:程序储存器允许
  • EA/VPP:外部访问允许

存储器结构

RAM:0-1F

  • 工作寄存器组:4组*8个Ri

RAM:20-2F

  • 位寻址区

RAM:30-7F

  • 通用RAM

RAM:80-FF

SFR(红色可位寻址)符号字节(物理)地址位名称
D7D6D5D4D3D2D1D0
P0P080HP0.7P0.6P0.5P0.4P0.3P0.2P0.1P0.0
堆栈指针SP81H
数据指针DPTRDPH82H
DPL83H
保留3字节84H-86H
电源和波特率PCON87HSMOD GF1 GF0 PD IDL
定时器计数器控制寄存器TCON88HTF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
定时器计数器方式控制TMOD89HGATE1 C/T*1 M1_1 M1_0 GATE0 C/T*0 M0_1 M0_0
定时器计数器0LTL08AH
定时器计数器1LTL18BH
定时器计数器0HTH08CH
定时器计数器1HTH18DH
保留2Byte8EH-8FH
P1P190HP1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
保留7Byte91H-97H
串行控制SCON98HSM0 SM1 SM2 REN TB8 RB8 TI RI
串行缓冲区SBUF99H
P2P2A0HP2.7 P2.6 P2.5 P2.4 P2.3 P2.2 P2.1 P2.0
中断允许IEA8HEA ET2
(reg52.h //8052 only)
ES ET1 EX1 ET0 EX0
P3P3B0HP3.7 P3.6 P3.5 P3.4 P3.3 P3.2 P3.1 P3.0
中断优先IPB8H PT2
(reg52.h)
PS PT1 PX1 PT0 PX0
定时器/计数器2T2CONC8HTF2 EXF2 RCLK TCLK EXEN2 TR2 C/T*2 CP/RL2
定时器/计数器2模式T2MODC9H T2OE DCEN
捕获RCPA2LCAH
RCPA2HCBH
定时器/计数器2高低位TL2CCH
TH2CDH
程序状态字PSWD0HCY AC F0 RS1 RS0 OV PF
累加器ACCE0H
寄存器BBF0H

定时器

  • 计数周期为:机器周期

定时器/计数器0、1

  • 寄存器
定时器计数器控制寄存器TCON88HTF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
定时器计数器方式控制TMOD89HGATE1 C/T*1 M1_1 M1_0 GATE0 C/T*0 M0_1 M0_0
中断允许IEA8HEA ES ET1 EX1 ET0 EX0
定时器计数器0LTL08AH
定时器计数器1LTL18BH
定时器计数器0HTH08CH
定时器计数器1HTH18DH
  • TCON
    • TF:定时器/计数器中断标志-----【硬件置位清零】
    • TR:定时器/计数器运行标志
  • TMOD
    • GATE:门控开关。0:软件启动。1:TR=1的同时还需要外部 INT0、INT1 为1才能启动。
    • C/T*:定时器/计数器选择,0:应用为定时器。1:应用为计数器。
    • M0、M1:工作模式选择,见下表
M1M0工作方式功能备注
00013位(不可重装)高5位加低8位
01116位不可重装\\
1028位自动重装TH值==>>TL值
113两个8位计数器(只适用于T0)
  • IE 【EA = 1】
    • ET对应置为才能启用中断功能

定时器T2

  • 中断软件清零
  • 寄存器
定时器/计数器2T2CONC8HTF2 EXF2 RCLK TCLK EXEN2 TR2 C/T*2 CP/RL2
定时器/计数器2模式T2MOD C9H T2OE DCEN
定时器/计数器2高低位TL2CCH
TH2CDH
捕获RCPA2LCAH
RCPA2HCBH

T2CON
  • 有两个信号源:①内部时钟溢出TF2。②外部T2EX负跳沿。
  • 定时器2有三个工作方式
    • 捕获方式
    • 自动重装(向上/下计数)
    • 波特率发生器
RCLKTCLKCP/R2EXEN2工作方式
11xx波特率发生器
0011外部T2EX*捕获
0010\\
0001外部T2EX*重装
0000溢出自动重装
  • 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向下计数,否则向上计数。
重装模式
  • 用RCAPH、L值装入T2H、L
捕获模式
  • 当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]

调用方法

定时器0、1
#include <reg52.h>
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 */

定时器2
#include <reg52.h>
char timer2 = ;	    //T0计数值
void init_T2();

int main()
    Intr_init();
    Timer2_init();
    while(1)
    
        /* idle process */
    ;
    return 0;


/* 中断初始化 */
void Intr_init()

    /* 波特率模式下不需中断 */
	//ET2 = 1;		//开T2中断
    //修改中断优先级
    PT2 = 1;
    EA = 1;

/* 定时器初始化 */
void Timer2_init()

	//初始化定时器2初值
    /*******波特率模式*********/
    TH0 = (65536 - timer2)/255;
    TL0 = (65536 - timer2)%255;
    RCAP2L = (65536 - timer2)/255;
    RCAP2H = (65536 - timer2)%255;
    /*
    *******捕获模式*********
    TH0 = 0x00;
	TL0 = 0x00;

    *******重装模式*********
    TH0 = 65536 - timer2;
    TL0 = 65536 - timer2;
    RCAP2L = 65536 - timer2;
    RCAP2H = 65536 - timer2;
    */

    //定时器2模式选择
    //参考寄存器表
    RCLK = 1;    //波特率发生器模式
    TCLK = 1;
    /*
    EXEN2 = 1;  //使能外部引脚
    CP_RL2 = 1;    //捕获模式
    C_T2 = 1;   //使用计数器
    */
    TR2 = 1;

/* T0中断服务程序 */
void intr_T2() interrupt 5

    TF2 = 0;    //软件清零
    //EXF2 = 0;
	/* do something */

中断

  • 中断向量表
中断号中断地址中断功能
003HEX0
10BHT0
213HEX1
31BHT1
423HES
52BHET2
  • 优先级
IP^中断功能
0EX0
1T0
2EX1
3T1
4ES
5ET2
### 串口UART1
串行控制SCON98HSM0 SM1 SM2 REN TB8 RB8 TI RI
串行缓冲区SBUF99H

SM0-2

  • SM2:多机通信控制位
  • SM0、SM1:串口工作模式
SM0SM1说明波特率
00同步移位寄存器Fosc/12
0110bit帧、8bitdata定时器T1/T2
1011bit帧、8bit、1bit多机Fosc/32或Fosc/64
1111bit帧、8bit、1bit多机T1/T2
  • REN:接收使能
  • T、RB8:11bit帧作为第九位
  • TI、RI:发送接收中断标志,硬件置位,软件清零

实现方法

非中断方法
#include <reg52.h>
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()		//9600bps@12.000MHz

	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xD9;		//设置定时初始值
	TH1 = 0xD9;		//设置定时重载值
	ET1 = 0;		//禁止定时器%d中断
	TR1 = 1;		//定时器1开始计时

中断方法
#include <reg52.h>
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 */
	

重定向printf
#include <reg52.h>
#include <stdio.h>
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

电源和波特率PCON87HSMOD GF1 GF0 PD IDL
  • PD:掉电工作位
  • IDL:空闲工作位
  • GF:系统保留通用标志

PSW

  • CY:进位标志
  • AC:辅助进位标志
  • F0、F1:用户定义
  • RS1、0:工作寄存器
  • OV:溢出标志
  • P:奇偶标志:1–>奇

STC15F100系列

  • 在AT89C52基础增加
    • 【看门狗】
    • 【IAP】
    • 【可编程时钟输出】
    • 【P3 I/O控制寄存器】
  • 在AT89C52基础减去
    • 【定时器2(包括捕获功能)】
  • 修改定时器工作模式0为16位重装载

特殊寄存器映射

SFR符号字节(物理)地址位名称
D7D6D5D4D3D2D1D0
电源控制寄存器PCON87H--LVDF-GF1GF0PDIDL
辅助寄存器0AUXR8EHT0*12T1*12------
INT_CLKOINT_CLKO8FH-EX4EX3EX2--T1CLKOT0CLKO
CLK_DIVCLK_DIV97H-----CLKS2CLKS1CLKS0
P3M1P3M1B1H
P3M0P3M0B2H
IRC_CLKOIRC_CLKOBBH------IRCS1IRCS0
WDT_CONRWDT_CONRC1H
ISP/IAP Flash数据寄存器IAP_DATAC2H
ISP/IAP Flash地址高8bitIAP_ADDRHC3H
ISP/IAP Flash地址低8bitIAP_ADDRLC4H
ISP/IAP命令寄存器IAP_CMDC5H------MS1MS0
ISP/IAP命令触发器IAP_TRIGC6H
ISP/IAP控制寄存器IAP_CONTRC7HIAPENSWBSSWRSTCMD_FAIL-WT2WT1WT0

可编程时钟

系统时钟分频

CLK_DIVCLK_DIV97H-----CLKS2CLKS1CLKS0
  • 系统R/C震荡时钟分频如下表格
CLKS2CLKS1CLKS0分频系数
000/1
001/2
010/4
011/8
100/16
101/32
110/64
111/128

可编程时钟输出

  • 有三路可编程时钟输出
    • IRC_CLKO/P3.4
    • CLK_OUT0/P3.5
    • CLK_OUT1/P3.4
  • 寄存器
辅助寄存器0AUXR8EHT0*12T1*12------
INT_CLKOINT_CLKO8FH-EX4EX3EX2--T1CLKOT0CLKO
IRC_CLKOIRC_CLKOBBH------IRCS1IRCS0
  • AUXR
    • T*12:定时器速度是传统51的12倍**【计数时钟为系统(晶振)时钟】**
  • INT_CLKO
    【关闭定时器中断,定时器工作于方式0或者2】
    • T1CLKO:管脚P3.5允许时钟输出【定时器1】
    • T0CLKO:管脚P3.4允许时钟输出【定时器0】
    • 输出时钟频率= T溢出率 / 2
  • IRC_CLKO
    • IRCS:输出IRC时钟(见下表)
IRCS1IRCS0输出频率
00无时钟输出
01内部时钟输出不分频
102分频
114分频

P3口输出模式

  • P3M0、1:设定P3.5-3.0
P3M1[5:0]P3M0[5:0]I/O模式
00标准双向I/O
01推挽
10高阻
11开漏(外加上拉电阻)

IAP

  • 1KB/2KB数据EEPROM
  • 每个扇区512(0.5K)字节数据
ISP/IAP Flash数据寄存器IAP_DATAC2H
ISP/IAP Flash地址高8bitIAP_ADDRHC3H
ISP/IAP Flash地址低8bitIAP_ADDRLC4H
ISP/IAP命令寄存器IAP_CMDC5H------MS1MS0
ISP/IAP命令触发器IAP_TRIGC6H
ISP/IAP控制寄存器IAP_CONTRC7HIAPENSWBSSWRSTCMD_FAIL-WT2WT1WT0

IAP_CMD

  • 命令见下表
MS1MS0命令内容
00待机、无操作
01对数据Flash区读字节
10对数据Flash区进行字节编程
11对数据Flash扇区进行擦除

IAP_TRIG

  • 先写5AH再写A5H,触发命令

IAP_CONTR

ISP/IAP控制寄存器IAP_CONTRC7HIAPENSWBSSWRSTCMD_FAIL-WT2WT1WT0
  • IAPEN:IAP读写擦使能
  • SWBS:0:软件选择从用户应用程序启动;1:从系统ISP监控程序区启动
  • SWRST:1:软件复位
  • CMD_FAIL:触发命令失败标志位,软件清零
  • WT2-0:设置等待时间(见下表)
WT2WT1WT0ReadProgramSector Erase推荐系统时钟
0002个时钟55个时钟21012个时钟<=1MHz
0012个时钟110个时钟42024个时钟<=2MHz
0102个时钟165个时钟63036个时钟<=3MHz
0112个时钟330个时钟126072个时钟<=6MHz
1002个时钟660个时钟252114个时钟<=12MHz
1012个时钟1100个时钟420240个时钟<=20MHz
1102个时钟1320个时钟504288个时钟<=24MHz
1112个时钟1760个时钟672384个时钟<=30MHz

调用方法

  • 参考STCF100系列指南
#include <reg51.h>
#include <intrins.h>

typedef unsigned char Byte;
typedef unsigned int  Word;

/* 声明ISP功能寄存器地址 */
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   //Stand-By
#define CMD_READ    1   //Byte-READ
#define CMD_PROGRAM 2   //Byte-Program
#define CMD_ERASE   3   //Sector-Erase

/* 定义IAP等待时间 */
#define ENABLE_IAP  0x82    //if SYSCLK<20KHz

#define IAP_ADDRESS 0x0000

void Delay(Byte n);
void IapIdle();
Byte IapReadByte(Word addr);
void IapProgrameByte(Word addr, Byte dat);
void IapEraseSector(Word addr);

void\\ main()

    Word i;
    P1 = 0xFE;              //System Reset OK!
    Delay(10);
    IapEraseSector(IAP_ADDRESS);    //Erase current sector
    for(i=0;i<512;i++)
        if(IapReadByte(IAP_ADDRESS+i) != 0xFF)
        goto Error;
    
    P1 = 0xFC;              //Erase Successful
    Delay(10);
    for(i=0;i<512;i++)
    
        IapProgrameByte(IAP_ADDRESS+i,byByte(i));
    
    P1 = 0xF0;              //Verify Successful
    while(1);
    Error;
    P1 &= 0x7F;             //IAP Error
    while(1);


/* Software delay function */
void Delay(Byte n) 
    Word x;
    while (n--) 
        x = 0;
        while (++x);
    


/* Disable ISP/IAP/EEPROM function Make MCU in a safe state*/
void IapIdle()

    IAP_CONTR = 0;
    IAP_CMD = 0;
    IAP_TRIG = 0;
    IAP_ADDRH = 0x80;
    IAP_ADDRL =0x00;


/* Read one byte form ISP/IAP/EEPROM area
Input: addr
Output: Flash data*/
void IapReadByte(Word addr) 
    Byte dat;

    IAP_CONTR=ENABLE_IAP;
    IAP_CMD=CMD_READ;
    IAP_ADDRL=addr;
    IAP_ADDRH=addr>>8;
    IAP_TRIG=0x5A;
    IAP_TRIG=0xA5;
    _nop_();
    _nop_();
    _nop_();

    dat=IAP_DATA;
    IapIdle();

    return dat;


/* Program one byte to ISP/IAP/EEPROM area
Input: addr  dat
Output: -
*/
void IapProgrameByte(Word addr, Byte dat)

    IAP_CONTR=ENABLE_IAP;
    IAP_CMD=CMD_PROGRAM;
    IAP_ADDRL=addr;
    IAP_ADDRH=addr>>8;
    IAP_DATA=dat;
    IAP_TRIG=0x5A;
    IAP_TRIG=0xA5;
    _nop_();
    _nop_();
    _nop_();
    IapIdle();


/* Erase sector
Input: addr
Output; -
 */
void IapEraseSector(Word addr) 
    IAP_CONTR=ENABLE_IAP;
    IAP_CMD=CMD_ERASE;
    IAP_ADDRL=addr;
    IAP_ADDRH=addr>>8;
    IAP_TRIG=0x5A;
    IAP_TRIG=0xA5;
    _nop_();
    _nop_();
    _nop_();
    IapIdle();

看门狗

  • 本质为一个定时器,定时器溢出时将会产生复位。因此必须在定时器计数溢出前将看门狗计数清零,才能保证不产生看门狗复位【也叫做“喂狗”】。
WDT_CTRL
WDT_FLAG
\\
EN_WDT
CLR_WDT
IDLE_WDT
PS[2:0]
看门狗定时器
溢出标志
\\ 看门狗使能
看门狗定时器
清零
空闲模式下
看门狗是否工作
看门狗定时器
分频系数 以上是关于STC15系列学习的主要内容,如果未能解决你的问题,请参考以下文章

STC15比较器介绍以及比较器中断方式作为掉电检测示例程序

STC15系列PWM相关功能寄存器介绍

STC15系列PWM中断控制寄存器介绍以及PWM相关示例

STC15单片机PWM实际波形测量

STC15W408AS单片机3路PWM输出波形实测

12.STC15W408AS单片机比较器

(c)2006-2024 SYSTEM All Rights Reserved IT常识