求大神解答 2023-05-04 08:04 采纳率: 72.7%
浏览 17

矩阵键盘∶纠错,谢谢你们

这是自己的代码和电路图(电路图不完整,不知道怎么补充),但是一直找不到哪里有错?
这是问题

img


电路图

img


代码

img

img

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-05-04 10:03
    关注
    • 你可以看下这个问题的回答https://ask.csdn.net/questions/7762703
    • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:为了强调低电平有效,有时也将反相器图形符号中表示反相的小圆圈画在输入端,例如上图的左边一列反相器的画法
    • 除此之外, 这篇博客: 【笔记】6位数码管显示定时器定时的时分秒,通过按键控制时间,自定义串口通信协议,根据单片机接收到的指令控制数码管显示中的 4、源代码  部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    • /*******************************************************************************
      程序功能:1.时分秒的动态显示。2.用三个按键实现时分秒的修改,调节的数字闪烁提示。
      3.串口控制时钟的暂停、开始、清零、读取、设置时间
      串口协议格式:s+指令+数据+e
      s:表示开始码
      指令:
      	|	p:计时暂停(无数据位)	         |
      	|	r:计时重启(无数据位)	         |
      	|	c:显示清零(无数据位)	         |
      	|	q:查询当前时间(无数据位)        
      	|	t:设置时间(数据位格式为6位数字) 
      *******************************************************************************/
      
      #include <reg52.h>		 //包含需要的头文件
      
      #define u8 unsigned char
      #define u16 unsigned int	
      
      u8 WeiMa[6]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};
      u8 DuanMa[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
      
      //函数声明
      void Delay_ms(u16 xms);
      void ShuMaGuan(u8 wei,u8 duan);
      void Display_Timer(u8 hour,u8 min,u8 sec);
      u8 Key_Scan();
      void PutChar(u8 n);
      void UartInit();
      void PutString(u8 *p);
      void Key_Timer_Set();
      void Uart_Timer_Set();
      void Pintf_Uart();
      
      
      //引脚定义
      sbit SW1=P3^2;
      sbit SW2=P3^3;
      sbit SW3=P3^4;
      
      u8 Hour=0,Min=0,Sec=0;//全局变量,时分秒
      u8 mode=0;//全局变量:状态切换,0:时钟显示,1:调节时;2:调节分;3:调节秒
      bit flash_tip=1;//数码管闪烁标志,为0时数码管熄灭,为一时数码管显示
      
      #define Data_SIZE 15 //数据长度
      u8 USART_RX_BUF[Data_SIZE]; //接收缓冲,最大Data_SIZE个字节.末字节为换行符 
      u8 Start_Receiving=0; //开始接收标志位
      u8 Receive_OK=0;   //接收完毕接收位 1为接收完毕
      
      //函数功能:定时器初始化
      void Time0init()
      {
      	TMOD|=0x01;				//设置定时器模式
      	TF0=0;					//清除TF0标志
      	TH0=(65536-50000)/256;  //设置定时初值
      	TL0=(65536-50000)%256;	//设置定时初值
      	TR0=1;					//定时器0允许计时
      	ET0=1;					//中断允许
      	EA=1;					//CPU中断允许位打开
      }
      
      //串口初始化
      void UartInit()  //9600bps@11.0592MHz
      {
       
      	 PCON &= 0x8F;  //波特率倍速
      	 SCON = 0x50;  //8位数据,可变波特率
      	 TMOD &= 0x0F;  //清除定时器1模式位
      	 TMOD |= 0x20;  //设定定时器1为8位自动重装方式
      	 TL1 = 0xFD;   //设定定时初值
      	 TH1 = 0xFD;  //设定定时器重装值
      	 TR1 = 1;  //启动定时器1
      	 EA=1;
      	 ES=1;  //打开接收中断
      }
      
      /*******************************************************************************
      * 函 数 名: void main()
      * 函数功能: 主函数
      *******************************************************************************/
      void main()
      {
      	
      	
      	Time0init();//定时器
      	UartInit(); //串口
      	Pintf_Uart();//输入提示
      	while(1)
      	{
      		Key_Timer_Set();//按键控制时钟
      		Uart_Timer_Set();//按键调节时钟
      		Display_Timer(Hour,Min,Sec);//数码管显示
      		
      	}
      }
      
      /*******************************************************************************
      * 函 数 名: void Pintf_Uart()
      * 函数功能: 串口助手输入指示
      *******************************************************************************/
      void Pintf_Uart()
      {
      	/***************输入指示*******************/
      	PutString("Please input:s+command(data)+e\r\n");
      	PutString("Stop_Time:spe\r\n");
      	PutString("Start_Time:sre\r\n");
      	PutString("Zero_Time:sce\r\n");
      	PutString("Read_Time:sqe\r\n");
      	PutString("Set_Time:st******e\r\n");
      	/*******************************************/
      }
      
      /*******************************************************************************
      * 函 数 名: void Key_Timer_Set()
      * 函数功能: //按键调节时钟
      *******************************************************************************/
      void Key_Timer_Set()
      {
      	u8 keynum;
      	keynum=Key_Scan();//按键返回值
      	if(keynum)   //非0表示有按键按下
      	{
      		switch(keynum)  //判断是哪个按键按下,按键一调节模式,按键2自加,按键3自减
      		{
      			case 1:if(++mode>=4) mode=0;break;  //++mode为先自增再判断是否大于4
      			case 2:
      				if(mode==1) if(++Hour>=24) Hour=0;//++mode为先自增再判断是否大于4
      				if(mode==2) if(++Min>=60) Min=0;//++Min先自增再判断是否大于60
      				if(mode==3) if(++Sec>=60) Sec=0;//++Sec先自增再判断是否大于60
      				break;										
      			case 3:
      				if(mode==1)	if(--Hour==255) Hour=23;//--Hour先自增再判断是否溢出
      				if(mode==2) if(--Min==255) Min=59;//--Min先自增再判断是否大溢出
      				if(mode==3) if(--Sec==255) Sec=59;//--Sec先自增再判断是否大溢出
      				break;
      			default:break;
      		}
      	}	
      }
      /*******************************************************************************
      * 函 数 名: void Key_Timer_Set()
      * 函数功能: 串口调节时钟
      串口协议格式:s+指令+数据+e
      s:表示开始码
      指令:
      	|	p:计时暂停(无数据位)	|
      	|	r:计时重启(无数据位)	|
      	|	c:显示清零(无数据位)	|
      	|	q:查询当前时间(无数据位)         
      	|	t:设置时间(数据位格式为6位数字)  
      *******************************************************************************/
      void Uart_Timer_Set()
      {
      	static u8 Hour_1,Min_1,Sec_1;//时间暂存 
      	if(Receive_OK) //如果串口接收到数据
      	{
      		Receive_OK=0;
      		switch(USART_RX_BUF[0])//存入数组的数据没有开始码,所以第一个数据是指令
      		{
      			case 'p':   //时钟暂停
      				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
      					PutString("Error!\r\n");
      				else
      				{
      					TR0=0;
      					PutString("Stop OK!\r\n");
      				}
      				
      				break;
      			case 'r':   //开始计时
      				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
      					PutString("Error!\r\n");
      				else
      				{
      					TR0=1;
      					PutString("Start OK!\r\n");
      				}
      				break;
      			case 'c':   //清零
      				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
      					PutString("Error!\r\n");
      				else
      				{
      					Hour=0;
      					Min=0;
      					Sec=0;
      					PutString("Zero OK!\r\n");
      				}
      				
      				break;
      			case 'q':   //查询当前时间
      				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
      					PutString("Error!\r\n");
      				else
      				{
      					PutString("The time is:");
      					PutChar(Hour/10+48);  //转化ASCII码字符,0为48,1为48+1=49.....
      					PutChar(Hour%10+48);
      					PutChar(':');
      					PutChar(Min/10+48);
      					PutChar(Min%10+48);
      					PutChar(':');
      					PutChar(Sec/10+48);
      					PutChar(Sec%10+48);
      					PutString("\r\n");
      				}
      				
      				break;
      			case 't':   //设置时间
      				if(USART_RX_BUF[7]!='e')//如果接收到的数据不是6位数字,说明第7位数组的数据不是停止码
      					PutString("Error!\r\n");
      				else
      				{
      					Hour_1=(USART_RX_BUF[1]-48)*10+(USART_RX_BUF[2]-48); //转化成十进制
      					Min_1=(USART_RX_BUF[3]-48)*10+(USART_RX_BUF[4]-48); //转化成十进制
      					Sec_1=(USART_RX_BUF[5]-48)*10+(USART_RX_BUF[6]-48); //转化成十进制
      					if(Hour_1>23 || Min_1>59 || Sec_1>59)  //超出时间阈值
      						PutString("Error!\r\n");	
      					else  
      					{
      						Hour=Hour_1;  
      						Min=Min_1;
      						Sec=Sec_1;
      						PutString("Set OK!\r\n");
      					}
      				}
      				break;
      			default:PutString("Error!\r\n");break;
      		}
      		ES=1;  //开启接收
      	}
      }
      
      /*******************************************************************************
      * 函 数 名: void Delay_ms(u16 xms)
      * 函数功能: 软件延时函数,xms为延时多少毫秒
      *******************************************************************************/
      void Delay_ms(u16 xms)
      {
      	
      	unsigned char i, j;
      	while(xms--)
      	{
      		i = 2;
      		j = 135;
      		do
      		{
      			while (--j);
      		} while (--i);
      	}
      }
      
      /*******************************************************************************
      * 函 数 名: void ShuMaGuan(u8 wei,u8 duan)
      * 函数功能: 静态显示一位,参数:wei控制位选duan控制段选,表示要显示的一个数字
      *******************************************************************************/
      void ShuMaGuan(u8 wei,u8 duan)
      {
      	P1=WeiMa[wei];    //位选
      	P2=DuanMa[duan];  //段选
      	Delay_ms(1); //间隔一段时间扫描
      	P1=0xFF;    
      	P2=0xFF;	   //消隐
      }
      
      /*******************************************************************************
      * 函 数 名: void Display_Timer(u8 hour,u8 min,u8 sec)
      * 函数功能:数码管动态显示
        flash_tip为数码管闪烁标志,为0时数码管熄灭,为一时数码管显示
        flash_tip每4.5秒进行取反
      *******************************************************************************/
      void Display_Timer(u8 hour,u8 min,u8 sec)
      {
      	if(mode!=1 || flash_tip==1) //mode=1时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示
      	{
      		ShuMaGuan(5,hour/10);
      		ShuMaGuan(4,hour%10);
      	}
      	else P1=0xFF;
      	
      	
      	if(mode!=2 || flash_tip==1)//mode=2时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示
      	{
      		ShuMaGuan(3,min/10);
      		ShuMaGuan(2,min%10);
      	}
      	else P1=0xFF; 
      	
      	
      	if(mode!=3 || flash_tip==1)//mode=3时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示
      	{
      		ShuMaGuan(1,sec/10);
      		ShuMaGuan(0,sec%10);
      	}
      	else P1=0xFF;  
      }
      
      /*******************************************************************************
      * 函 数 名: u8 Key_Scan()
      * 函数功能: 独立按键检测,按键按下分别返回1.2.3
      *******************************************************************************/
      u8 Key_Scan()
      {
      	static u8 key_up=1; //按键按松开标志
      	if(key_up && (SW1==0 || SW2==0 || SW3==0))
      	{
      		Delay_ms(10); //去抖动
      		key_up=0; //松手标志为0,那么下次再检测,if结果为0,则不会进入这里的语句
      		if(SW1==0) return 1;
      		if(SW2==0) return 2;
      		if(SW3==0) return 3;
      	}
      	else if(SW1 == 1 && SW2 == 1 && SW3 == 1) key_up=1; //松手标志
      	return 0; // 无按键按下
      }
      
      /*******************************************************************************
      * 函 数 名: void PutChar(u8 n)
      * 函数功能: 发送一个字符
      *******************************************************************************/
      void PutChar(u8 n)
      {
      	 SBUF=n;
      	 while(!TI);
      	 TI=0;
      }
      
      /*******************************************************************************
      * 函 数 名: void PutString(u8 *p)
      * 函数功能: 发送字符串
      *******************************************************************************/
      void PutString(u8 *p)
      {
      	while(*p!='\0')
      	{
      		PutChar(*p);
      		p++;
      	}
      }
      /*******************************************************************************
      * 函 数 名: void uart() interrupt 4
      * 函数功能: 串口中断服务函数,单片机接收数据并存入USART_RX_BUF[]数组中
      开始码s不存入数组
      *******************************************************************************/
      void uart() interrupt 4
      {
      	static u8 Data_count=0;
      	u8 Data;
      	if(RI==1)
      	{
      		RI=0;
      		Data=SBUF;
      		if(Data=='s')
      		{
      			Start_Receiving=1;  //开始接收数据
      		}
      		else if(Start_Receiving)
      		{
      			USART_RX_BUF[Data_count++]=Data;//数据还没结束发送,就存到USART_RX_BUF[]数组中
      			if(Data=='e')
      			{
      				Start_Receiving=0;
      				Data_count=0;
      				Receive_OK=1;
      				ES=0;
      			}
      			
      		}
      		
      	}
      }
      
      /*******************************************************************************
      * 函 数 名: void Time0() interrupt 1
      * 函数功能: 定时器0中断服务函数,时钟效果
      *******************************************************************************/
      void Time0() interrupt 1
      {
      	static unsigned char flag_1,flag_2; 
      	TH0=(65536-50000)/256;  
      	TL0=(65536-50000)%256;//重新赋初值
      	
      	if(mode==0)flag_1++;  //mode为0时,数码管正常显示
      	else flag_2++;   
      	
      	if(flag_1==20 && mode==0)  //每秒执行一次
      	{
      		flag_1=0;
      		if(++Sec>=60) //++Sec先自增再判断是否大于60  
      		{
      			Sec=0;
      			if(++Min>=60)//++Min先自增再判断是否大于60
      			{
      				Min=0;
      				if(++Hour>=24)//++Hour先自增再判断是否大于60
      				{
      					Hour=0;
      				}
      			}
      		}
      	}
      	if(flag_2==9)
      	{
      		flash_tip=~flash_tip;//每4.5秒进行取反
      		flag_2=0;
      	}
      
      }

    • 您还可以看一下 刘伶华老师的软件测试经典面试题剖析课程中的 工作中有遇到什么困难,怎么解决的?小节, 巩固相关知识点
    评论

报告相同问题?

问题事件

  • 创建了问题 5月4日

悬赏问题

  • ¥15 dnat基础问题,本机发出,别人返回的包,不能命中
  • ¥15 请各位帮我看看是哪里出了问题
  • ¥15 vs2019的js智能提示
  • ¥15 关于#开发语言#的问题:FDTD建模问题图中代码没有报错,但是模型却变透明了
  • ¥15 uniapp的h5项目写一个抽奖动画
  • ¥15 hadoop中启动hive报错如下怎么解决
  • ¥15 如何优化QWebEngineView 加载url的速度
  • ¥15 关于#hadoop#的问题,请各位专家解答!
  • ¥15 如何批量抓取网站信息
  • ¥15 Spring Boot离线人脸识别