首页 > 其他分享 >51按键外部中断控制流水灯

51按键外部中断控制流水灯

时间:2023-06-08 23:34:53浏览次数:32  
标签:P1 中断 flow void 51 流水 按键 include


实验二 外部按键输入

一、实验目的

1、了解单片机检测口方法

2、了解单片机外部中断原理

3、了解按键输入原理

二、实验内容

1、完成按键扫描控制流水灯

2、完成按键外部中断控制流水灯

三、实验原理

51按键外部中断控制流水灯_子程序

四、实验电路与程序

1、软件实验一:按键扫描控制流水灯

1)实验要求:读取四个按键的输入,检测到按下后控制灯流动一段时间,然后继续读取按键输入。

2)实验目的:1. 掌握按键消抖方法;2. 掌握单片机端口检测方法

3)实验说明:通过本实验,可以了解单片机读取IO口电平的方法,同时也可以了解单片机编程,调试方法。

4)、程序框图

51按键外部中断控制流水灯_#include_02

5)、代码
 main.c1. #include <reg52.h>
2. #include <key.h>
3. 
4. void main(void)
5. {
6. unsigned char key_val;
7. P1=0xFF;
8. while(1)
9. {
10. key_val=key_scan();//扫描键盘
11. light_led(key_val);//选择不同的点灯方式
12. }
13. }
key.h14. #ifndef _KEY_H
15. #define _KEY_H
16. #include <reg52.h>
17. void delay(unsigned int z);
18. unsigned char key_scan(void);
19. void light_led(unsigned char mode);
20. void flow_forward(void);
21. void flow_back(void);
22. void light_all(void);
23. void dark_all(void);
24. #endif
key.c25. #include <key.h>
26. unsigned char key_scan(void)
27. {
28. while(P3==0x0f)//等待按键按下
29. {
30. ;
31. }
32. delay(10);//软件消抖
33. switch (P3)
34. {
35. case 0xFE: return 0;//判断是哪个按键按下
36. case 0xFD: return 1;
37. case 0xFB: return 2;
38. case 0xF7: return 3;
39. }
40. 
41. 
42. }
43. 
44. 
45. void flow_forward(void)
46. {
47. int i=0;
48. P1=0xFE;
49. for(i=0;i<8;i++)
50. {
51. delay(500);
52. P1=(P1<<1)|(P1>>7);//循环左移1位
53. }
54. 
55. }
56. void flow_back(void)
57. {
58. int i=0;
59. P1=0xFE;
60. for(i=0;i<8;i++)
61. {
62. delay(500);
63. P1=(P1>>1)|(P1<<7);//循环右移1位
64. }
65. }
66. void light_all(void)//点亮所有灯
67. {
68. P1=0
  1. ;
1. }
2. 
3. void dark_all(void)//熄灭所有灯
4. {
5. P1=1;
6. }
7. 
8. void light_led(unsigned char mode)
9. {
10. switch (mode)
11. {
12. case 0:dark_all();//灯全灭
13. break;
14. case 1:light_all();//灯全亮
15. break;
16. case 2:flow_forward();//流水灯正流
17. break;
18. case 3:flow_back();//流水灯反流
19. 
20. }
21. }

2、软件实验二:按键外部中断控制流水灯

1)实验要求:按键1按下时流水灯正流,按键0按下时流水灯反流。

2)实验目的:1. 掌握中断服务子程序的编写方法; 2. 掌握定时器中断的配置方法。

3)实验说明:通过本实验,可以了解单片机掌握中断服务子程序的编写方法和定时器中断的配置方法,同时也可以了解单片机编程,调试方法。

4)、程序框图

51按键外部中断控制流水灯_子程序_03

5)、代码

