2301_77450812 2023-09-08 22:12 采纳率: 75%
浏览 9
已结题

51单片机利用串口hex模式发送两个位数,hex模式返回他们的和,但是第一次发送数据都会出错,后面就再发送正确,能否帮我找一下问题出在哪

img

img


#include <REGX52.H>


void UART_Init(void)        //串口初始化函数  
                            //4800bps@12.000MHz
{
    PCON |= 0x80;        //使能波特率倍速位SMOD
    SCON = 0x50;        //8位数据,可变波特率,使能接收
    TMOD &= 0x0F;        //设置定时器模式
    TMOD |= 0x20;        //设置定时器模式
    TL1 = 0xF3;            //设置定时初始值
    TH1 = 0xF3;            //设置定时重载值
    ET1 = 0;            //禁止定时器中断
    TR1 = 1;            //定时器1开始计时
    EA=1;                //串口中断
    ES=1;
}

void UART_SendByte(unsigned char Byte)       //串口发送一个字节数据
{
    SBUF=Byte;
    while(TI==0);     //发送控制器发送后变1,需软件重新赋值0
    TI=0;
}        


unsigned char data1,data2,count=0,sum;

void main()
{
    UART_Init();

    while(1)
    {
        
    }
}

void UART_Routine() interrupt 4    
{
    if(RI==1)                      //返回电脑输入第一个数据函数,十六进制
    {
        RI=0;
        if(count==0)
        {
            data1=SBUF;
            count=1;
        }
        else if(count==1)
        {
            data2=SBUF;
            count=2;
        }
    }
    if(count==2)
    {
        sum=data1+data2;
        if(sum<=9)                        //hex模式相当于发送ASCII值,hex模式接收该ASCII对应的十六进制数,当sum<10时,sum不变例如ASCII=9对应0x09
            UART_SendByte(sum);
        else
        {
               sum=sum+6;                    //hex模式相当于发送ASCII值,hex模式接收该ASCII对应的十六进制数,当sum>10时,sum+6例如ASCII=16对应0x10
               UART_SendByte(sum);
        }
        count=0;
    }
        
}
    
  • 写回答

