关于STC15单片机加减法出现错误的原因分析

        最近在做一个项目,使用STC15单片机自带的ADC获取数据时候,发现在获取数据进行加减法运算之后,单片机的加减法出现结果错误的情况。

        在不断的调试之后,我发现问题出现在sprintf函数上,简单说就是单片机ADC采集和sprintf发生了冲突,导致单片机内部算法出现错误。

错误

void main()
{
  Uart1_Init();
  ADC_Init();
  Timer0_Init();
  Uart1_SendString("hello world\r\n");
  while(1)
  {
    if(revADC_flag)
    {
      rev_Vol_MAX=revAC_MAX*5/1024.0;
      rev_Vol_Min=revAC_Min*5/1024.0;
      rev_Vol_error=rev_Vol_MAX - rev_Vol_Min;
      revAC_MAX=0;
      revAC_Min=1024; 
      
      sprintf(str,"Max=%5.3f - Min=%5.3f - Error=%0.3f\n",\
                    rev_Vol_MAX,rev_Vol_Min,(float)(1.0+1.0));
      Uart1_SendString(str);
      revADC_flag=0;      
    }
  }
}

这是我部分的一个代码,出现的效果为下图

非常的不可思议,1+1的值出现了错误。

修正

接下来,我对代码进行了修改

首先,先对单片机的printf函数进行重定义,重定义的办法只需要加入一个代码即可,代码如下:

char putchar(char ch)
{
  SBUF=ch;
  while(!TI);
  TI=0;
  return ch;
}

其次,我们可以使用printf作为串口打印函数了,下面是修正之后的代码,使用printf代替sprintf+Uart1-SendString作为字符串输出。

void main()
{
  Uart1_Init();
  ADC_Init();
  Timer0_Init();
  printf("hello world\r\n");
  while(1)
  {
    if(revADC_flag)
    {
      rev_Vol_MAX=revAC_MAX*5/1024.0;
      rev_Vol_Min=revAC_Min*5/1024.0;
      rev_Vol_error=rev_Vol_MAX - rev_Vol_Min;
      revAC_MAX=0;
      revAC_Min=1024; 
      
      printf("Max=%5.3f - Min=%5.3f - Error=%0.3f\n",\
                rev_Vol_MAX,rev_Vol_Min,(float)(1.0+1.0));
      revADC_flag=0;      
    }
  }
}

修正之后的串口打印效果,此时我们的1+1终于等于2了。

以下是基于STC89C52单片机的简易加减法计算器的代码,供你参考: ```c #include <reg52.h> #include <stdio.h> sbit KEY1 = P3^2; sbit KEY2 = P3^3; sbit KEY3 = P3^4; sbit KEY4 = P3^5; sbit D1 = P1^0; sbit D2 = P1^1; sbit D3 = P1^2; sbit D4 = P1^3; char code Table[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; unsigned char num1, num2, flag, oper, result; unsigned char Stack[4]; unsigned char Top = 0; void Delay(unsigned int i) { while(i--); } void Display(unsigned char num) { D4 = 1; P0 = Table[num%10]; D4 = 0; Delay(5); D3 = 1; P0 = Table[num/10%10]; D3 = 0; Delay(5); D2 = 1; P0 = Table[num/100%10]; D2 = 0; Delay(5); D1 = 1; P0 = Table[num/1000%10]; D1 = 0; Delay(5); } void KeyDown() { if(!KEY1) { Delay(2000); if(!KEY1) { if(flag == 0) { num1 = num1*10 + 1; Display(num1); } else { num2 = num2*10 + 1; Display(num2); } } } if(!KEY2) { Delay(2000); if(!KEY2) { if(flag == 0) { num1 = num1*10 + 2; Display(num1); } else { num2 = num2*10 + 2; Display(num2); } } } if(!KEY3) { Delay(2000); if(!KEY3) { if(flag == 0) { num1 = num1*10 + 3; Display(num1); } else { num2 = num2*10 + 3; Display(num2); } } } if(!KEY4) { Delay(2000); if(!KEY4) { if(flag == 0) { oper = '+'; flag = 1; } else { oper = '-'; flag = 2; } } } } void Init() { TMOD = 0x01; TH0 = 0xfc; TL0 = 0x18; EA = 1; ET0 = 1; TR0 = 1; } void Time0() interrupt 1 { TH0 = 0xfc; TL0 = 0x18; KeyDown(); } void Calculate() { switch(oper) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; default: break; } Stack[Top++] = result%10; Stack[Top++] = result/10%10; Stack[Top++] = result/100%10; Stack[Top++] = result/1000%10; while(Top != 0) { Display(Stack[--Top]); Delay(10000); } } void main() { Init(); while(1) { if(flag == 2) { Calculate(); flag = 0; num1 = 0; num2 = 0; oper = 0; } } } ``` 以上是基于STC89C52单片机的简易加减法计算器的代码,其中包括按键扫描、数码管显示、加减法运算等功能。需要注意的是,代码中的硬件电路需要自行搭建,并且可能需要根据具体情况进行调整。另外,代码中的延时函数只是简单的延时,实际中需要根据具体情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值