汇编代码
1. ORG 0000H ;程序执行的起始地址
2. LJMP Main ;跳转到main函数
3. 
4. ORG 0003H ;外部中断0起始地址
5. LJMP 0100H ;外部中断0服务子程序地址
6. ORG 0013H ;外部中断1起始地址
7. LJMP 0200H ;外部中断1服务子程序地址
8. 
9. Main: ;主函数
10. MOV IE, #10000101B ;置位EA,EX1,EX0
11. MOV TCON, #00000000B ;外部中断0和1都是低电平触发
12. 
13. LOOP: JMP LOOP ;while(1)死循环
14. 
15. ORG 0100H ;外部中断0服务子程序
16. EXT0:
17. CALL DELAY1 ;短延时,按键消抖
18. MOV R3, #32 ;灯流4次
19. MOV A, #0FEH
20. EXT0L: MOV P1, A ;P1口赋值
21. RR A ;循环右移一位
22. CALL DELAY
23. DJNZ R3, EXT0L
24. RETI ;中断返回
25. 
26. ORG 0200H ;外部中断1服务子程序
27. EXT1:
28. CALL DELAY1 ;短延时,按键消抖
29. MOV R3, #32 ;灯流4次
30. MOV A, #0FEH
31. EXT1L: MOV P1, A ;P1口赋值
32. RL A ;循环左移一位
33. CALL DELAY
34. DJNZ R3, EXT1L
35. RETI ;中断返回
36. 
37. DELAY: MOV R1, #200 ;执行200*200个跳转
38. DELAY1: MOV R2, #200
39. DELAY2: DJNZ R2, DELAY2
40. DJNZ R1, DELAY1
41. RET
42. 
43. 
44. END
C程序代码
 main.c1. #include <reg52.h>