2条回答 默认 最新

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2023-09-08 22:18
    关注

    该回答引用ChatGPT-3.5,仅为您提供参考,不保证完全正确
    根据你提供的代码,可能存在一个问题是在程序启动时,count 的初始值为0,这会导致第一次接收数据时,进入了 count==0 的条件分支,然后接收到的第一个数据被存储到 data1 中,但在第一次发送之前并没有等待接收到第二个数据。这会导致在第一次发送数据之前,data2 变量中的数据是未初始化的。


    为了解决这个问题,你可以将 count 的初始值设置为1,或者在程序一开始先接收一个数据,然后再进入主循环等待下一个数据的到来。以下是一种修改后的代码示例:

    #include <REGX52.H>
    
    void UART_Init(void)
    {
        PCON |= 0x80;
        SCON = 0x50;
        TMOD &= 0x0F;
        TMOD |= 0x20;
        TL1 = 0xF3;
        TH1 = 0xF3;
        ET1 = 0;
        TR1 = 1;
        EA = 1;
        ES = 1;
    }
    
    void UART_SendByte(unsigned char Byte)
    {
        SBUF = Byte;
        while (TI == 0);
        TI = 0;
    }
    
    unsigned char data1, data2, count = 1, sum;
    
    void main()
    {
        UART_Init();
    
        while (1)
        {
            // 主循环可以放一些其他的代码逻辑
    
            // 如果需要发送数据,将数据发送到串口
            // UART_SendByte(dataToSend);
        }
    }
    
    void UART_Routine() interrupt 4
    {
        if (RI == 1)
        {
            RI = 0;
            if (count == 1)
            {
                data1 = SBUF;
                count = 2;
            }
            else if (count == 2)
            {
                data2 = SBUF;
                count = 0;
                
                // 在接收到两个数据后,计算它们的和并发送
                sum = data1 + data2;
                if (sum <= 9)
                    UART_SendByte(sum);
                else
                {
                    sum = sum + 6;
                    UART_SendByte(sum);
                }
            }
        }
    }
    

    这个修改后的代码将在接收到两个数据后再进行计算和发送,从而避免了第一次发送数据时的问题。


    该回答引用NewBing,仅为您提供参考,不保证完全正确
    未知错误


    该回答引用文心一言,仅为您提供参考,不保证完全正确
    你的代码里,串口初始化后,你没有设置串口的中断允许,也就是你没有设置ES=1。你需要在UART_Init()函数中添加ES=1;来允许串口中断。


    此外,你在主函数main()中,没有开启全局中断,你需要添加EA=1;来允许全局中断。


    修改后的代码如下:

    #include <REGX52.H>
    
    void UART_Init(void)        //串口初始化函数  
                                //4800bps@12.000MHz
    {
        PCON |= 0x80;        //使能波特率倍速位SMOD
        SCON = 0x50;        //8位数据,可变波特率,使能接收
        TMOD &= 0x0F;        //设置定时器模式
        TMOD |= 0x20;        //设置定时器模式
        TL1 = 0xF3;            //设置定时初始值
        TH1 = 0xF3;            //设置定时重载值
        ET1 = 0;            //禁止定时器中断
        TR1 = 1;            //定时器1开始计时
        EA=1;                //允许全局中断
        ES=1;                //允许串口中断
    }
    
    void UART_SendByte(unsigned char Byte)       //串口发送一个字节数据
    {
        SBUF=Byte;
        while(TI==0);     //发送控制器发送后变1,需软件重新赋值0
        TI=0;
    }        
    
    unsigned char data1,data2,count=0,sum;
    
    void main()
    {
        UART_Init();
        EA=1;                //允许全局中断  //添加这一行
        while(1)
        {
            
        }
    }
    
    void UART_Routine() interrupt 4    
    {
        if(RI==1)                      //返回电脑输入第一个数据函数,十六进制
        {
            RI=0;
            if(count==0)
            {
                data1=SBUF;
                count=1;
            }
            else if(count==1)
            {
                data2=SBUF;
                count=2;
            }
        }
        if(count==2)
        {
            sum=data1+data2;
            if(sum<=9)                        //hex模式相当于发送ASCII值,hex模式接收该ASCII对应的十六进制数,当sum<10时,sum不变例如ASCII=9对应0x09
                UART_SendByte(sum);
            else
            {
                   sum=sum+6;                    //hex模式相当于发送ASCII值,hex模式接收该ASCII对应的十六进制数,当sum>10时,sum+6例如ASCII=16对应0x10
                   UART_SendByte(sum);
            }
            count=0;
        }
            
    }
    

    该回答引用讯飞星火,仅为您提供参考,不保证完全正确
    问题可能出在串口接收中断函数UART_Routine()中。当第一次接收到数据时,count的值可能为0或1,此时会将接收到的数据存储到data1或data2中。但是,当第二次接收到数据时,count的值为2,此时会将data1和data2相加并将结果存储到sum中。然而,在计算sum的值时,没有考虑到sum可能小于等于9的情况,这可能导致sum的值不正确。


    为了解决这个问题,可以在计算sum的值时,根据sum的值是否小于等于9来选择不同的处理方式。以下是修改后的代码:

    #include <REGX52.H>
    
    void UART_Init(void)        //串口初始化函数  
                                //4800bps@12.000MHz
    {
        PCON |= 0x80;        //使能波特率倍速位SMOD
        SCON = 0x50;        //8位数据,可变波特率,使能接收
        TMOD &= 0x0F;        //设置定时器模式
        TMOD |= 0x20;        //设置定时器模式
        TL1 = 0xF3;            //设置定时初始值
        TH1 = 0xF3;            //设置定时重载值
        ET1 = 0;            //禁止定时器中断
        TR1 = 1;            //定时器1开始计时
        EA=1;                //串口中断
        ES=1;
    }
    
    void UART_SendByte(unsigned char Byte)       //串口发送一个字节数据
    {
        SBUF=Byte;
        while(TI==0);     //发送控制器发送后变1,需软件重新赋值0
        TI=0;
    }        
    
    unsigned char data1,data2,count=0,sum;
    
    void main()
    {
        UART_Init();
    
        while(1)
        {
            
        }
    }
    
    void UART_Routine() interrupt 4    
    {
        if(RI==1)                      //返回电脑输入第一个数据函数,十六进制
        {
            RI=0;
            if(count==0)
            {
                data1=SBUF;
                count=1;
            }
            else if(count==1)
            {
                data2=SBUF;
                count=2;
            }
        }
        if(count==2)
        {
            sum=data1+data2;
            if(sum<=9)                        //hex模式相当于发送ASCII值,hex模式接收该ASCII对应的十六进制数,当sum<10时,sum不变例如ASCII=9对应0x09
                UART_SendByte(sum);
            else
            {
                   sum=sum+6;                    //hex模式相当于发送ASCII值,hex模式接收该ASCII对应的十六进制数,当sum>10时,sum+6例如ASCII=16对应0x10
                   UART_SendByte(sum);
            }
            count=0;
        }
            
    }
    

    这样修改后,当sum的值小于等于9时,会直接发送sum的值;当sum的值大于9时,会将sum的值加上6后再发送。这样可以确保sum的值正确。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 9月9日
  • 创建了问题 9月8日

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?