找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1232|回复: 10
收起左侧

串口计算器程序,电脑向单片机发送顺序计算式1*2+3=不知道为什么在串口接收过来乱码

[复制链接]
ID:435640 发表于 2023-6-20 18:32 | 显示全部楼层 |阅读模式
150黑币
不知道程序那些地方有问题,不考虑算式优先级,发送顺式计算结果返回给串口,但是不知道为什么发送的是乱码
单片机源程序如下:
#include<reg52.h>
#include<stdio.h>

unsigned char rec_data[32];
unsigned char op,flag, num[2],n=0;
unsigned int i,j,ansi=0,nm;
void delay_ms(int a)
{
        int b,d;
        for(b=a;b>0;b--)
        for(d=0;d<114;d--);
        
}
void chuankou_chushihua()//串口初始化程序
{
   TMOD|=0X20; //设置计数器1为工作方式 2
   SCON=0X50; //设置串行口为工作方式 1
   PCON=0X80; //波特率加倍
   TH1=0XFA; //计数器初始值设置9600baud
   TL1=0XFA;
   ES=1; //打开接收中断
   EA=1; //打开总中断
   TR1=1; //打开计数器
}

void uart() interrupt 4 //串口通信中断函数
{
        
        RI = 0;                        //清除接收中断标志位
        rec_data[nm]=SBUF;        //存储接收到的数据
        nm++;        
        flag=1;//设立标识位
        }
void send_data( unsigned char jieguo)
{
        SBUF=jieguo;
        
        while(!TI);
                TI=0;
}
void panduan_jisuan()
{
        if('0'<=rec_data[0]&&rec_data[0]<='9')
    {// 将第一个数字存入num[0]
    num[0] = rec_data[0] - '0';

    // 扫描整个字符数组,从第二个字符开始逐一处理
    for (i = 1; i < nm; i++)
    {
        // 如果是运算符,则将其存储到op中,并将下一个数字存入num[1]
        if (rec_data[ i] == '+' || rec_data[ i] == '-' || rec_data[ i] == '*' ||rec_data[ i] == '/')
        {
            op = rec_data[ i];
            num[1] = rec_data[i + 1] - '0';
                        
            // 将指针移位至下一个数字
        }
        // 如果是等号,则运算结果即为第一个数字
        else if (rec_data[ i] == '=')
        {
            ansi = num[0];
        }
        // 如果是数字,则根据之前的运算符进行运算
        else if('0'<=rec_data[0]&&rec_data[0]<='9')
        {
            switch (op)
            {
                case '+':
                    num[0] = num[0] + (rec_data[ i] - '0');
                    break;
                case '-':
                    num[0] = num[0] - (rec_data[ i] - '0');
                    break;
                case '*':
                    num[0] = num[0] * (rec_data[ i] - '0');
                    break;
                case '/':
                    num[0] = num[0] / (rec_data[ i] - '0');
                    break;
            }
                         ansi=num[0];
        }
    }
        }
               
}
void send_int_to_serial_port(int c)
        {
    char buffer[16];

    // 使用 sprintf() 函数将整型变量转换为字符串
    sprintf(buffer, "%d", c);

    // 将字符串逐个发送到串口
    for (i = 0; buffer[ i] != '\0'; i++)
                {
        send_data(buffer[ i]);
    }
        }
void main()
{         

        chuankou_chushihua( );        

        while(1)
        {
                if(flag==1)
                 {
                         panduan_jisuan();
                        
                        send_int_to_serial_port(ansi);
                 }   
    flag=0;                 
        }
}

回复

使用道具 举报

ID:161164 发表于 2023-6-21 11:24 | 显示全部楼层
1. flag不可以在每次进中断都赋值,应改为串口超时后赋值
2. 如果TI不在中断里清零,要在SBUF=。。。之前关中断(ES=0;),TI清零后再开
回复

使用道具 举报

