外部中断、定时器、计数器,串口
串口相关(TMOD、SCON、PCON)寄存器的配置链接:https://blog.csdn.net/qq_36554582/article/details/82695138
学习如逆水行舟,不进则退,很久不用发现自己都已经将中断,定时器,计数器这部分忘完了,今天将它重新复习并整理,在便于以后学习的同时也警示自己。
同时感谢普中科技的C51单片机教程以及CSDN的一位作者:老马识途单片机,他的proteus教程写的很好,同时也对C语言进行了讲解,很适合初学者。
为了偷个懒,就发图了,自己画的,不好看,但是表述还是明确,如果不想看可以参考其他人写的。
为了避免多个页面,将中断函数都写在了一个页面,可直接在main()函数调用就行,
但是为了避免地址冲突,应单个运行,即仅在main()函数中取消一个子函数的注释。
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar counter=0; //计数器
sbit key0 = P3^5;
sbit key1 = P3^4;
sbit key2 = P3^3;
sbit key3 = P3^2;
sbit led = P1^0; //定义P10口是led
//------------------------------------------------------//外部中断0
//外部中断0初始化函数
void Int0init()
{ //设置INT0
EA = 1; //开总中断
EX0 = 1; //开(INT0)外部中断0的中断允许
IT0 = 1; //选择电平负跳变(下降沿)触发方式
}
//外部中断T0中断函数
void int0(void) interrupt 0 using 0
{
P1 = 0x0f; //点亮LED
}
//------------------------------------------------------//外部中断1
//外部中断1初始化函数
void Int1init(void)
{ //设置INT1
EA = 1; //开总中断
EX1 = 1; //开外部中断1
IT1 = 1; //选择电平负跳变触发方式,
}
//外部中断T1中断函数
void int1(void) interrupt 2 using 0
{
P1 = 0xf0; //点亮LED
}
//------------------------------------------------------//定时器T0
//定时器T0初始化
void Timer0init()
{ //设置T0
TMOD|=0X01; //选择为定时器0模式,工作方式1,仅用TR0打开启动
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1; //打开定时器0中断允许
EA=1; //打开总中断
TR0=1; //打开定时器
}
void Timer0() interrupt 1
{
static uint i;
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
i++;
if(i==1000)
{
i=0;
led=~led;
}
}
//------------------------------------------------------//计数器T0
//计数器T0外部计数方式统计计按键次数
void Counter0init()
{ //设置T0
TMOD=0X06; //使用定时器T0的计数工作方式,工作于工作方式2(8位自动重装)
TH0=256-1; //定时器T0的高8位赋值,计数值为1
TL0=256-1; //定时器T0的低8位赋值
ET0=1; //允许计数中断
EA=1; //开总中断
TR0=1; //启动计数方式工作
}
//T0计数中断服务函数
void Counter0(void) interrupt 1 using 0
{
counter++; //按键次数加1
P1=counter;
}
//------------------------------------------------------//定时器T1
//定时器T1初始化
void Timer1init()
{ //设置T1
TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
TH1=0XFC; //给定时器赋初值,定时1ms
TL1=0X18;
ET1=1;//打开定时器1中断允许
EA=1;//打开总中断
TR1=1;//打开定时器
}
void Timer1() interrupt 3
{
static uint i;
TH1=0XFC; //给定时器赋初值,定时1ms
TL1=0X18;
i++;
if(i==1000)
{
i=0;
led=~led;
}
}
//------------------------------------------------------//计数器T1
//计数器T1外部计数方式统计计按键次数
void Counter1init()
{ //设置T1
TMOD=0X60; //使用定时器T1的计数工作方式,工作于工作方式2(8位自动重装)
TH1=256-1; //定时器T1的高8位赋值,计数值为1
TL1=256-1; //定时器T1的低8位赋值
ET1=1; //允许计数中断
EA=1; //开总中断
TR1=1; //启动计数方式工作
}
//T1计数中断服务函数
void Counter1(void) interrupt 3 using 0
{
counter++; //按键次数加1
P1=counter;
}
/*******************************************************/
void main(void)
{
P1 = 0xff; //关闭LED
// Int0init();//外部中断0初始化
// Int1init();//外部中断1初始化
// Timer0init();//定时器T0初始化
// Counter0init();//计数器T0初始化
// Timer1init();//定时器T1初始化
// Counter1init();//计数器T1初始化
while(1);
}
Proteus仿真电路图
串口相关(TMOD、SCON、PCON)寄存器的配置链接:https://blog.csdn.net/qq_36554582/article/details/82695138
发现很多人都在用串口程序,为了方便,我就给大家贴一个完整的串口收发程序:
//这是一个完整的虚拟串口收发程序
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int//毫秒级延时函数
void delayms(uint ms)
{
uchar i;
while(ms--)
for(i = 0;i < 120;i++);
}
//字符发送函数
void putchar(uchar dat)
{
SBUF = dat; //将待发送的字符送入发送缓冲器
while(TI == 0); //等待发送完成
TI = 0; //发送中断标志请0
}
//字符串发送函数
void putstring(uchar *dat)
{
while(*dat != '\0') //判断字符串是否发送完毕
{
putchar(*dat); //发送单个字符
dat++; //字符地址加1,指向先下一个字符
delayms(5);
}
}
uchar receive(void)
{ //数据接收函数 -- 和本例中断函数功能相同
uchar dat;
while(RI==0); //数据没有接收完毕时等待接收
RI=0; //接收完毕时清零
dat=SBUF; //将接收缓冲器中的数据存入dat
putchar(dat);
return dat; //将接收到的数据返回
}
void Usartinit()
{
SCON = 0X50; //串口工作方式设置,串口方式1 ,允许接收
TMOD = 0X20; //定时器工作方式设置,T1工作于方式2
PCON = 0X00; //波特率倍增设置,不倍增
TH1 = 0XFD; //波特率设置
TL1 = 0XFD;
ES=1; //打开串口接收中断
EA = 1; //打开总中断
//TI = 0;
TR1 = 1; //开启定时器
}
void Usart() interrupt 4
{
uchar temp;
if(RI == 0) return; //如果没有接收中断标志,返回
ES = 0; //关闭串口中断
RI = 0; //清串行中断标志位
temp = SBUF; //接收缓冲器中的字符
putchar(temp); //将接收的字符发送出去
// P1=temp;
ES = 1; //开启串口中断
}
void main(void)
{
uchar c=0;
Usartinit();
delaym--s(200);
putstring("Receiving from 8051...\r\n");
//串口向终端发送字符串,结尾处回车换行
putstring("----------------------\r\n");
delayms(50);
while(1){
P1= receive();
}
}
虚拟串口仿真图:
TX-----------------发送
RX----------------接收