c - 8051 微 Controller 的 7 段显示屏上的数字闪烁

标签 c interrupt interrupt-handling 8051 nxp-microcontroller

我用C语言为微 Controller 8051架构编写了程序,该程序从串行端口接收数据并显示在7段显示器上,但数字在闪烁。你能帮我解决这个问题吗?处理器是80C32。 4051多路复用器与微 Controller 连接并选择显示器。有5个7段显示器,通过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++);
  }
}

最佳答案

以下是一些可以帮助您的建议:

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

关于c - 8051 微 Controller 的 7 段显示屏上的数字闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49875788/

相关文章:

linux - 在 Linux 中修改定时器中断

python - Raspberry Pi 和 PiFace Digital 的中断

interrupt-handling - __even_in_range(UCA0IV,0x08) 是什么意思

c++ - 如何使用C\C++在windows中实现linux管道

c - c中for循环问题中的特殊字符读取

使用可变参数函数连接字符串

iphone - openAL 流媒体和中断

c - 函数和头文件 (ansi c)

ios - iOS 应用程序在后台录制时音频中断

java - 线程中断有时有效有时无效