0

我用 C 语言为微控制器 8051 架构编写了程序,它从串口接收数据并显示在 7seg 显示器上,但数字在闪烁。你能帮我解决这个问题吗?处理器是 80C32。4051多路复用器与微控制器连接并选择显示器。有5个7seg显示器,通过ULN2803与微控制器连接。谢谢。这是我的代码:

enter code here

#include <reg51.h>
#include <stdio.h>
#include <stdlib.h>

void displayDigit(unsigned char cifra);
void delayTimer();
void showNumber(); //receive data from serial port and store data in buffer buff
void initSerial(); // serial port initialization
char receiveData();
void delay(unsigned int msdelay);
char buff[20]; // store data from serial port
unsigned int tmp1,tmp2,tmp3,tmp4,tmp5;
int tail=0; // index of element in buffer buff
sbit A=P3^4;   // A is pin on 4051 Multiplexer
sbit BB=P3^5;  // BB is pin on 4051 Multiplexer
sbit C=P3^6;  // C is pin on 4051 Multiplexer
sbit INH=P3^7; // INH pin on 4051 Multiplexer

void main(void)
{
   P1=0x00;
   P3=0x03;
   PT0=1;
   while(1)
   {
     initSerial();
     showNumber();
     delayTimer(); 
   }
}

// mask
void displayDigit(unsigned char cifra)
{
   switch(cifra)
   {
     case 0: P1=0x3F; break;
     case 1: P1=0x06; break;
     case 2: P1=0x5B; break;
     case 3: P1=0x4F; break;
     case 4: P1=0x66; break;
     case 5: P1=0x6D; break;
     case 6: P1=0x7D; break;
     case 7: P1=0x07; break;
     case 8: P1=0x7F; break;
     case 9: P1=0x6F; break;
  }
}

// refresh display - a 
void delayTimer()
{
  TMOD&=0xF0;
  TMOD|=0x01;
  TH0=0xFF;
  TL0=0xFF;
  ET0=1;
  EA=1;
  TR0=1;
  while(TF0==0);
  TF0=0;
  TR0=0;
}

// serial port initialization
void initSerial()
{
  SCON=0xD0;
  TMOD&=0x0F;
  TMOD|=0x20;
  TH1=0xFD;
  TR1=1;
}

// receive data
char receiveData()
{
  char el;
  while(RI==0);
  el=SBUF;
  RI=0;
  return el;
}

// receive data from serial port and store data in buffer
void showNumber()
{ 
  int tail=0; 
  char el;
  el=receiveData();
  if(el==0x02) // start of communication
  {
    buff[tail]=el;
    tail++;
    while(el!=0x03)
    {
      el=receiveData();
      if(el!=0x03)
      {
        buff[tail]=el;
        tail++;
      }
      else
      {
        buff[tail]=el;
        tail++;
        buff[tail]='\0';
      }
      if(tail==20)
        tail=0;
    } 
  }
  else if(el==0x03) // end of communication
  {
    buff[tail]=el;
    tail++;
    buff[tail]='\0'; 
  } 
} 
// show on display
void timer0(void) interrupt 1
{
  int i;
  tmp5=buff[3]-'0';
  tmp4=buff[4]-'0'; 
  tmp3=buff[5]-'0';
  tmp2=buff[6]-'0';
  tmp1=buff[7]-'0'; 
  if(tmp5==0 && tmp4==0 && tmp3==0 && tmp2==0) // 1 digit on display
  {
    for(i=0;i<40;i++)
    {
      INH=0;
      C=0;
      BB=0;
      A=1;
      displayDigit(tmp1);
      delay(8);
    }
  }
  else if(tmp5==0 && tmp4==0 && tmp3==0) // 2 digits on display
  {
    for(i=0;i<40;i++)
    {
      INH=0;
      C=0;
      BB=0;
      A=1;
      displayDigit(tmp1);
      delay(8);
      INH=0;
      C=0;
      BB=1;
      A=0;
      displayDigit(tmp2);
      delay(8);
    }
  }
  else if(tmp5==0 && tmp4==0) // 3 digits on display
  {
    for(i=0;i<40;i++)
    {
      INH=0;
      C=0;
      BB=0;
      A=1;
      displayDigit(tmp1);
      delay(8);
      INH=0;
      C=0;
      BB=1;
      A=0;
      displayDigit(tmp2);
      delay(8);
      INH=0;
      C=0;
      BB=1;
      A=1;
      displayDigit(tmp3);
      delay(8);
    }
  }
  else if(tmp5==0) // 4 digits on display
  {
    for(i=0;i<40;i++)
    {
      INH=0;
      C=0;
      BB=0;
      A=1;
      displayDigit(tmp1);
      delay(8);
      INH=0;
      C=0;
      BB=1;
      A=0;
      displayDigit(tmp2);
      delay(8);
      INH=0;
      C=0;
      BB=1;
      A=1;
      displayDigit(tmp3);
      delay(8);
      INH=0;
      C=1;
      BB=0;
      A=0;
      displayDigit(tmp4);
      delay(8);
    }
  }
  else  // 5 digits on display
  {
    for(i=0;i<40;i++)
    {
      INH=0;
      C=0;
      BB=0;
      A=1;
      displayDigit(tmp1);
      delay(8);
      INH=0;
      C=0;
      BB=1;
      A=0;
      displayDigit(tmp2);
      delay(8);
      INH=0;
      C=0;
      BB=1;
      A=1;
      displayDigit(tmp3);
      delay(8);
      INH=0;
      C=1;
      BB=0;
      A=0;
      displayDigit(tmp4);
      delay(8);
      INH=0;
      C=1;
      BB=0;
      A=1;
      displayDigit(tmp5);
      delay(8);
    }
  }
}

void delay(unsigned int msdelay)
{
  unsigned int i,j;
  for(i=0;i<msdelay;i++)
  {
    for(j=0;j<100;j++);
  }
}
4

1 回答 1

0

这里有一些建议可以帮助你:

  1. 使能 UART RX 中断。让该中断处理程序执行 == 禁用中断 == 如果接收到的字节为 0x02,则: ==== 将 buffIndex 设置为 0 ==== 设置全局标志,指示接收下一条消息 == 否则,如果接收到的字节为 0x03,则设置标志指示完整消息可用 == 否则将字符保存在 buff[] 中的下一个位置并增加 buffIndex == 清除 UART RX 中断挂起标志 == 退出
  2. 代码应该实现“双缓冲区”,以便后台处理“主”有时间处理新消息。
  3. 哪个缓冲区正在接收字节应该被认为是“活动”缓冲区 哪个缓冲区正在显示消息应该被认为是“非活动”缓冲区
  4. main位于等待消息可用的自旋循环上。然后 main 将立即重置“消息可用”标志
  5. 为了获得最大的稳健性,消息的显示应在 1 毫秒内完成,因此字符的显示必须有足够长的延迟,以便多路复用器稳定下来。这样的多路复用器建立时间应该以微秒为单位,而不是毫秒。消息的显示是“串行的”并且没有时间(除了等待多路复用器建立),因此建议不要将其置于中断上。
  6. 您的硬件是否有每个数字的数据锁存器?如果是这样,则无需多次写入一个数字,因此可以消除那些一遍又一遍地写入相同数据的循环。
于 2018-04-19T07:22:10.737 回答