找回密码
 立即注册
楼主: wuzhengmin

第一次:环境的创立 | 送实验箱

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 4 天前 | 显示全部楼层
第十一集  《矩阵按键》



那么像这种矩阵式的按键, 它和独立按键的区别就是它的端可是可以复用的,
可以看到这里有8个按键, 如果说按照独立按键的接法, 他是不是应该接在8个10口上?但是这里可以看到他只有6个,是不是能发现他横着4个,接在一个脚上。
这里两行占了两个竖的一列,竖的1列接在了一个引脚上,对不对这里有4列,所以有4个端口,他总共用了6个端口,他就可以实现我们8个按键。如果是16个按键,他是不是只要4列加4行都可以?这种就是一个矩阵按键。



截图202508201938357332.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 3 天前 | 显示全部楼层
最大的好处在哪里呢?就是它可以用有限的端口,去实现我们更多的按键。
这个按键检测,会比这个独立按键比较慢,因为独立按键他单个端口就检测一个引脚对不对,那么这里的话他要反复的去扫描。先一列一列的扫过去,然后再一行一行的扫过去。好那我们来看一下这个原理这个矩阵按键的原理是什么呢?
按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。
①  第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一行的10就会变成低电平,就可以判断出哪一行按下了。
②  第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的10就会变成低电平,就可以判断出哪一列按下了。
③  第三步:行列组合一下就可以判断出是哪个按键按下了。


截图202508210918065730.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 3 天前 | 显示全部楼层
核心扫描代码如下:
  1. /*
  2.         #define ROW1        P06                        //端口定义
  3.         #define ROW2        P07
  4.         #define COL1        P00
  5.         #define COL2        P01
  6.         #define COL3        P02
  7.         #define COL4        P03
  8. */
  9. u8 key_num = 0xff;
  10. //任务1:数码管显示当前的按键号
  11. void Task_1(void)
  12. {
  13.         //①第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
  14.         COL1 = 0;
  15.         COL2 = 0;
  16.         COL3 = 0;
  17.         COL4 = 0;
  18.         ROW1 = 1;
  19.         ROW2 = 1;
  20.        
  21.         if(( ROW1 == 0 ) || ( ROW2 == 0 ))                //如果行按键有按下
  22.         {
  23.                 if(( ROW1 ==0 ) && ( ROW2 ==0 ))        //如果两行都有按键按下,不处理
  24.                 {
  25.                        
  26.                 }
  27.                 else if((( ROW1 ==1 )&&( ROW2 ==0 )) || (( ROW1 ==0 )&&( ROW2 ==1 )))        //如果有按键按下,而且只有一颗
  28.                 {
  29.                         if( ROW1 ==0 )                                //判断哪一行,输出行开始的序号
  30.                                 key_num = 0;
  31.                         else if( ROW2 ==0 )
  32.                                 key_num = 4;
  33.                                
  34.                         //②第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
  35.                         COL1 = 1;
  36.                         COL2 = 1;
  37.                         COL3 = 1;
  38.                         COL4 = 1;
  39.                         ROW1 = 0;
  40.                         ROW2 = 0;
  41.                        
  42.                         if( COL1 ==0 )                                //判断哪一列,叠加按键的序号
  43.                         {
  44. //                                key_num = key_num ;
  45.                         }
  46.                         else if( COL2 ==0 )
  47.                         {
  48.                                 key_num = key_num + 1;
  49.                         }
  50.                         else if( COL3 ==0 )
  51.                         {
  52.                                 key_num = key_num + 2;
  53.                         }
  54.                         else if( COL4 ==0 )
  55.                         {
  56.                                 key_num = key_num + 3;
  57.                         }
  58.                 }
  59.                 COL1 = 0;
  60.                 COL2 = 0;
  61.                 COL3 = 0;
  62.                 COL4 = 0;
  63.                 ROW1 = 1;
  64.                 ROW2 = 1;               
  65.         }
  66.         else
  67.         {
  68.                 key_num = 0xff;
  69.         }
  70.        
  71.         //③第三步:行列组合一下就可以判断出是哪个按键按下了。
  72. }
复制代码


