问题描述:
原本单独测试没问题的定时器程序,但在加上串口程序后出现了问题,发现定时器貌似没有在正常工作......
问题发现:
程序如下:
该程序主要想实现的功能是:
1.串口在初始化时发送"welcome\r\n"
2.后续定时器定时每1200ms让串口发送一次"666\r\n"
但最终这段代码只实现了功能1,并没有实现功能2
#include "stc15f2k60s2.h"
#include "stdio.h"
//蜂鸣器继电器引脚:
sbit buzz=P0^6;
sbit RELAY=P0^4;
typedef unsigned char u8;
typedef unsigned int u16;
typedef int u32;
bit print_flag;
u16 print_cnt;
void task_clock(); //模块时序安排
void inint_all(); //初始化所有模块
void inint_port(u8 i); //初始化74hc573芯片
void Timer0Init(void); //1毫秒@12.000MHz
void UartInit(void); //9600bps@11.0592MHz
void handle_printf_data(); //串口测试打印数据
void main()
{
inint_all();
while(1)
{
if(print_flag==1)
{
print_flag=0;
printf("666\r\n");
}
}
}
void inint_all() //初始化所有模块
{
inint_port(5); //关闭外设
buzz=0;
inint_port(5); //关闭外设
RELAY=0;
inint_port(4);
P0=0XFF;
Timer0Init();
UartInit();
printf("welcome\r\n");
}
void inint_port(u8 i) //初始化74hc573芯片
{
switch(i)
{
case 4:P2=(P2&0X1F)|0X80;break; //LED
case 5:P2=(P2&0X1F)|0XA0;break; //BUZZ RELAY
case 6:P2=(P2&0X1F)|0XC0;break; //数码管位选
case 7:P2=(P2&0X1F)|0XE0;break; //数码管段选
}
}
void Timer0Init(void)
{
AUXR &= 0x7F;TMOD &= 0xF0;TL0 = 0x18;TH0 = 0xFC;
TF0 = 0;TR0 = 1;EA=1;ET0=1;
}
void timer0_serv() interrupt 1
{
if(++print_cnt==1200)//1200ms发送一次串口
{print_cnt=0;print_flag=1;}
}
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xE0; //设置定时初始值
T2H = 0xFE; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
REN=1;
ES=1;
EA=1;
}
void Uart_1_serv() interrupt 4
{if(RI){RI=0;}}
void send_date(unsigned char date) {SBUF = date; while(!TI); TI = 0;}
char putchar (char ch){send_date(ch);return ch;}
问题解决:
在分析改正下,发现原来是串口中断服务函数没有编写导致了这个问题!
在文件中加上这个串口1中断服务函数就解决了:
void Uart_1_serv() interrupt 4
{if(RI){RI=0;}}
上位机测试也没问题了:
问题原理:
那为何会出现这样的BUG呢?
在单片机中,串口和定时器都可以使用中断,而中断服务函数是用来响应中断请求的,如果你没有定义好对应的中断服务函数,在产生中断请求时,系统就找不到对应的中断服务函数,无法处理中断请求。
在这种情况下,如果串口接收到数据时,因为没有定义串口接收中断服务函数,数据就不能被及时处理,从而导致数据丢失。同时,如果你没有定义定时器中断服务函数,当定时器计数到指定时间时,系统会无法响应中断请求,导致定时器无法正常工作。因此,在单片机中,使用中断来处理串口和定时器的数据会更加高效和稳定。