单片机交流
登录
直播中
蒲泛粟
7年用户
939经验值
私信
关注
[问答]
初识STC89C52RC单片机
开启该帖子的消息推送
单片机
STC89C52RC
定时器
怎样去使用STC89C52RC
单片机
的定时器呢?
怎样去使用STC89C52RC单片机的串口呢?
回帖
(1)
杨靖
2021-10-20 17:00:10
该模板适用于51单片机入门,比较易于理解,包含定时器和串口的操作。
可以在定时器T0中断服务函数和主循环中实现主要功能,在UART中断服务函数(T1定时器)中实现简单的串口通信接收命令的功能。
注:本模板STC89C52RC单片机使用11.0592MHz的晶振,若使用12MHz晶振可修改定时器相关位置
STC89C52RC原理图
模板及分析
1.主要结构
#include 《reg52.h》
unsigned char T0RH = 0; //T0重载值高字节
unsigned char T0RL = 0; //T0重载值低字节
unsigned char RxdByte = 0; //串口接收到的字节
void ConfigTimer0(unsigned int ms);
void ConfigUART(unsigned int baud);
void main()
{
EA = 1; //使能总中断
ConfigTimer0(1); //配置为1ms
ConfigUART(9600); //配置波特率为9600
while(1)
{
}
}
/*配置并启动T0,ms-T0定时时间*/
void ConfigTimer0(unsigned int ms)
{
}
/*串口配置函数,baud-通信波特率*/
void ConfigUART(unsigned int baud)
{
}
/*T0中断服务函数*/
void InterruptTimer0() interrupt 1
{
}
/*UART中断服务函数*/
void InterruptUART() interrupt 4
{
}
2.配置及实现T0中断
先写配置函数ConfigTimer0。要实现每隔一定时间单片机进入T0中断服务函数执行它的功能,首先要确定多久进入一次中断。
我们输入这个函数的参数是ms,需要在函数中转换成单片机实际的工作方式来计算。
STC89C52RC的1个机器周期等于12个时钟周期。单片机的工作周期要用机器周期计算,每过一个单片机的工作周期,定时器的值就从初值向上增加1,在16位定时器模式下直到65536溢出,触发相应中断,进入相应中断服务函数。
以11.0592MHz的晶振为例,先将时钟周期转换为机器周期,ms转换为s计算出所需的计数值。由于定时器是向上计数溢出的,所以要用溢出值减去计数值得出重载值。(假如定时器是向下计数的就不用这步)
unsigned long tmp;
tmp = 11059200 / 12; //计算所需的计数值
tmp = (tmp * ms) / 1000;
tmp = 65536 - tmp; //计算定时器重载值
T0是个16位定时器,分为TH0高8位和TL0低8位,对应重载值也要分开计算。
unsigned char T0RH = 0; //T0重载值高字节
unsigned char T0RL = 0; //T0重载值低字节
T0RH = (unsigned char)(tmp》》8); //定时器重载值拆分为高低字节
T0RL = tmp;
TCON:
TMOD:
IE:
接下来配置TCON、TMOD和IE这些寄存器。
先把工作模式寄存器TMOD配置为16位定时器模式,然后给TH0、TL0两个8位寄存器赋初值,再配置可位寻址的中断允许寄存器IE,即ET0 = 1,最后配置 定时器/控制器控制寄存器TCON:TR0 = 1 启动T0定时器。
TMOD &= 0xF0; //清零T0控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = T0RH; //加载T0重载值
TL0 = T0RL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
最后在T0中断服务函数InterruptTimer0中每次溢出进入中断的时候重新初始化定时器的值,执行功能。
TH0 = T0RH; //重载初值
TL0 = T0RL;
。..
3.配置及实现串口中断
串口中断和上面的中断又有所不同。首先,它只能由T1或T2定时器作为“波特率发生器”,T0不可以;其次,定时器的作用是定时检测数据,而不是定时进入中断;再就是串口一般由P3.0(RXD)和P3.1(TXD)担当,因为关于具体通信协议已经由单片机的硬件电路实现了,我们只要懂得如何配置寄存器就可以。
(STC89C52RC只有一个串口,假如要这个单片机既使用串口接收传感器的一些数据,又要把数据通过串口通信传回上位机,一个串口就不够用了,可以用IO口模拟串口,自己写一下串口通信协议的实现,最方便的是用2个串口的单片机)
SCON:(串口控制寄存器)
先配置串口为模式1(一字节接收8位),然后配置定时器T1为8位重装载模式,即TL1每次达到256溢出后装载TH1的值。,默认 电源控制器及波特率选择寄存器 PCON = 1, 一个位检测32次,同理,用256减得到T1重载值,也就是控制溢出的时间为约定好波特率时(9600),一个位占用时间的
。
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值
TL1 = TH1; //初始等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
SBUF为串口数据缓冲寄存器,大小为8字节。
当接收一字节数据结束时,RI自动置1,要在中断服务函数中手动归0;TI 同理。然后接收数据,传递执行功能的信息。
/*UART中断服务函数*/
void InterruptUART() interrupt 4
{
if (RI) //接收到字节
{
RI = 0; //手动清零接收中断标志位
RxdByte = SBUF; //接收到的数据(8位)保留在接收字节变量中
SBUF = RxdByte; //接收到的数据直接发回,用以提示输入信息是否被正确接收
。..
}
if (TI) //字节发送完毕
{
TI = 0; //手动清零发送中断标志位
}
}
完整模板代码
/***********************************************************************
* 中断的4个寄存器(都为8位)
* 中断允许 中断优先级 定时器/计数器工作模式 定时器/计数器控制
* IE IP TMOD TCON
* 位寻址 固定 不可位寻址 位寻址
* EA|ET1|ES1 ---- T1|T0 TR0|TR1
* 串口控制寄存器 SCON 不可位寻址 置0x50
* 中断优先级(0~5):INT0 T0 INT1 T1 TX/RX T2
*
* 具体的可转入reg52.h头文件中查看
************************************************************************/
#include 《reg52.h》
/******************************定义引脚*********************************/
/******************************定义全局变量*****************************/
/*************************定时器********************************/
unsigned char T0RH = 0; //T0重载值高字节
unsigned char T0RL = 0; //T0重载值低字节
/************************串口通信*******************************/
unsigned char RxdByte = 0; //串口接收到的字节
/****************************函数声明***********************************/
void ConfigTimer0(unsigned int ms);
void ConfigUART(unsigned int baud);
/*主函数*/
void main()
{
EA = 1; //使能总中断
ConfigTimer0(1); //配置为1ms
ConfigUART(9600); //配置波特率为9600
while(1)
{
}
}
/*配置并启动T0,ms-T0定时时间*/
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp;
tmp = 11059200 / 12; //计算所需的计数值(ms换算成s)
tmp = (tmp * ms) / 1000;
tmp = 65536 - tmp; //计算定时器重载值
//tmp = tmp + 13; //补偿中断响应延时造成的误差
T0RH = (unsigned char)(tmp》》8); //定时器重载值拆分为高低字节
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零T0控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = T0RH; //加载T0重载值
TL0 = T0RL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
/*串口配置函数,baud-通信波特率*/
void ConfigUART(unsigned int baud)
{
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值(32:PCON配置为1,一个数据监测32次,保证准确性)
TL1 = TH1; //初始等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
}
/******************************自定义函数*******************************/
/******************************自定义函数END****************************/
/*T0中断服务函数*/
void InterruptTimer0() interrupt 1
{
TH0 = T0RH; //重载初值
TL0 = T0RL;
/**************************定时器0功能实现***************************/
/*******************************END**********************************/
}
/*UART中断服务函数*/
void InterruptUART() interrupt 4
{
if (RI) //接收到字节
{
RI = 0; //手动清零接收中断标志位
RxdByte = SBUF; //接收到的数据(8位)保留在接收字节变量中
SBUF = RxdByte; //接收到的数据直接发回
//用以提示输入信息是否被正确接收
/**************************串口通信功能实现***************************/
/********************************END**********************************/
}
if (TI) //字节发送完毕
{
TI = 0; //手动清零发送中断标志位
}
}
该模板适用于51单片机入门,比较易于理解,包含定时器和串口的操作。
可以在定时器T0中断服务函数和主循环中实现主要功能,在UART中断服务函数(T1定时器)中实现简单的串口通信接收命令的功能。
注:本模板STC89C52RC单片机使用11.0592MHz的晶振,若使用12MHz晶振可修改定时器相关位置
STC89C52RC原理图
模板及分析
1.主要结构
#include 《reg52.h》
unsigned char T0RH = 0; //T0重载值高字节
unsigned char T0RL = 0; //T0重载值低字节
unsigned char RxdByte = 0; //串口接收到的字节
void ConfigTimer0(unsigned int ms);
void ConfigUART(unsigned int baud);
void main()
{
EA = 1; //使能总中断
ConfigTimer0(1); //配置为1ms
ConfigUART(9600); //配置波特率为9600
while(1)
{
}
}
/*配置并启动T0,ms-T0定时时间*/
void ConfigTimer0(unsigned int ms)
{
}
/*串口配置函数,baud-通信波特率*/
void ConfigUART(unsigned int baud)
{
}
/*T0中断服务函数*/
void InterruptTimer0() interrupt 1
{
}
/*UART中断服务函数*/
void InterruptUART() interrupt 4
{
}
2.配置及实现T0中断
先写配置函数ConfigTimer0。要实现每隔一定时间单片机进入T0中断服务函数执行它的功能,首先要确定多久进入一次中断。
我们输入这个函数的参数是ms,需要在函数中转换成单片机实际的工作方式来计算。
STC89C52RC的1个机器周期等于12个时钟周期。单片机的工作周期要用机器周期计算,每过一个单片机的工作周期,定时器的值就从初值向上增加1,在16位定时器模式下直到65536溢出,触发相应中断,进入相应中断服务函数。
以11.0592MHz的晶振为例,先将时钟周期转换为机器周期,ms转换为s计算出所需的计数值。由于定时器是向上计数溢出的,所以要用溢出值减去计数值得出重载值。(假如定时器是向下计数的就不用这步)
unsigned long tmp;
tmp = 11059200 / 12; //计算所需的计数值
tmp = (tmp * ms) / 1000;
tmp = 65536 - tmp; //计算定时器重载值
T0是个16位定时器,分为TH0高8位和TL0低8位,对应重载值也要分开计算。
unsigned char T0RH = 0; //T0重载值高字节
unsigned char T0RL = 0; //T0重载值低字节
T0RH = (unsigned char)(tmp》》8); //定时器重载值拆分为高低字节
T0RL = tmp;
TCON:
TMOD:
IE:
接下来配置TCON、TMOD和IE这些寄存器。
先把工作模式寄存器TMOD配置为16位定时器模式,然后给TH0、TL0两个8位寄存器赋初值,再配置可位寻址的中断允许寄存器IE,即ET0 = 1,最后配置 定时器/控制器控制寄存器TCON:TR0 = 1 启动T0定时器。
TMOD &= 0xF0; //清零T0控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = T0RH; //加载T0重载值
TL0 = T0RL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
最后在T0中断服务函数InterruptTimer0中每次溢出进入中断的时候重新初始化定时器的值,执行功能。
TH0 = T0RH; //重载初值
TL0 = T0RL;
。..
3.配置及实现串口中断
串口中断和上面的中断又有所不同。首先,它只能由T1或T2定时器作为“波特率发生器”,T0不可以;其次,定时器的作用是定时检测数据,而不是定时进入中断;再就是串口一般由P3.0(RXD)和P3.1(TXD)担当,因为关于具体通信协议已经由单片机的硬件电路实现了,我们只要懂得如何配置寄存器就可以。
(STC89C52RC只有一个串口,假如要这个单片机既使用串口接收传感器的一些数据,又要把数据通过串口通信传回上位机,一个串口就不够用了,可以用IO口模拟串口,自己写一下串口通信协议的实现,最方便的是用2个串口的单片机)
SCON:(串口控制寄存器)
先配置串口为模式1(一字节接收8位),然后配置定时器T1为8位重装载模式,即TL1每次达到256溢出后装载TH1的值。,默认 电源控制器及波特率选择寄存器 PCON = 1, 一个位检测32次,同理,用256减得到T1重载值,也就是控制溢出的时间为约定好波特率时(9600),一个位占用时间的
。
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值
TL1 = TH1; //初始等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
SBUF为串口数据缓冲寄存器,大小为8字节。
当接收一字节数据结束时,RI自动置1,要在中断服务函数中手动归0;TI 同理。然后接收数据,传递执行功能的信息。
/*UART中断服务函数*/
void InterruptUART() interrupt 4
{
if (RI) //接收到字节
{
RI = 0; //手动清零接收中断标志位
RxdByte = SBUF; //接收到的数据(8位)保留在接收字节变量中
SBUF = RxdByte; //接收到的数据直接发回,用以提示输入信息是否被正确接收
。..
}
if (TI) //字节发送完毕
{
TI = 0; //手动清零发送中断标志位
}
}
完整模板代码
/***********************************************************************
* 中断的4个寄存器(都为8位)
* 中断允许 中断优先级 定时器/计数器工作模式 定时器/计数器控制
* IE IP TMOD TCON
* 位寻址 固定 不可位寻址 位寻址
* EA|ET1|ES1 ---- T1|T0 TR0|TR1
* 串口控制寄存器 SCON 不可位寻址 置0x50
* 中断优先级(0~5):INT0 T0 INT1 T1 TX/RX T2
*
* 具体的可转入reg52.h头文件中查看
************************************************************************/
#include 《reg52.h》
/******************************定义引脚*********************************/
/******************************定义全局变量*****************************/
/*************************定时器********************************/
unsigned char T0RH = 0; //T0重载值高字节
unsigned char T0RL = 0; //T0重载值低字节
/************************串口通信*******************************/
unsigned char RxdByte = 0; //串口接收到的字节
/****************************函数声明***********************************/
void ConfigTimer0(unsigned int ms);
void ConfigUART(unsigned int baud);
/*主函数*/
void main()
{
EA = 1; //使能总中断
ConfigTimer0(1); //配置为1ms
ConfigUART(9600); //配置波特率为9600
while(1)
{
}
}
/*配置并启动T0,ms-T0定时时间*/
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp;
tmp = 11059200 / 12; //计算所需的计数值(ms换算成s)
tmp = (tmp * ms) / 1000;
tmp = 65536 - tmp; //计算定时器重载值
//tmp = tmp + 13; //补偿中断响应延时造成的误差
T0RH = (unsigned char)(tmp》》8); //定时器重载值拆分为高低字节
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零T0控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = T0RH; //加载T0重载值
TL0 = T0RL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
/*串口配置函数,baud-通信波特率*/
void ConfigUART(unsigned int baud)
{
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值(32:PCON配置为1,一个数据监测32次,保证准确性)
TL1 = TH1; //初始等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
}
/******************************自定义函数*******************************/
/******************************自定义函数END****************************/
/*T0中断服务函数*/
void InterruptTimer0() interrupt 1
{
TH0 = T0RH; //重载初值
TL0 = T0RL;
/**************************定时器0功能实现***************************/
/*******************************END**********************************/
}
/*UART中断服务函数*/
void InterruptUART() interrupt 4
{
if (RI) //接收到字节
{
RI = 0; //手动清零接收中断标志位
RxdByte = SBUF; //接收到的数据(8位)保留在接收字节变量中
SBUF = RxdByte; //接收到的数据直接发回
//用以提示输入信息是否被正确接收
/**************************串口通信功能实现***************************/
/********************************END**********************************/
}
if (TI) //字节发送完毕
{
TI = 0; //手动清零发送中断标志位
}
}
举报
更多回帖
rotate(-90deg);
回复
相关问答
单片机
STC89C52RC
定时器
stc89c52rc
型号烧不进程序
2020-03-12
4478
请问3.3V电源可以用于
STC89LE52RC
单片机
吗?
2023-10-08
542
怎样去设计基于
STC89C52RC
单片机
的多功能智能小车
2021-10-14
1597
如何利用
STC89C52RC
单片机
进行编程?
2022-02-15
1543
STC89C52RC
单片机
的主要结构是怎样构成的?
2021-07-14
1978
如何利用
STC89c52rc
单片机
实现红外循迹小车的设计?
2021-10-20
1720
如何用
STC89C52RC
单片机
控制SIM300发短信,求源码!谢谢!!!
2014-05-02
3160
如何解决
STC89C52
更换为
STC89C52RC
芯片出现无法烧录的问题?
2021-10-26
2886
STC89C52RC
普中开发板能给AT
89
S5224PU
单片机
下载程序吗?
2014-08-15
11400
如何去实现一种基于
STC89C52RC
的电子秒表设计呢
2021-11-10
1315
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分