ID:712097 发表于 2023-6-21 11:37 | 显示全部楼层
串口通信乱码通常都是波特率不匹配。看下发送固定内容,每次接收到的乱码是否相同。如果相同,则基本可以判定是波特率的问题。如果每次收到的都是随机乱码,则说明有干扰。
回复

使用道具 举报

ID:435640 发表于 2023-6-21 11:44 | 显示全部楼层
lkc8210 发表于 2023-6-21 11:24
1. flag不可以在每次进中断都赋值,应改为串口超时后赋值
2. 如果TI不在中断里清零,要在SBUF=。。。之前 ...

能否给改一下,串口第一次用
回复

使用道具 举报

ID:1066657 发表于 2023-6-21 14:46 | 显示全部楼层
这个首先要排除波特率误差问题,其次才是报文等,因为串口通讯比较简单
回复

使用道具 举报

ID:435640 发表于 2023-6-21 16:19 | 显示全部楼层
oldhawk 发表于 2023-6-21 14:46
这个首先要排除波特率误差问题,其次才是报文等,因为串口通讯比较简单

现在没有乱码只是计算结果为零
回复

使用道具 举报

ID:1084404 发表于 2023-6-21 17:36 | 显示全部楼层
系统乱码:主要是Windows中显示乱码,比如菜单、桌面、启动界面等,造成乱码的主要原因是注册表中有关字体部分出现错误。
软件乱码:主要出现在各种软件、游戏中,本该显示中文的地方出现乱码。这种乱码的形成比较复杂,可能与系统乱码的原因相同,也有可能是软件中用到中文动态链接库被其他原语言链接库覆盖所造成的。
文件乱码:一般出现在文档或者邮件中,这是比较常见的乱码。出现这种情况往往是因为系统里没有安装可以打开该文件的软件,或者该文件类型的打开方式错误。
网页乱码:在浏览器打开的网页中出现乱码,一般来说,这是由于繁体中文大五码(BIG5)与简体中文(GB2312)不通用而造成的。
回复

使用道具 举报

ID:1084901 发表于 2023-6-23 13:36 | 显示全部楼层
想问一下你的乱码是怎么解决的
回复

使用道具 举报

ID:1086796 发表于 2023-7-2 15:56 | 显示全部楼层
该单片机源程序存在几个问题:  串口通信中断函数 uart() 中的 nm 变量没有初始化,默认为0,会导致接收到的数据存储位置错误。建议在主程序中的 chuankou_chushihua() 函数中将 nm 初始化为0。  panduan_jisuan() 函数中判断数字的条件有误,应使用 rec_data[i] 判断,而不是 rec_data[0]。正确的条件应为 '0' <= rec_data[i] && rec_data[i] <= '9'。  在 panduan_jisuan() 函数中对运算符进行处理后,应将指针移位至下一个字符,以避免重复处理已经处理过的字符。可以在 switch 语句执行后,将 i 自增1,即 i++。  在 send_int_to_serial_port() 函数中,未定义变量 i,建议在函数内部声明 int i。  在 send_int_to_serial_port() 函数中,需要在发送每个字符之后等待发送完成,即等待 TI 标志位被置位后再继续发送下一个字符。可以在 SBUF = jieguo; 后添加 while (!TI); 和 TI = 0;。
回复

使用道具 举报

ID:821429 发表于 2023-7-3 15:12 | 显示全部楼层
编程可以先画个流程图理清楚思路,整个程序思路有点乱,距离得到正确结果有点远……
回复

使用道具 举报

ID:1040201 发表于 2023-7-4 09:28 | 显示全部楼层
void delay_ms(int a)
{
        int b,d;
        for(b=a;b>0;b--)
        for(d=0;d<114;d--);    //d++?  d--没有意义呀,重新算一下这个  或者用逻辑分析仪测试。
        
}         


进了中断  不清零,它出不去。      TI = 0;
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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