您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 
 订阅
51单片机入门基础知识
 
作者: 王家寧
   次浏览      
 2023-12-22
 
编辑推荐:
本文讲解了51单片机入门基础知识相关内容。希望对您的学习有所帮助。
本文来自于CSDN,由火龙果软件Linda编辑、推荐。

一、单片机介绍

单片机,英文Micro Controller Unit,简称MCU

内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能

单片机的任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设备(例如电机,LED等)的控制

单片机跟计算机相比,单片机算是一个袖珍版计算机,一个芯片就能构成完整的计算机系统。但在性能上,与计算机相差甚远,但单片机成本低、体积小、结构简单,在生活和工业控制领域大有所用

同时,学习使用单片机是了解计算机原理与结构的最佳选择

51单片机是指80年代Intel开发的8051单片机内核的统称,就是因为这个“8051”有个51,所以凡是与“8051”内核一样的单片机都统称为51系列单片机

二、LED代码

2-1点亮一个LED

这里使用的普中单片机的LED是共阳极,所以将P2寄存器设置值为如下0xFE //1111 1110

  1. #include <REGX52.H>
  2. voidmain()
  3. {
  4. P2=0xFE; //1111 1110
  5. }

2-2LED循环闪烁

通过调用延时函数实现闪烁

  1. #include <REGX52.H>
  2. #include <INTRINS.H> //_nop_()函数所在库
  3. voidDelay500ms() //@11.0592MHz
  4. {
  5. unsignedchari, j, k;
  6. _nop_(); //空操作,延时一个指令的时间
  7. i=4;
  8. j=129;
  9. k=119;
  10. do
  11. {
  12. do
  13. {
  14. while (--k);
  15. } while (--j);
  16. } while (--i);
  17. }
  18. voidmain()
  19. {
  20. while(1)
  21. {
  22. P2=0x00;
  23. Delay500ms(); //这里是通过STC-ISP软件生成的延时函数调用
  24. P2=0xFF;
  25. Delay500ms();
  26. }
  27. }

 

2-3LED流水灯

通过进行P2寄存器的不断延时赋值实现流水灯-基础版

  1. #include <REGX52.H>
  2. #include <INTRINS.H> //_nop_()函数所在库
  3. voidDelay500ms() //@11.0592MHz
  4. {
  5. unsignedchari, j, k;
  6. _nop_(); //空操作,延时一个指令的时间
  7. i=4;
  8. j=129;
  9. k=119;
  10. do
  11. {
  12. do
  13. {
  14. while (--k);
  15. } while (--j);
  16. } while (--i);
  17. }
  18. voidmain()
  19. {
  20. while(1)
  21. {
  22. P2=0xFE; //1111 1110
  23. Delay500ms(); //这里是通过STC-ISP软件生成的延时函数调用
  24. P2=0xFD; //1111 1101
  25. Delay500ms();
  26. P2=0xFB; //1111 1011
  27. Delay500ms();
  28. P2=0xF7; //1111 0111
  29. Delay500ms();
  30. P2=0xEF; //1110 1111
  31. Delay500ms();
  32. P2=0xDF; //1101 1111
  33. Delay500ms();
  34. P2=0xBF; //1011 1111
  35. Delay500ms();
  36. P2=0x7F; //0111 1111
  37. Delay500ms();
  38. }
  39. }

2-4LED流水灯Plus

优化含参延时函数,但是会有一定的误差

  1. #include <REGX52.H>
  2. #include <INTRINS.H> //_nop_()函数所在库
  3. voidDelay1ms(xms) //@11.0592MHz
  4. {
  5. unsignedchari, j;
  6. while(xms)
  7. {
  8. _nop_();
  9. i=2;
  10. j=199;
  11. do
  12. {
  13. while (--j);
  14. } while (--i);
  15. xms--;
  16. }
  17. }
  18. voidmain()
  19. {
  20. while(1)
  21. {
  22. P2=0xFE; //1111 1110
  23. Delay1ms(500); //优化含参延时函数
  24. P2=0xFD; //1111 1101
  25. Delay1ms(500);
  26. P2=0xFB; //1111 1011
  27. Delay1ms(500);
  28. P2=0xF7; //1111 0111
  29. Delay1ms(500);
  30. P2=0xEF; //1110 1111
  31. Delay1ms(500);
  32. P2=0xDF; //1101 1111
  33. Delay1ms(500);
  34. P2=0xBF; //1011 1111
  35. Delay1ms(500);
  36. P2=0x7F; //0111 1111
  37. Delay1ms(500);
  38. }
  39. }

 

