串口发送多字节数据
#include "STC15W4K.H" // 包含 "STC15W4K.H"寄存器定义头文件#defineTRUE 1
#defineFALSE 0
#define Buf1_Max 30
#defineuint8 unsigned char
static uint8 Buf1_Flag=FALSE; //串口1接收标识符
static uint8 xdata Rec_Buf1; //接收串口缓存数组
static uint8 i = 0; //串口接收数据个数变量
static uint8 Buf1_Length = 0; //串口接收数据长度
/*********************************************/
//描述:串口初始化函数,使用T1方式2自重载方式做波特率发生器
void UART_init(void)
{
// 下面代码设置定时器1
TMOD = 0x20; // 0010 0000 定时器1工作于方式2(8位自动重装方式)
TH1= 0xFA; // 波特率:9600 /22.1184MHZ
TL1= 0xFA; // 波特率:9600 /22.1184MHZ
TR1= 1;
// 下面代码设置定串口
AUXR = 0x00; // 很关键,使用定时器1作为波特率发生器,S1ST2=0
SCON = 0x50; // 01010 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接受)
// 下面代码设置中断
ES = 1; // 关键:开启了中断就必须编写相应的中断函数,哪怕是中断空函数,
// 但必须有,否则程序进入中断入口地址后(这里是0023H)不能跳出,必然出错
EA = 1;
}
/***************************************************************************
* 描述 : 串口发送数据函数
* 入参 : uint8 数据
* 返回值 : 无
**************************************************************************/
void SendDataByUart1(uint8 dat)
{
SBUF = dat; //写数据到UART数据寄存器
while(TI == 0); //在停止位没有发送时,TI为0即一直等待
TI = 0; //清除TI位(该位必须软件清零)
}
/***************************************************************************
* 描述 : 串口发送字符串函数
* 入参 : 字符串
* 返回值 : 无
**************************************************************************/
void SendStringByUart1(uint8 *s)
{
while(*s)
{
SendDataByUart1(*s++); //将字符串中的字符一个一个发送
}
}
功能描述:清除串口缓存内容函数
入口参数:无
返回值:无
******************************************************************************/
void CLR_Buf1(void)
{
uint8 k;
for(k=0;k<Buf1_Max;k++) //将串口1缓存数组的值都清为零
{
Rec_Buf1 = 0;
}
i = 0; //清零串口1接收数据个数变量
}
/***************************************************************************
* 描述 : 串口1中断服务函数
* 入参 : 无
* 返回值 : 无
**************************************************************************/
void Uart1() interrupt 4 using 1
{
uint8 temp;
ES = 0; // 串口1中断关闭
if (RI) //串行接收到停止位的中间时刻时,该位置1
{
RI = 0; //清除RI位 (该位必须软件清零)
temp = SBUF; //接收到的数赋值给临时变量
if(temp !='\n') //没有接收到换行符
{
Rec_Buf1 = temp; //接收到的数存到接收数组中
i++; //串口1接收数据个数变量累加
}
else //接收到结束符
{
Buf1_Length = i; //接收数据长度赋值
i = 0; //清零串口1接收数据个数变量
Buf1_Flag=TRUE; //接收完数据,接收标识符有效
}
}
ES =1; // 串口1中断打开
}
/**************************************************************************************
* 描述 : 串口接收到字符串后发送出去
* 入参 : 无
* 返回值 : 无
**************************************************************************************/
void UART1_2_Tx_Puts(void)
{
if(Buf1_Flag) //串口接收一组字符串完成
{
ES = 0; //串口中断关闭
SendStringByUart1(Rec_Buf1); //发送字符
SendDataByUart1(0x0D); //发送换行符
SendDataByUart1(0x0A); //发送换行符
ES = 1; //串口中断打开
CLR_Buf1(); //清除串口缓存
Buf1_Flag=FALSE; //清除接收标识符
}
}
/***************************************************************************
* 描述 : 主函数
* 入参 : 无
* 返回值 : 无
**************************************************************************/
int main()
{
P3M1 &= 0xFE; P3M0 &= 0xFE; //设置P3.0为准双向口
P3M1 &= 0xFD; P3M0 |= 0x02; //设置P3.1为推挽输出
P1M1 &= 0xFE; P1M0 &= 0xFE; //设置P1.0为准双向口
P1M1 &= 0xFD; P1M0 |= 0x02; //设置P1.1为推挽输出
UART_init(); // 串口初始化
EA = 1; //总中断打开
CLR_Buf1(); //清除串口1缓存
while(1)
{
UART1_2_Tx_Puts(); //UART接收到字符串后发送出去
}
}
为什么不把发送函数也在中断中执行?
这是个问题,我也不知道,于是搜索了一下
将接收和发送都写在中断函数中可能会带来以下问题:(1) 中断响应时间过长
[*]中断函数的执行时间应尽可能短,以确保系统能够及时响应其他中断或任务。
[*]如果接收和发送都写在中断函数中,中断函数的执行时间会变长,可能导致:
[*]丢失其他中断(如定时器中断、外部中断等)。
[*]降低系统的实时性。
(2) 数据竞争问题
[*]如果接收和发送共享同一个缓冲区或变量,可能会导致数据竞争(Data Race)。
[*]例如,接收中断正在写入缓冲区,而发送中断正在读取缓冲区,这可能会导致数据不一致或错误。
(3) 发送阻塞问题
[*]如果发送数据依赖于接收数据(例如接收到数据后立即发送),可能会导致发送阻塞。
[*]例如,发送数据时如果缓冲区未准备好,可能会占用中断时间,影响接收数据的及时处理。
(4) 代码复杂度增加
[*]将接收和发送逻辑都放在中断函数中,会增加代码的复杂性和维护难度。
[*]中断函数应尽量保持简单,复杂的逻辑可以放在主循环中处理
页:
[1]