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;
    }
        
}
    

该回答引用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的值正确。

【相关推荐】




如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^