单片机软件工程(一)--FIFO设计


单片机软件工程(一)--FIFO设计  


中午调一个程序,一个比较简单的程序,就是几个按键,一个数码管,使得用按键控制数码管上的数字,前提是不阻塞CPU!!(本来整个程序设计是不准备利用延时的,但是为了方便起见,数码管的扫描过程中,还是用了一个延时,有点阻塞CPU)对按键的扫描的过程中不能使用延时,而是利用前后台程序的思想进行设计,让按键扫描程序在定时中断10ms内进行,后台程序获取键值。因为单片机执行速度很快,为了防止漏键,设计一个FIFO隔离软件与硬件层,即:让后台程序只是从FIFO里面取键值,而前台也只是将键值保存在FIFO中,这样,可以防止漏键可惜,一不小心,在防止中断影响共享时,关了中断,就忘记了打开,结果一直没调试出来,后来一行一行找,才发现了这个低级错误,浪费了一中午的时间!!!!

FIFO设计:在单片机的程序设计过程 中,通常为了防止数据的丢失,利用FIFO来缓冲高速与低速设备的差异,这样可以保证数据在传输的过程中不会丢失。

程序设计如下:

/*********************************************************************************************
      
/*********************************************************************************************
说明: 按键的设计:利用FIFO队列来进行数据的缓冲,这样CPU不直接操作硬件,而是通过键盘缓冲区来
获取键盘的值。这样,可以将前台与后台程序隔离开来。消除了按键扫描与读键之间的时间关联性

/*********************************************************************************************/
/**********************************************************************************************/
#include<reg51.h>      //常用的头文件
#include <intrins.h> //51基本运算(包括_nop_空函数)
//#include<dispy.h>    //模块接口 :display()扫描,send_dat(uint dat)显示数据,前者放在定时器里面,后者放在后台

#define uchar unsigned char
#define ulong unsigned long
#define uint unsigned int
#define size 4


void key_buffer(uchar key);
uchar key_get();


sbit KEY1_IN=P3^7;
sbit KEY2_IN=P3^6;
sbit dula=P2^6;    //控制数码管位选的使能
sbit wela=P2^7;    //控制数码管段选的使能,低电平位选中
//sbit KEY2_IN=P3^6;
//sbit KEY3_IN=P3^7;


uchar P_key1=255;    //存放按键前一次状态的变量
uchar N_key1=255;     // 存放下一次按键的状态,通过定时器中断(10ms)的扫描便可以确定是否被按下

uchar key_max=0;
uchar key_min=0;
uchar count=0;         //定义FIFO的头指针,尾指针,与指针计数
uchar key_inbuff[size];       //定义FIFO的容量

static  uchar temp;

uchar P_key2=255;    //存放按键前一次状态的变量
uchar N_key2=255;     // 存放下一次按键的状态,通过定时器中断(10ms)的扫描便可以确定是否被按下

//uchar P_key3=255;    //存放按键前一次状态的变量
//uchar N_key3=255;     // 存放下一次按键的状态,通过定时器中断(10ms)的扫描便可以确定是否被按下

unsigned char code table[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//数码管数据

/**********************按键1扫描***************************************************************/
void key_scan()      //放在10ms的中断函数里面执行
{
  P_key1=N_key1;       //每扫描一次,则把下一次的状态给当前(即把后一次的给前一次)
  N_key1=KEY1_IN;       //按键此时的状态给N_key

  P_key2=N_key2;       //每扫描一次,则把下一次的状态给当前(即把后一次的给前一次)
  N_key2=KEY2_IN;       //按键此时的状态给N_key

 // P_key3=N_key3;       //每扫描一次,则把下一次的状态给当前(即把后一次的给前一次)
 // N_key3=KEY3_IN;       //按键此时的状态给N_key

if((P_key1!=0)&&(N_key1==0))    //表示按键被按下
        key_buffer(0x01);   //可以代表键值,可也以用此表征键被按下

if((P_key2!=0)&&(N_key2==0))    //表示按键被按下
        key_buffer(0x02);   //可以代表键值,可也以用此表征键被按下
 
}
/**********************按键2扫描***************************************************************/

/***********************将键值数据压入FIFO****************************************************/
void key_buffer(uchar key)     // 设计一FIFO,将键值压入FIFO
{
  if (count>=size) return;
     EA=0;  //防止数据被 中断
  count++;         //按键次数递增
 key_inbuff[key_max] =key;       //压入FIFO
   if (++key_max>=size)     //如果越界,而从头部追加新的数据
     
   {
     key_max=0;
   }
     EA=1;
}
/**********************************************************************************************/
void delayms(uint z)   //ms级延时函数
    { uint x,y;
        for(x=z;x>0;x--)
            for(y=110;y>0;y--);
     }
/**********************************************************************************************/
void display(uchar a)   //第一个数码管亮  位选
{
   wela=0;
   P0=0xfe;
   wela=1;
   wela=0;

   dula=0;
   P0=table[a]; //显示最高位
   dula=1;
   dula=0;
   delayms(2);
}
/**********************************************************************************************/
uchar key_get(void)       // 从FIFO里面取出键值
{
  uchar key;
  if(count==0) return(0);    //如果没数据,返回0
  EA=0;
  count--;
  key=key_inbuff[key_min];
  if (++key_min>=size)
    {
  key_min=0;
 }
  EA=1;
  return(key);
}
/**********************************************************************************************/
/**********************************************************************************************/
void timer_init(void)
{
 TMOD=0x10;
 TH1=(65536-15000)/256;      //时间为1ms
 TL1=(65536-15000)%256;
 EA=1;
 ET1=1;
 TR1=1;
}
/**********************************************************************************************/
void main()
{
  uchar i ;
  timer_init();
  while(1)
    {
   temp= key_get();  //获取键值
  
   if(temp==0x01)  //按键进行处理
      {
    i++;
    if(i==9)
    i=0;
    display(i);
   }
   if (temp==0x02)
      {
   display(5);
    }
   
 
 }
}
/**********************************************************************************************/
void time1(void)interrupt 3   //以每15ms对按键进行扫描
  {
   TH1=(65536-15000)/256;
   TL1=(65536-15000)%256;
   key_scan();
 
  }
/**********************************************************************************************/
/**********************************************************************************************/
/**********************************************************************************************/
/**********************************************************************************************/
/**********************************************************************************************/

原文地址http://li19910722.blog.163.com/blog/static/136856822201141814614750/

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值