串口中断顺序及原理

五行外的小和尚 2013-12-10 11:16:17
#include <reg52.h>
#define uchar unsigned char ;
bit Flag; //串口接收到字符的标志
unsigned char UartChar;


/*--------------------------------------------------------------
函数声明
--------------------------------------------------------------*/
void InitUART(void);
void SendByte(unsigned char dat);
void SendStr(unsigned char *s);

/*--------------------------------------------------------------
主函数
--------------------------------------------------------------*/
void main (void)
{
//串口初始化
InitUART();

SendStr("\r\n\n SZ-51 UART test OK if you see these words!");
SendStr("\r\n ARM技术论坛 神舟51开发板 单片机串口收发测试");
SendStr("\r\n 神舟51开发板,中断方式接收,请输入字符:");

Flag = 0;
while (1)
{
if(Flag == 1)
{
Flag = 0;
SendByte(UartChar);
if(UartChar == '\r')
{
SendByte('\n');
}
}
}
}

/*--------------------------------------------------------------
串口初始化
--------------------------------------------------------------*/
void InitUART(void)
{

SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装
//TH1 = 0xF3; // 波特率4800、数据位8、停止位1。效验位无 (12M)
TH1 = 0xFD; // TH1: 重装值 9600 波特率 晶振 11.0592MHz
TR1 = 1; // TR1: timer 1 打开
EA = 1; //打开总中断
ES = 1; //打开串口中断
}

/*--------------------------------------------------------------
发送一个字节
--------------------------------------------------------------*/
void SendByte(unsigned char dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}

/*--------------------------------------------------------------
发送一个字符串
--------------------------------------------------------------*/
void SendStr(unsigned char *s)
{
//检测是否字符串末尾, '\0'表示字符串结束标志,
while(*s != '\0')
{
SendByte(*s);
s++;
}
}

/*--------------------------------------------------------------
串口中断程序
--------------------------------------------------------------*/
void UART_SER (void) interrupt 4 //串行中断服务程序
{
if(RI) //判断是接收中断产生
{
RI=0; //标志位清零
UartChar = SBUF; //读入缓冲区的值
Flag = 1; //把值输出到P1口,用于观察
}

if(TI) //如果是发送标志位,清零
{
//TI=0; //发送为查询方式
}
}

这是一个正常的串口收发函数,当我需要对中断接收的数据进行处理的时候,就会出现问题,所以我做了如下测试:
while (1)
{
if(Flag == 1)
{
Flag = 0;
SendByte('a');

}
}
这样的话,当我从串口精灵发送一串字符,发送的时候就会出发中断,所以我收到的‘a’的个数是我发送字符的个数
我现在又这么做,不发送字符了,我发送字符串
while (1)
{
if(Flag == 1)
{
Flag = 0;
SendStr(“abcdef”);

}
}
这样的话,当我从串口精灵发送字符串给单片机,如果说每个字符都产生中断,那么“abcdef”的个数,应该跟我的字符串长度一致,但是实际上不是这样的,可能因为以前指示发送一个字符,所以只用之行一个机器周期,所以是跟原始程序一样,不影响操作。输出是正确的,但是发送字符串的话,执行的机器周期多了,改变了原有的操作,所以发送“abcdef”的个数大致上跟字符串长度是这样的关系1-1,2-1,3-2,4-2..7-3...
如果是这样的话,那我接收数据就会不断的丢失。。。
...全文
778 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
island0209 2013-12-14
  • 打赏
  • 举报
回复
这要看的应用要求了,如果发送的数据长度可以无限制,那就需要流量控制,在接收缓存快要满的时候,让发送端等待一下再发送数据过来。 如果数据长度最大只有1K,那可以直接开一个接收缓存来完成收取的工作。另外收到‘a’,然后将其转换成16进制再发送,即发送“61”,那你的发送数据将是接收数据的2倍。
island0209 2013-12-10
  • 打赏
  • 举报
回复
中断接收中采用缓存方式: UartChar[RcLen++] = SBUF; //读入缓冲区的值 if(RcLen > MAXLEN) RcLen = 0; 然后设置一个定时器,超时后再置Flag = 1;
  • 打赏
  • 举报
回复
引用 1 楼 island0209 的回复:
中断接收中采用缓存方式: UartChar[RcLen++] = SBUF; //读入缓冲区的值 if(RcLen > MAXLEN) RcLen = 0; 然后设置一个定时器,超时后再置Flag = 1;
收字符,发送字符串,这个能不能实现?比如我收个‘a’,我要发送AT%IPSEND="61" 61就是a的16进制ascii 这样的话,我收的速度远比发的速度快,我会不会丢失数据?如果不丢失数据,我该怎么做?

27,382

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