找回密码
 立即注册
查看: 250|回复: 0

串口发送多字节数据

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:119
  • 最近打卡:2025-06-18 14:58:09
已绑定手机

12

主题

57

回帖

419

积分

中级会员

积分
419
发表于 2025-2-25 11:06:34 | 显示全部楼层 |阅读模式
#include "STC15W4K.H"          // 包含 "STC15W4K.H"寄存器定义头文件
#define  TRUE    1
#define  FALSE   0
#define Buf1_Max 30

#define  uint8    unsigned char

static uint8 Buf1_Flag=FALSE;     //串口1接收标识符
static uint8 xdata Rec_Buf1[Buf1_Max];     //接收串口缓存数组
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[k] = 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) 代码复杂度增加
  • 将接收和发送逻辑都放在中断函数中,会增加代码的复杂性和维护难度。
  • 中断函数应尽量保持简单,复杂的逻辑可以放在主循环中处理



回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-18 23:03 , Processed in 0.139967 second(s), 46 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表