基于STC51单片机的计数器

基于STC51单片机的计数器

设计要求:

  • 写出矩阵键盘的驱动

  • 分别按下对应的键。数码管会将键盘对应的值累加并显示

设计概述:

​  按照设计要求,所需要的单片机芯片为STC89C52,所用的硬件工具是由华清远见开发的基于STC89C52的智能小车。该小车配备所需要的矩阵按键模块和数码管模块,矩阵按键模块由P3口控制,数码管模块位选P2.7口控制,段选由P2.6口控制,数字显示由P0口控制。STC89C52是一种低功耗,高性能的8位微控制器,是加强版的80C51单片机。

**矩阵键盘:**4x4矩阵键盘共有16个按键,每个按键的左端都连接在一根线上形成行线,每个按键的右端也都连接在一根线上形成列线。P3口的低4位分别于行线连接,高4位分别与列线连接。通过扫描矩阵键盘中按键两端的电平变化来准确识别其中的按键。

源代码:

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char

sbit WELA = P2^7; //定义位选IO口
sbit DULA = P2^6;//定义段选IO口

void matrix_key_scan();
void delay_ms(uint ms);
void sum_key();
void display_num(unsigned int num);
void display_digit(unsigned char wela,unsigned char dula);

uint key_value = 0; //定义全局变量保存键值
uint keynum1 = 0;
uint keynum2 = 0;

//数码管0-9段选编码
uchar code Du[] = {0x3f,0x06,0x5b,0x4f,
                   0x66,0x6d,0x7d,0x07,
                   0x7f,0x6f}; 

/*-----矩阵键盘扫描函数-----*/
void matrix_key_scan()
{
   uchar temp;
   uchar a = 0;
   P3 = 0x0f;//将所有行电平拉高,列电平拉低,进行行扫描
   temp = P3;
   if(temp != 0x0f)//检测是否有键按下
   {
   	   delay_ms(5);//延时去抖
	   if(temp != 0x0f)//再次确认按键按下
	   {
	   	  P3 = 0x0f;//将所有行电平拉高,列电平拉低,进行行扫描
          temp = P3;
		  switch(temp)
		  {
		     case 0x0e:key_value = 0;	//第1行
			           break;
		  	 case 0x0d:key_value = 4;  //第2行
			           break;
			 case 0x0b:key_value = 8;	//第3行
			           break;
			 case 0x07:key_value = 12; //第4行
			           break;
		  }
		  P3 = 0xf0;//将所有列电平拉高,行电平拉低,进行列扫描
          temp = P3;	  
		  switch(temp)
		  {
		  	 case 0xe0:key_value = key_value + 0;//第1列
			           break;
		  	 case 0xd0:key_value = key_value + 1;//第2列
			           break;
             case 0xb0:key_value = key_value + 2;//第3列
			           break;
			 case 0x70:key_value = key_value + 3;//第4列
			           break;
		  
		  
		  //这里需要延时200ms,因为矩阵键盘扫描函数在while循环中是不断执行
		  //如果按下键后不松开或者松开键慢了,keynum2变量就会不断累加,
		  delay_ms(200);
		  keynum1 = key_value;
		  keynum2 = keynum2 + keynum1;

	  }
	}
   
   while((a < 50)&&(temp != 0xf0))//等待按键释放
   {
   	   a++;
   }
}

/*-----毫秒级延时函数-----*/
void delay_ms(uint ms)
{
   volatile uint i,j;
   for(i = ms;i > 0;i--)
   {
      for(j=0;j<110;j++);
   }
  
}

/*--------数码管显示数字函数---------*/
void display_num(unsigned int num)
{
	unsigned int div = 0;
	unsigned char rema = 0;
	unsigned char index = 0;
		
	while((div = num / 10) > 0)
	{
		rema = num % 10;
		display_digit(index,rema);
		num = div;
		index++;
		delay_ms(2);
	}
	rema = num % 10;
	display_digit(index,rema);
}

/*-------数码管位选函数-------*/
void display_digit(unsigned char wela,unsigned char dula)
{
	WELA = 1;// 位选端锁存器置高,送数据
	P0 = 0xFF;//消影
	P0 &= ~(1 << (7 - wela));//1000 0000	  0111 1111
	WELA = 0;// 位选端锁存器置低,保存数据

	DULA = 1;// 段选端锁存器置高,送数据
	P0 = Du[dula];//送数据
	DULA = 0;// 段选端锁存器置低,保存数据
}

void main()
{
	while(1)   
	{  
	   matrix_key_scan();
	   display_num(keynum2);
 	}
}

小车部分原理图:

在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值