2. #include <key.h>
3. #include <interrupt.h>
4. int task_flag;
5. int timer_flag;
6. void main()
7. {

8. Config_EXTI();//初始化外部中断
9. Config_Timer();//初始化定时器
10. P1=0xFE;//初始化GPIO
11. while(1)//任务调度器
12. {

13. if(timer_flag)//每1000ms执行一次任务
14. {

15. timer_flag=0;
16. switch (task_flag)//判断执行哪个任务
17. {

case 1 :flow_forward();//流水灯正流break;case 2 :flow_back();//流水灯反流break;1. }
2. }
3. }
4. }
interrupt.h
1. #ifndef _INTERRUPT_H
2. #define _INTERRUPT_H
3. #include <reg52.h>
4. #include <key.h>
5. void delay(unsigned int z);
6. void Config_EXTI(void);
7. void Config_Timer(void);
8. extern int task_flag;
9. extern int timer_flag;
10. #endif
interrupt.c
1. #include <interrupt.h>
2. void delay(unsigned int z)//延时ms
3. {

unsigned int x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);1. }
2. void Config_Timer(void)
3. {

TMOD=0x01;//设置定时器0为工作方式1(M1 M0为01),是向上计数TH0=(65536-45872)/256;//装初值11.0582晶振定时50ms数为45872,高位TL0=(65536-45872)%256;//低位EA=1;//开总中断ET0=1;//开定时器0中断TR0=1;//启动定时器01. }
2. 
3. void Config_EXTI(void)
4. {

5. EA=1;//开中断总允许
6. IT0=1;//下降沿触发外部中断0
7. EX0=1;//开外部中断0
8. IT1=1;//下降沿触发外部中断1
9. EX1=1;//开外部中断1
10. }
11. 
12. void EXT0_Handle() interrupt 0
13. {

delay(10);task_flag=1;//开启正向流水灯任务1. }
2. 
3. void EXT1_Handle() interrupt 2
4. {

delay(10);task_flag=2;//开启反向流水灯任务1. }
2. 
3. void T0_Handle() interrupt 1
4. {

static int num=0;TMOD=0x01;//重装初值TH0=(65536-45872)/256;//高位TL0=(65536-45872)%256;//低位1. 
if(num<20)//每1000ms把timer_flag置位{num++;}else{num=0;timer_flag=~timer_flag;}1. }
key.h
1. #ifndef _KEY_H
2. #define _KEY_H
3. #include <reg52.h>
4. unsigned char key_scan(void);
5. void flow_forward(void);
6. void flow_back(void);
7. #endif
key.c
1. #include <key.h>
2. 
3. void flow_forward(void)
4. {

5. P1=(P1<<1)|(P1>>7);//循环左移1位
6. }
7. void flow_back(void)
8. {

9. 
10. P1=(P1>>1)|(P1<<7);//循环右移1位
11. 
12. }

  1. 五、实验总结
  2. 在键盘扫描程序中,卡的比较久时间的是点灯。后面发现不同的开发板,灯的位置不一样。第二个卡的比较久的地方是判断P3口时,没有考虑到高四位的情况,考虑进去之后,switch p3就正常了。
    2.设计键盘外部中断的时候,考虑到如果把流水灯放在中断回调函数里面进行的话,会导致执行回调函数的时候,别的中断来了会很麻烦。于是改为在回调函数里面设置标志位,while(1)里面根据标志位来选择执行哪个点灯代码。但是流水灯需要延时,如果用跑空循环来作延时的话,有点像是阻塞型任务,别的中断来的时候,中断套中断,就很麻烦。于是就开了一个定时器,定时器中断里面设置一个flag,每1秒钟flag置位一下,然后去看看要不要切换任务,以及执行哪个任务。这样子就给单片机节省出大量的资源来了。
  3. 汇编代码比较遗憾的地方是没有加进定时器中断,delay用跑空循环实现。


标签:P1,中断,flow,void,51,流水,按键,include
From: https://blog.51cto.com/u_16131692/6444232

相关文章

  • 51定时器中断控制流水灯
    一、实验目的1、了解读取和清零定时器标志位的方法。2、了解定时器中断的方法。3、了解定时器初始化设置的方法。二、实验内容1、完成读取定时器溢出标志位来控制流水灯2、完成定时器中断服务函数控制流水灯三、实验原理只用一个定时器:定时器级联:四、实验电路与程序1、软......
  • 16-流水灯
    1.流水灯利用板载的LED灯进行流水灯的设计,让LED灯依次进行点亮,像流水一样,原理就是依次控制LED灯的IO口的高低电平的变化,让LED灯一次2.FPGA设计2.1模块框图和波形本次的实验是让led灯依次闪亮的间隔为0.5s,也就是让led灯每次只亮一个,每次亮的时间为0.5s,这样就速度就比较......
  • Codeforces 1514 C
    1514C题意给出一个数n,求[1,2,3...n-1]的某个最长子序列,这个子序列的元素乘积模n余1。思路这是个思维题,一个数学公式\[x\equiv1(modn)\rightarrowkx\equivk(mod kn)\]所以子序列中的元素与\(n\)互质,累乘结果模\(n\)后如果不是1,那么将序列中等于结果的元素去......
  • Codeforces 1515 B
    1515B题意有n只袜子(n为偶数),但左袜子有L只,右袜子有R只,每只袜子的颜色为\(C_i\),可以进行以下操作:换袜子的方向、或者将袜子变色,问进行多少次操作后变成(n/2)对袜子思路很曲折,想了很久后终于想清楚,排除配对的袜子后,对于某类袜子\(i\),剩下\(c\geq2\)(假设剩下的是右边)只,它的配对......
  • ASEMI代理英飞凌TDK5100F射频模块的性能与应用分析
    编辑-Z本文将对TDK5100F射频模块进行详细的介绍与分析,包括其性能特点、应用领域、使用方法。通过对这三个方面的阐述,希望能够帮助读者更好地了解TDK5100F射频模块的优势和应用场景。 1、TDK5100F射频模块的性能特点TDK5100F射频模块是一款高性能的无线通信模块,具有以下几个显著的......
  • ASEMI代理英飞凌TDK5100F射频模块的性能与应用分析
    编辑-Z本文将对TDK5100F射频模块进行详细的介绍与分析,包括其性能特点、应用领域、使用方法。通过对这三个方面的阐述,希望能够帮助读者更好地了解TDK5100F射频模块的优势和应用场景。 1、TDK5100F射频模块的性能特点TDK5100F射频模块是一款高性能的无线通信模块,具有以下几个显......
  • [LeetCode] 1351. Count Negative Numbers in a Sorted Matrix
    Givena mxn matrix grid whichissortedinnon-increasingorderbothrow-wiseandcolumn-wise,return thenumberof negative numbersin grid.Example1:Input:grid=[[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]Output:8Explanation:Thereare......
  • P1751 贪吃虫 题解
    题意:题目传送门在一棵n个结点的树上,有k个贪吃虫去吃食物。每个贪吃虫都走到达食物的唯一路径。当一条贪吃虫通向食物的道路上有另一条贪吃虫,则较远的那只停止移动。多条贪吃虫要进入同一节点时,编号最小的才能进入,其他的停止移动。贪吃虫的移动速度皆为1。一只贪吃虫吃......
  • 算法学习day51动态规划part12-309、714
    packageLeetCode.DPpart12;/***309.最佳买卖股票时机含冷冻期*给定一个整数数组prices,其中第prices[i]表示第i天的股票价格。*设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):*卖出股票后,你无法在第二天买入......
  • GitOps 最佳实践(上)| 基于 Amazon EKS 构建 CI/CD 流水线
    GitOps是目前比较理想的方法来实现基于Kuberentes集群的持续部署。了解了 GitOps的概念以及CI/CD流水线的架构,接下来我们将通过以下四个模块逐步完成构建CI/CD流水线的最佳实践:通过IaC部署云基础架构;在AmazonEKS集群上部署FluxCD;利用FluxCD部署GitOps工......