标题:
51单片机中断、串口通信综合程序
[打印本页]
作者:
境s。
时间:
2019-8-19 17:02
标题:
51单片机中断、串口通信综合程序
正在初学51的中断,定时器,串口等等,遇到很多瓶颈比如串口怎么发送变量的数值啦(加一个0x30就好),分享这个程序给初学者们啦
功能:
1. 开机以后,LED0和LED1实现0.5秒间隔闪烁2次,蜂鸣器同时鸣叫2次。
2. 之后,串口等待接收到一个字符'R',开始进入主循环体。
3. 主循环体中,LED0和LED1实现1秒间隔闪烁。
4. 串口接收到字符'D',回复LED当前状态和系统当前处于运行还是暂停状态,如果运行状态,收到字符'R',如果暂停状态,收到字符'P'。
5. 串口接收到字符'T',回复主循环体开始运行的时间和系统当前处于运行还是暂停状态,时间单位为秒,最大计数值65535,以每一位的ASCII码字符发送,最后加换行符。
6. 串口接收到其他字符,回复字符'W',且蜂鸣器高频率鸣叫2次。
7. 主循环体运行每分钟,蜂鸣器低频率鸣叫1次。
8. 开启INT0中断,按下S_INT0,可以暂停目前的程序运行,再次按下,可以继续运行,之前的所有都保持继续运行的状态,计数值也继续累加。暂停状态下, 依然可以响应串口的'D'和'T'的应答回复,具体暂停还是运行状态的解释,详见第4条要求。
9. 所有定时, 用T0方式1中断实现。
10. 串行口配置为方式1,4800波特率,中断接收,查询发送。
PS:定时器的初值为了方便是用晶振12HZ算的哦,想要精确延时的朋友记得换成11.0592算一下啦
用的STC89C52REC的迷你单片机,原理图附在压缩包里啦
单片机源程序如下:
#include <reg52.h>
#include"main.h"
void main()
{
init();
for(i=0; i<2; i++)
{
LED0 = 0;
LED1 = 0;
beep = 0;
delay(25);
LED0 = ~LED0;
LED1 = ~LED1;
beep = 1;
delay(25);
}
while(1)
{
while(g_b_enter_flag)
{
if(LED0 == LED1)
{
LED0 = 0;
LED1 = 1;
delay(50);
}
LED0 = ~LED0;
LED1 = ~LED1;
delay(50);
}//end of while(g_b_enter_flag)
while(!g_b_enter_flag)
{
;
}
}//end of while(1)
}
//按键中断子程序
void int0() interrupt 0
{
g_b_enter_flag = ~g_b_enter_flag;//暂停和继续的切换
}
//定时器中断子程序
void Timer0() interrupt 1 using 1
{
TH0 = 0xB1; //重新加载初值
TL0 = 0xE0;
g_i_cnt++;
if(g_b_enter_flag)
{
g_i_20ms_time++; //记录主循环运行时间
}
if(g_i_20ms_time>50) //主程序运行1s
{
g_i_1s_time++;
g_i_totaltime++;
g_i_20ms_time = 0;
}
if(g_i_1s_time>60) //运行一分钟
{
beep = 0;
cdelay(200);
beep = 1;
g_i_1s_time=0;
}
if(g_i_1s_time>65535)//最大计时值655353
{
g_i_1s_time = 0;
}
}
//精确延时
void delay(unsigned int z)
{
g_i_cnt=0;
while(g_i_cnt<z)
{
;
}
g_i_cnt=0;
}
//发送一个字符
void send(unsigned char byte)
{
SBUF=byte;
while(!TI);
TI=0;
}
//不精确延时
void cdelay(unsigned int k)
{
unsigned int x,y;
for(x=0; x<k; x++)
{
for(y=0;y<600;y++);
}
}
//外部中断和定时器的初始化
void init()
{
i=0;
g_b_R_flag=0;//判断是否是第一次发送R
g_b_enter_flag=0; //判断是否进入主循环,0为否,1为是
g_i_cnt=0; //精确延时用
g_i_20ms_time=0; //一个等于20ms
g_i_1s_time=0; //一个等于1s
g_i_totaltime=0; //主程序运行总时间
EX0 = 1;//开外部中断0
IT0 = 0;//外部中断0低电平触发
ET0 = 1;//打开定时器0中断
TMOD |= 0X01; //定时器工作模式1,16位定时模式
TR0 = 1;//启动定时器0
TH0 = 0xB1;
TL0 = 0xE0; //定时20ms
ES = 1; //打开串口中断
SCON = 0x50;//配置串口为模式 1
REN = 1;//串口允许接收
TMOD |= 0x20;//定时器1,工作模式2 8位自动重装
TH1 = 0xFA; //波特率4800
TL1 = 0xFA;
ET1 = 0; //禁止 T1 中断
TR1 = 1;//启动定时器1
EA = 1; //打开总中断
}
//UART中断服务函数
void InterruptUART() interrupt 4 using 1
{
if(RI)//判断接收是否完成
{
RI = 0;//手动清零接收中断标志位
if((SBUF==0x52)&(g_b_R_flag==1))
{
send('W');
beep=0;
cdelay(60);
beep=1;
cdelay(60);
beep=0;
cdelay(60);
beep=1;
cdelay(60);
}
if(SBUF==0x52) //接受字母为R,开始进入主循环体
{
g_b_enter_flag = 1;
g_b_R_flag=1;
}
else if(SBUF==0x44)//接收字母为D,发送LED状态
{
if(g_b_enter_flag)
{
send('R');
send('\n');
if(LED0==1&&LED1==0)
{
send('C');
send('O');
send('\n');
}
else
{
send('O');
send('C');
send('\n');
}
}
else
{
send('P');
send('\n');
}
}//end of else if(SBUF==0x44)
else if(SBUF==0x54)//接受字母T发送系统状态和运行时间
{
if(g_b_enter_flag)
{
send('R');
send('\n');
}
else
{
send('P');
send('\n');
}
num1 = 0x30+g_i_totaltime/10000;
SBUF = num1;
while(!TI);
TI = 0;
num2 = 0x30+g_i_totaltime%10000/1000;
SBUF = num2;
while(!TI);
TI = 0;
num3 = 0x30+g_i_totaltime%1000/100;
SBUF = num3;
while(!TI);
TI = 0;
num4 = 0x30+g_i_totaltime%100/10;
SBUF = num4;
while(!TI);
TI = 0;
num5 = 0x30+g_i_totaltime%10;
SBUF = num5;
while(!TI);
TI = 0;
send('\n');
} //end of else if(SBUF==0x54)
else
{
send('W');
beep=0;
cdelay(60);
beep=1;
cdelay(60);
beep=0;
cdelay(60);
beep=1;
cdelay(60);
}
if(TI)//判断是否发送完成
{
TI = 0;//清零发送完成标志位
}
}//end of if(RI)
}
复制代码
所有资料51hei提供下载:
totaltask.rar
(83.75 KB, 下载次数: 34)
2019-8-19 17:02 上传
点击文件名下载附件
源程序+原理图
下载积分: 黑币 -5
作者:
Peilin1024
时间:
2019-12-1 17:12
我也是初学者,感谢分享
作者:
liang1889
时间:
2020-1-6 14:49
非常不错
作者:
wang_00008
时间:
2020-3-2 00:32
非常不错
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1