回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 3 天前 | 显示全部楼层
实际上,虽然跟着冲哥听就觉得还可以理解,但是要自己独立的完成
任务二密码锁,还是相当困难的:

  1. void PW_write_Task(void)
  2. {
  3.         if( key_num <0xff )
  4.         {
  5.                 Key_Vol3 ++;
  6.                 if( Key_Vol3 == 5 )
  7.                 {
  8.                         if( key_no == 0 )
  9.                         {
  10.                                 passward[0] = 16;
  11.                                 passward[1] = 16;
  12.                                 passward[2] = 16;
  13.                                 passward[3] = 16;
  14.                                 passward[4] = 16;
  15.                                 passward[5] = 16;
  16.                                 passward[6] = 16;
  17.                                 passward[7] = 16;                       
  18.                         }                               
  19.                         passward[ key_no] = key_num ;
  20.                         key_no ++;
  21. //                        passward[7] = 17;       
  22.                         if( key_no == 8 )                //密码输入到了八位
  23.                         {
  24.                                 if((passward[0]==0) && (passward[1]==1) && (passward[2]==2) && (passward[3]==3) && (passward[4]==4) && (passward[5]==5) && (passward[6]==6) &&(passward[7]==7) )  
  25.                                 {
  26. //                                        passward[0] = 17;
  27. //                                        passward[1] = 17;
  28. //                                        passward[2] = 17;
  29. //                                        passward[3] = 17;
  30. //                                        passward[4] = 17;
  31. //                                        passward[5] = 17;
  32. //                                        passward[6] = 17;
  33. //                                        passward[7] = 17;       
  34.                                         passward[0] = 8;  //密码对,显示8个8
  35.                     passward[1] = 8;
  36.                     passward[2] = 8;
  37.                     passward[3] = 8;
  38.                     passward[4] = 8;
  39.                     passward[5] = 8;
  40.                     passward[6] = 8;
  41.                     passward[7] = 8;
  42.                                        
  43.                                 }
  44.                                 else
  45.                                 {
  46. //                                        passward[0] = 16;  
  47. //                                        passward[1] = 16;
  48. //                                        passward[2] = 16;
  49. //                                        passward[3] = 16;
  50. //                                        passward[4] = 16;
  51. //                                        passward[5] = 16;
  52. //                                        passward[6] = 16;
  53. //                                        passward[7] = 16;       
  54.                                         passward[0] = 14;   //密码错,显示8个E
  55.                     passward[1] = 14;
  56.                                         passward[2] = 14;
  57.                                         passward[3] = 14;
  58.                                     passward[4] = 14;
  59.                                     passward[5] = 14;
  60.                                     passward[6] = 14;
  61.                                     passward[7] = 14;
  62.                                
  63.                                
  64.                                
  65.                                 }   
  66.                                 key_no = 0;
  67.                         }      
  68.                 }           
  69.         }               
  70.         else
  71.         {
  72.                 Key_Vol3 = 0;
  73.         }
  74. }
复制代码
这部分代码和键盘扫描,其实逻辑很严密,自己估计搞不掂........
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 3 天前 | 显示全部楼层
第十二集: 系统复位:

任务1:编写看门狗程序

  1. void main(void)
  2. {
  3.         Sys_init();                                                                                //系统初始化
  4.         usb_init();                                     //USB CDC 接口配置
  5.     IE2 |= 0x80;                                    //使能USB中断
  6.         Timer0_Init();                                                                        //定时器初始化
  7.         Init_595();
  8.     EA = 1;                                                                                        //IE |= 0X80;
  9.        
  10.         P40 = 0;
  11.        
  12.         while (DeviceState != DEVSTATE_CONFIGURED);     //等待USB完成配置
  13.         WDT_CONTR = 0X24;  //启动看门狗---0.5s溢出
  14.        
  15.         while(1)
  16.         {
  17.                
  18.         if (bUsbOutReady)                                                        //如果接收到了数据
  19.         {
  20.             //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
  21.                        
  22.             usb_OUT_done();                                                        //
  23.         }
  24.                 Task_Pro_Handler_Callback();                                //执行功能函数
  25.                 if( P33 !=0 ) //人为加条件,按住P33超过0.5秒就复位!
  26. //按键P33按下超过0.5秒系统就会复位,因为在0.5秒内没有喂狗                       
  27.                 WDT_CONTR = 0X34; //喂狗清看门狗,否则系统复位
  28.         }
  29. }
复制代码