三、独立按键与LED

轻触按键:相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开

LED发光二极管:Light Emitting Diode

LED正极引脚较长,负极引脚较短

LED正极闪电极较小,负极闪电极较小(在玻璃灯罩里面的)

3-1独立按键控制LED亮灭

通过循环和判断实现按键控制LED亮灭功能

  1. #include <REGX52.H>
  2. voidmain()
  3. {
  4. while(1)
  5. {
  6. if(P3_1==0)
  7. P2_0=0;
  8. else
  9. P2_0=1;
  10. }
  11. }

 

3-2独立按键控制LED状态

按键的抖动

对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动

为了避免误操作,需要进行消抖处理:硬件消抖、软件消抖

硬件消抖: RS触发器、电容充放电滤波等方式

软件消抖:Delay函数延时消抖,定时消抖以及外部中断消抖

  1. #include <REGX52.H>
  2. #include <intrins.h>
  3. void Delay(unsigned int xms) //@11.0592MHz
  4. {
  5. unsigned char i, j;
  6. while(xms)
  7. {
  8. _nop_();
  9. i = 2;
  10. j = 199;
  11. do
  12. {
  13. while (--j);
  14. } while (--i);
  15. xms--;
  16. }
  17. }
  18. void main()
  19. {
  20. while(1)
  21. {
  22. if(P3_1==0)
  23. {
  24. Delay(20);
  25. while(P3_1==0); //判断是否还在按下按键,等松开时跳出循环,并延时消抖,执行相关操作
  26. Delay(20);
  27. P2_0=~P2_0;
  28. }
  29. }
  30. }

3-3独立按键控制LED显示二进制

通过二进制值的输出来让LED显示

  1. #include <REGX52.H>
  2. #include <intrins.h>
  3. void Delay(unsigned int xms) //@11.0592MHz
  4. {
  5. unsigned char i, j;
  6. while(xms--)
  7. {
  8. _nop_();
  9. i = 2;
  10. j = 199;
  11. do
  12. {
  13. while (--j);
  14. } while (--i);
  15. }
  16. }
  17. void main()
  18. {
  19. unsigned char LEDnum; //定义无符号字符变量用来存储二进制
  20. while(1)
  21. {
  22. if(P3_1==0)
  23. {
  24. Delay(20);
  25. while(P3_1==0);
  26. Delay(20);
  27. LEDnum++; //逐渐递增
  28. P2=~LEDnum; //并将二进制结果传给P2寄存器,因为LED共阳极,低电平亮,所以取反
  29. // P2_0=~P2_0; //这样不行是因为会导致P2_0值改变
  30. }
  31. }
  32. }

 

3-4独立按键控制LED移位

通过C语言移位指令以及对LEDNum变量值的控制来完成LED移位显示操作

  1. #include <REGX52.H>
  2. #include <intrins.h>
  3. void Delay(unsigned int xms) //@11.0592MHz
  4. {
  5. unsigned char i, j;
  6. while(xms--)
  7. {
  8. _nop_();
  9. i = 2;
  10. j = 199;
  11. do
  12. {
  13. while (--j);
  14. } while (--i);
  15. }
  16. }
  17. unsigned char LEDnum;
  18. void main()
  19. {
  20. while(1)
  21. {
  22. if(P3_1==0)
  23. {
  24. Delay(20);
  25. while(P3_1==0);
  26. Delay(20);
  27. LEDnum++;
  28. if(LEDnum>=8) //当到8的时候应该先清零再进行取反,不然灯会不亮
  29. LEDnum=0;
  30. P2=~(0x01<<LEDnum);
  31. }
  32. if(P3_0==0)
  33. {
  34. Delay(20);
  35. while(P3_0==0);
  36. Delay(20);
  37. if(LEDnum==0) //因为定义的是无符号字符变量,所以为了避免向下溢出,进行0值判断置7操作
  38. LEDnum=7;
  39. else
  40. LEDnum--;
  41. P2=~(0x01<<LEDnum);
  42. }
  43. }
  44. }

 

