【问题标题】:The digits are blinking on 7 seg display with 8051 microcontroller使用 8051 微控制器的 7 段显示器上的数字闪烁
【发布时间】:2018-04-17 10:32:43
【问题描述】:

我用 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++);
  }
}

【问题讨论】:

  • 嗯?数字之间的 8 毫秒延迟对于多路复用来说方式太多了,5 ​​位数字可以实现最大 1/(5*40e-3) =~ 5 fps,所以这当然会闪烁。跨度>
  • 为什么要一遍遍地重新初始化串口?切勿使用char 存储原始数据。保持中断简短——你应该在那里设置一个标志,然后在 main 中进行实际工作。等等。一旦你得到这个工作,我建议你通过codereview.stackexchange.com,因为这里有太多的问题。标记它embedded
  • 我应该将中断保持多长时间?我应该在中断函数中设置标志吗?我应该使用什么来存储原始数据,而不是 char?

标签: c interrupt interrupt-handling 8051 nxp-microcontroller


【解决方案1】:

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

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

【讨论】:

  • 我做到了,但数字仍在闪烁。我没有每个数字的数据锁存器,所以我使用 for 循环。还有其他建议吗?
  • 当然数字会闪烁。当数字未被选择时,数字“消失”。 IE。您的硬件确实需要每个数字的数据锁存器,因此代码可以设置数字并继续进行其他活动。使用数据锁存器,数字将保持不变,直到代码出现以更改数据锁存器中的值
猜你喜欢
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多