截图202508211948492595.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 3 天前 | 显示全部楼层
二、软件复位:
9.1.2 IAP 控制寄存器(IAP_CONTR)
关键函数:

  1. void KEY_Task(void)
  2. {
  3.         if( P33 == 0 )
  4.         {
  5.                 Key_Vol++;
  6.                 if( Key_Vol==5 )
  7.                 {
  8.                         //按键按下的任务
  9. //                        printf( "按键单击\r\n" );
  10.                        
  11.                         USB_Reset_U();      //USB复位
  12.                         //IAP_CONTR = 0X60;  //前提是先执行USB的复位
  13.                        
  14.                         IAP_CONTR = 0X20;  //软件复位,前提是先执行USB的复位
  15.                        
  16.                                         }
  17.         }
  18.         else
  19.         {
  20.                 Key_Vol = 0;
  21.         }
  22.        
  23. }
复制代码


截图202508211950147677.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 前天 10:12 | 显示全部楼层
13.外部中断
第十三集 外部中断   摘要
1.中断系统介绍
2.外部中断介绍
3.外部中断用法


截图202508221012523973.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 前天 10:17 | 显示全部楼层
每一个中断源可以用软件独立地控制为开中断或关中断
例子程序也好理解:
  1. //测试工作频率为11.0592MH:
  2. #include“Ai8051U.H”  //头文件见下载软件
  3. #include"intrins.h"    //使用_nop_(函数所必须要包含的头文件,
  4. //否则延时函数中调用的_nop_0函数没有被头文件引用过来,会导致编译器找不//到这个而函数而报错。
  5. Void  INT0_Isr() interrupt 0
  6. {
  7. if(P32)  / /判断上升沿和下降沿
  8. {
  9. P10=!P10;   //测试端口
  10. }
  11. else
  12. {
  13. P11=!P11; //测试端口
  14. }
  15. }
  16. void main()
  17. {
  18. EAXFR=1;//允许访问扩展的特殊寄存器•XFR
  19. //(32位模式请使用这句•注释下一句)
  20. //P_SW2|=0x80; //(8 位模式请使用这句•注释上一句)
  21.           //允许访问扩展的特殊寄存器•XFR
  22. WTST=0;    //设置取程序代码等待时间
  23.              //赋值为 0 表示不等待•程序以最快速度运行
  24. CKCON=0;   //设置访问片内的xdata速度.
  25. //赋值为 0 表示用最快速度访问•不增加额外的等待时间
  26. P0M0= 0x00;
  27. P0M1=0x00;
  28. P1M0=0x00;
  29. P1M1=0x00;
  30. P2M0=0x00;
  31. P2M1=0x00;
  32. P3M0=0x00;
  33. P3M1=0x00;
  34. P4M0=0x00;
  35. P4M1=0x00;
  36. P5M0=0x00;
  37. P5M1=0x00;
  38. IT0=0;   //使能 INT0 上升沿和下降沿中断
  39. EX0= 1;  //使能 INTO 中断
  40. EA=1;
  41. while(1);
  42. }
复制代码
很简单,好理解吧?

截图202508221014411957.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 前天 11:04 | 显示全部楼层
什么引脚能作为外部中断口?
引脚带INTx标识的!!!

其实只有4个脚可以外部中断P32 INT0  、P33INT1、P36INT2、P37INT3

截图202508221103597618.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:17
  • 最近打卡:2025-08-22 10:12:58
已绑定手机

1

主题

158

回帖

407

积分

中级会员

积分
407
发表于 前天 11:35 | 显示全部楼层
设置外部中断,很简单,只需3步:

        ① IT0 = 1;                       //下降沿中断,0是上升沿和下降沿都可以
                //外部中断0:IT0可以置0,也可以置1
                      IE0  //是中断标志,如果INT0触发了,这个标志位置1
                            //当然标志位置1是硬件自动的。

EX0 = 1; //打开中断允许,允许往后走

③EA = 1;                                  //打开总中断,执行中断
接着配置中断函数:

Void  INT0_Isr() interrupt 0  //INT0中断(上升沿和下降沿),可同时支持上升沿和下降沿
{
if(P32)  / /判断上升沿和下降沿
{
P10=!P10;   //测试端口
}
else
{
P11=!P11; //测试端口
}
}



回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-8-24 09:21 , Processed in 0.123493 second(s), 89 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表