四、数码管

4-1静态数码管显示

注意若用开发板的时候不要接LCD1602显示屏,因为引脚共用原因会导致数字显示异常

  1. #include <REGX52.H>
  2. #include <intrins.h>
  3. voidDelay(unsignedintxms) //@11.0592MHz
  4. {
  5. unsignedchari, j;
  6. while(xms)
  7. {
  8. _nop_();
  9. i=2;
  10. j=199;
  11. do
  12. {
  13. while (--j);
  14. } while (--i);
  15. xms--;
  16. }
  17. }
  18. unsignedcharNixieTable[]=
  19. {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
  20. 0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; //定义数码管数组,用来存储显示对应数字时应该给寄存器赋的值
  21. voidNixie(unsignedcharLocation,Number)
  22. {
  23. switch(Location) //Location用来接收数字在哪一个数码管显示,通过三八译码器来实现数码管的选择
  24. {
  25. case1:P2_4=1;P2_3=1;P2_2=1;break;
  26. case2:P2_4=1;P2_3=1;P2_2=0;break;
  27. case3:P2_4=1;P2_3=0;P2_2=1;break;
  28. case4:P2_4=1;P2_3=0;P2_2=0;break;
  29. case5:P2_4=0;P2_3=1;P2_2=1;break;
  30. case6:P2_4=0;P2_3=1;P2_2=0;break;
  31. case7:P2_4=0;P2_3=0;P2_2=1;break;
  32. case8:P2_4=0;P2_3=0;P2_2=0;break;
  33. }
  34. P0=NixieTable[Number];
  35. }
  36. voidmain()
  37. {
  38. while(1)
  39. {
  40. Nixie(1,1); //测试数字循环显示
  41. Delay(500);
  42. Nixie(2,2);
  43. Delay(500);
  44. Nixie(3,3);
  45. Delay(500);
  46. Nixie(4,4);
  47. Delay(500);
  48. Nixie(5,5);
  49. Delay(500);
  50. Nixie(6,6);
  51. Delay(500);
  52. Nixie(7,7);
  53. Delay(500);
  54. Nixie(8,8);
  55. Delay(500);
  56. Nixie(1,9);
  57. Delay(500);
  58. Nixie(2,0);
  59. Delay(500);
  60. Nixie(3,10); //以下为ABCDEF
  61. Delay(500);
  62. Nixie(4,11);
  63. Delay(500);
  64. Nixie(5,12);
  65. Delay(500);
  66. Nixie(6,13);
  67. Delay(500);
  68. Nixie(7,14);
  69. Delay(500);
  70. Nixie(8,15);
  71. Delay(500);
  72. }
  73. }

 

4-2动态数码管显示

想要进行多个数码管同时显示,需要进行消影操作

出现串位显示的原因是因为数码管的位选和段选出现了交叉,导致串位:位选-段选-位选-段选-位选-段选

消影:位选-段选-清零-位选-段选-清零

  1. #include <REGX52.H>
  2. #include <intrins.h>
  3. voidDelay(unsignedintxms) //@11.0592MHz
  4. {
  5. unsignedchari, j;
  6. while(xms)
  7. {
  8. _nop_();
  9. i=2;
  10. j=199;
  11. do
  12. {
  13. while (--j);
  14. } while (--i);
  15. xms--;
  16. }
  17. }
  18. unsignedcharNixieTable[]=
  19. {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
  20. 0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
  21. voidNixie(unsignedcharLocation,Number)
  22. {
  23. switch(Location)
  24. {
  25. case1:P2_4=1;P2_3=1;P2_2=1;break;
  26. case2:P2_4=1;P2_3=1;P2_2=0;break;
  27. case3:P2_4=1;P2_3=0;P2_2=1;break;
  28. case4:P2_4=1;P2_3=0;P2_2=0;break;
  29. case5:P2_4=0;P2_3=1;P2_2=1;break;
  30. case6:P2_4=0;P2_3=1;P2_2=0;break;
  31. case7:P2_4=0;P2_3=0;P2_2=1;break;
  32. case8:P2_4=0;P2_3=0;P2_2=0;break;
  33. }
  34. P0=NixieTable[Number];
  35. Delay(1); //保持显示,避免变暗
  36. P0=0X00; //清零进行消影
  37. }
  38. voidmain()
  39. {
  40. while(1)
  41. {
  42. Nixie(1,1);
  43. // Delay(500); //消除延时之后,再加上消影功能就可以实现同时显示
  44. Nixie(2,2);
  45. // Delay(500);
  46. Nixie(3,3);
  47. }
  48. }

 

数码管驱动方式:

1.单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间

2.专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可

以上代码均为针对单片机直接扫描实现的,while(1)不断循环实现

五、LCD1602(模块化编程开始)

5-1模块化编程

模块化编程:

•传统方式编程:所有的函数均放在main.c里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路

•模块化编程:把各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数的声明,其它.c文件想使用其中的代码时,只需要#include "XXX.h"文件即可。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等

以Delay函数为例

  1. #include "Delay.h"
  2. voidmain()
  3. {
  4. Delay(10);
  5. }

Delay.h

  1. #ifndef __DELAY_H__
  2. #define __DELAY_H__
  3. voidDelay(unsignedintxms);
  4. #endif

Delay.c

  1. voidDelay(unsignedintxms)
  2. {
  3. unsignedchari, j;
  4. while(xms--)
  5. {
  6. i=2;
  7. j=239;
  8. do
  9. {
  10. while (--j);
  11. } while (--i);
  12. }
  13. }

图示

模块化实现数码管显示

  1. #include <REGX52.H>
  2. #include "Delay.h"
  3. #include "Nixie.h"
  4. voidmain()
  5. {
  6. while(1)
  7. {
  8. Nixie(1,1);
  9. // Delay(500);
  10. Nixie(2,2);
  11. // Delay(500);
  12. Nixie(3,3);
  13. Nixie(4,4);
  14. Nixie(5,5);
  15. }
  16. }

Delay.h

  1. #ifndef __DELAY_H__
  2. #define __DELAY_H__
  3. void Delay(unsigned int xms);
  4. #endif

 

Nixie.h

  1. #ifndef __NIXIE_H__
  2. #define __NIXIE_H__
  3. void Nixie(unsigned char Location,Number);
  4. #endif

Delay.c

  1. #include <intrins.h>
  2. void Delay(unsigned int xms) //@11.0592MHz
  3. {
  4. unsigned char i, j;
  5. while(xms)
  6. {
  7. _nop_();
  8. i = 2;
  9. j = 199;
  10. do
  11. {
  12. while (--j);
  13. } while (--i);
  14. xms--;
  15. }
  16. }

Nixie.c

  1. #include "Delay.h"
  2. #include <REGX52.H>
  3. unsigned char NixieTable[]=
  4. {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
  5. 0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
  6. void Nixie(unsigned char Location,Number)
  7. {
  8. switch(Location)
  9. {
  10. case 1:P2_4=1;P2_3=1;P2_2=1;break;
  11. case 2:P2_4=1;P2_3=1;P2_2=0;break;
  12. case 3:P2_4=1;P2_3=0;P2_2=1;break;
  13. case 4:P2_4=1;P2_3=0;P2_2=0;break;
  14. case 5:P2_4=0;P2_3=1;P2_2=1;break;
  15. case 6:P2_4=0;P2_3=1;P2_2=0;break;
  16. case 7:P2_4=0;P2_3=0;P2_2=1;break;
  17. case 8:P2_4=0;P2_3=0;P2_2=0;break;
  18. }
  19. P0=NixieTable[Number];
  20. Delay(1);
  21. P0=0X00;
  22. }

 

5-2LCD1602调试工具*

LCD1602调试函数模块

不同的LCD1602调试函数代码决定了不同的调试函数以及使用方法

使用时应注意对应的文件函数的异同

函数

作用

LCD_Init();

初始化

LCD_ShowChar(1,1,'A');

显示一个字符

LCD_ShowString(1,3,"Hello");

显示字符串

LCD_ShowNum(1,9,123,3);

显示十进制数字

LCD_ShowSignedNum(1,13,-66,2);

显示有符号十进制数字

LCD_ShowHexNum(2,1,0xA8,2);

显示十六进制数字

LCD_ShowBinNum(2,4,0xAA,8);

显示二进制数字

代码暂略,等后续对头文件以及源代码进行全方面分析之后再复盘补充

六、矩阵键盘

6-1矩阵键盘*

涉及到了施密特触发电路和上拉电阻和下拉电阻,等模电再学一学复盘一下

这里同样使用了前面的LCD1602的调试文件:LCD1602.H、LCD1602.C

编译时会出现WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS的报错,是因为引用的LCD1602的文件中的函数虽然定义了,但是并没有在程序中显式调用到定义过的函数,可以无视,但是会浪费RAM

main.c

  1. #include "DELAY.H"
  2. #include "lcd1602.h"
  3. #include "Delay.h"
  4. #include "MatrixKey.h"
  5. unsignedcharKeyNum; //定义无符号整型用来接收键码
  6. voidmain()
  7. {
  8. lcd1602_init(); //初始化LCD1602
  9. lcd1602_show_string(0,0,"MatrixKey:");//在第一列第一行显示MatrixKey:
  10. while(1)
  11. {
  12. KeyNum=MatrixKey(); //调用函数接收键码
  13. if(KeyNum) //接受到键码则判断键码值并显示
  14. {
  15. switch(KeyNum)
  16. {
  17. case1: lcd1602_show_string(0,1,"1");break;
  18. case2: lcd1602_show_string(0,1,"2");break;
  19. case3: lcd1602_show_string(0,1,"3");break;
  20. case4: lcd1602_show_string(0,1,"4");break;
  21. case5: lcd1602_show_string(0,1,"5");break;
  22. case6: lcd1602_show_string(0,1,"6");break;
  23. case7: lcd1602_show_string(0,1,"7");break;
  24. case8: lcd1602_show_string(0,1,"8");break;
  25. case9: lcd1602_show_string(0,1,"9");break;
  26. case10: lcd1602_show_string(0,1,"10");break;
  27. case11: lcd1602_show_string(0,1,"11");break;
  28. case12: lcd1602_show_string(0,1,"12");break;
  29. case13: lcd1602_show_string(0,1,"13");break;
  30. case14: lcd1602_show_string(0,1,"14");break;
  31. case15: lcd1602_show_string(0,1,"15");break;
  32. case16: lcd1602_show_string(0,1,"16");break;
  33. }
  34. }
  35. }
  36. }

 

MatrixKey.h

  1. #ifndef __MATRIXKEY_H__
  2. #define __MATRIXKEY_H__
  3. unsigned char MatrixKey();
  4. #endif

 

MatrixKey.c

  1. #include <REGX52.H>
  2. #include "Delay.h"
  3. unsignedcharMatrixKey()
  4. {
  5. unsignedcharKeyNumber=0;
  6. P1=0xff; // 全部拉高
  7. P1_3=0; //单独留一个低电位进行扫描按键
  8. if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
  9. if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
  10. if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
  11. if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
  12. P1=0xff; // 全部拉高
  13. P1_2=0; //单独留一个低电位进行扫描按键
  14. if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
  15. if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
  16. if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
  17. if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
  18. P1=0xff; // 全部拉高
  19. P1_1=0; //单独留一个低电位进行扫描按键
  20. if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
  21. if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
  22. if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
  23. if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
  24. P1=0xff; // 全部拉高
  25. P1_0=0; //单独留一个低电位进行扫描按键
  26. if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
  27. if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
  28. if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
  29. if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
  30. returnKeyNumber;
  31. }

 

6-2矩阵键盘密码锁

所使用的前述模块化列表

LCD1602

Delay

MatrixKey

  1. #include "lcd1602.h"
  2. #include "Delay.h"
  3. #include "MatrixKey.h"
  4. unsignedcharKeyNum; //定义KeyNum用于接收键码值
  5. unsignedintPassword,Count; //定义无符号整型用于存储 密码值 和 密码位数
  6. voidmain()
  7. {
  8. LCD_Init();
  9. LCD_ShowString(0,1,"Password:");
  10. while(1)
  11. {
  12. KeyNum=MatrixKey();
  13. if(KeyNum)
  14. {
  15. if(KeyNum<=10) //如果S1~S10按键按下,输入密码
  16. {
  17. if(Count<4) //如果位数不超过设定范围
  18. {
  19. Password*=10; //向左移动一位
  20. Password+=KeyNum%10; //累加密码
  21. Count++; //计次加一,确保四位
  22. }
  23. LCD_ShowNum(1,1,Password,4); //更新显示
  24. }
  25. if(KeyNum==11) //确认键
  26. {
  27. if(Password==2345) //设定密码为2345
  28. {
  29. LCD_ShowString(1,14,"OK!");
  30. Password=0; //密码清零
  31. Count=0; //计次清零
  32. LCD_ShowNum(1,1,Password,4); //更新显示
  33. }
  34. else
  35. {
  36. LCD_ShowString(1,14,"ERR");
  37. Password=0; //密码清零
  38. Count=0; //计次清零
  39. LCD_ShowNum(1,1,Password,4); //更新显示
  40. }
  41. }
  42. if(KeyNum==12) //删除键
  43. {
  44. Password=Password/10; //删除数字
  45. LCD_ShowNum(1,1,Password,4); //更新显示
  46. Count--; //计次减少
  47. }
  48. }
  49. }
  50. }

七、定时器

7-1定时器

定时器介绍:

51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成

定时器作用:

(1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作

(2)替代长时间的Delay,提高CPU的运行效率和处理速度

(3)多任务处理

(…)

STC89C52定时器资源

•定时器个数:3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源

•注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的

定时器框图

定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔“一秒”,计数单元的数值就增加一,当计数单元数值增加到“设定的闹钟提醒时间”时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行

定时器工作模式

STC89C52的T0和T1均有四种工作模式:

工作模式1(16位定时器/计数器)框图:

SYSclk:系统时钟,用来产生固定频率的脉冲(晶振电路)来使后面的计数器的技术值累加,此时作定时器使用,

MCU in 12T/6T mode:分频模式,例如当晶振频率为12MHz,采用MCU in 12T mode时,产生的脉冲频率就是1MHz

T0 Pin:外部接口,当由外部接口来提供脉冲时,作计数器使用

C/T非:配置寄存器时若其对应的控制字为1,则为Count计数器模式,为0,则为Time定时器模式

TH0和TL0:Time High 0和Time Low 0,代表了定时器的高位和低位,后面的0表示计时器0,计数器共十六位,最大计数值为65535

TF0:Time Flag 0,表示计时器0的标志位,当达到最大技术值后,下一次计数就会溢出,产生脉冲传送到标志位从而影响后面的Interrupt,从而申请中断。

 

   
次浏览       
相关文章

一文了解汽车嵌入式AUTOSAR架构
嵌入式Linux系统移植的四大步骤
嵌入式中设计模式的艺术
嵌入式软件架构设计 模块化 & 分层设计
相关文档

企点嵌入式PHP的探索实践
ARM与STM简介
ARM架构详解
华为鸿蒙深度研究
相关课程

嵌入式C高质量编程
嵌入式操作系统组件及BSP裁剪与测试
基于VxWorks的嵌入式开发、调试与测试
嵌入式单元测试最佳实践

最新活动计划
C++高级编程 12-25 [线上]
白盒测试技术与工具实践 12-24[线上]
LLM大模型应用与项目构建 12-26[特惠]
需求分析最佳实践与沙盘演练 1-6[线上]
SysML建模专家 1-16[北京]
UAF架构体系与实践 1-22[北京]
 
 
最新文章
基于FPGA的异构计算在多媒体中的应用
深入Linux内核架构——简介与概述
Linux内核系统架构介绍
浅析嵌入式C优化技巧
进程间通信(IPC)介绍
最新课程
嵌入式Linux驱动开发
代码整洁之道-态度、技艺与习惯
嵌入式软件测试
嵌入式C高质量编程
嵌入式软件可靠性设计
成功案例
某军工所 嵌入式软件架构
中航工业某研究所 嵌入式软件开发指南
某轨道交通 嵌入式软件高级设计实践
深圳 嵌入式软件架构设计—高级实践
某企业 基于IPD的嵌入式软件开发
更多...