• 51单片机—智能垃圾桶(定时器)


    一. 定时器

    1. 简介

    C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器或者计数器使用。

    确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时,每经过1个机器周期,计数存储器的值就加1。而当配置为计数器时,每来一个负跳变信号(信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。

    标准C51有2个定时器/计数器:T0和T1。他们的使用方法一致。C52相比C51多了一个T2

    1.1 概念解读
    • 定时器和计数器,电路一样
    • 定时或者计数的本质就是让单片机某个部件数数
    • 当定时器用的时候,靠内部震荡电路数数
    • 当计数器用的时候,数外面的信号,读取针脚的数据

    在51单片机中,定时器和计数器的主要区别在于它们的工作方式和用途:

    • 定时器(Timer)
      • 工作方式:定时器使用内部时钟源(例如晶振)进行计数。
      • 用途:用于计时,例如生成精确的时间延迟、实现周期性中断等。
      • 例子:设定一个定时器来每隔一秒触发一次中断,用于更新系统时钟。
    • 计数器(Counter)
      • 工作方式:计数器通过外部信号(例如外部引脚上的脉冲信号)进行计数。
      • 用途:用于计数外部事件或脉冲,例如计数输入脉冲的次数。
      • 例子:连接一个传感器到单片机的计数器引脚,计数传感器发出的脉冲信号。
    1.2 定时器怎么定时

    定时器的本质原理: 每经过一个机器周期,就加1 :寄存器

    思考:

    • 什么是晶振

    晶振(晶体震荡器),又称数字电路的“心脏”,是各种电子产品里面必不可少的频率元器件。数字电

    路的所有工作都离不开时钟,晶振的好坏、晶振电路设计的好坏,会影响到整个系统的稳

    • 什么是时钟周期

    时钟周期也称为振荡周期,定义为时钟频率的倒数。时钟周期是计算机中最基本的、最小的时间单

    位。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。更小的时钟周

    期就意味着更高的工作频率

    • 什么是机器周期

    机器周期也称为CPU周期。在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶

    段(如取指、译码、执行等),每一阶段完成一个基本操作。完成一个基本操作所需要的时间称为

    机器周期。一般情况下,一个机器周期由若干个时钟周期组成

    • 加1经过了多少时间

    当晶振频率是11.0592MHz的时候,等于11059.2KHz = 11059200Hz

    跳一次等于一个机器周期

    一个机器周期等于12个时钟周期

    一个时钟周期等于晶振的倒数:1/11059200秒

    那么跳一次就是:12/11059200秒 = 12000000/11059200 微秒= 1.085微妙

    机器周期 = 12 x 时钟周期

    = 12 x (1/时钟频率) 秒 = 12 / 时钟频率 秒 = 12 / 11059200 秒 = 12 000 000 / 11059200 微秒 = 1.085 微秒

    1.3 定时器编程

    相关寄存器:

    • 在哪里加1,最大计数时间,也就是爆表了能计算多长

    在T8H0/1和TL0/1寄存器中加1,默认是从0开始数数,最多能数65536下,累计计时71ms ,71毫秒

    • 如何算出10ms定时器的初值

    就不让他从0开始数数,10ms需要数9216下,你让他从65536-9126=56320(16进制表示为

    0xDC00)开始数数

    这样TL0=0x00;TH0=0xDC

    • 关于TCON

    • 怎么知道爆表

    TCON寄存器的bit5(TF0)能表示爆表:当爆表的时候,硬件会修改bit5(TF0)位上面的数据,改成 1(置1),如果不用中断,我们代码清零。

    • 怎么开始计时

    TCON寄存器的bit4,TRO通过编程让这个位为1的时候,开始计时,相当于按下了闹钟

    • 定时器使用是有很多种模式的

    定时器模式寄存器:TMOD来选择定时器模式,选择工作方式1,TMOD的bit0 bit1配置成0 1 :16 位的定时器功能

    • 四个二进制数表示一位的16进制数

    8421法进制的转换,二进制转16进制(方便人类来看,对计算机底层来说,不关心二进制010101010)。

    配寄存器推荐用按位操作,清零的时候,对应的需要清零的位与上0,不需要清零的位与上1

    置1的时候,需要置1的位置或1,不需要置一的位置或0

    AUXR,降低单片机时钟对外界的辐射。

    • 定时器控制led灯每隔一秒灭一次
    1. #include "reg52.h"
    2. sbit led1 = P3^6; // 定义 led1 变量,指向 P3.6 引脚
    3. sbit led2 = P3^7; // 定义 led2 变量,指向 P3.7 引脚
    4. void main()
    5. {
    6. // 1.配置定时器0工作模式为16位计数器模式
    7. int cnt = 0; // 定义一个整数变量 'cnt' 用于计数
    8. led1 = 1; // 初始化 led1 为高电平(假设高电平点亮)
    9. led2 = 0; // 初始化 led2 为低电平(假设低电平熄灭)
    10. TMOD = 0x01; // 配置定时器0为模式116位定时器模式)
    11. // 2.设置定时器初值,使其每10ms产生一次溢出
    12. TL0 = 0x00; // 设置定时器08位初值为 0x00
    13. TH0 = 0xDC; // 设置定时器08位初值为 0xDC
    14. // 3.启动计时
    15. TR0 = 1; // 启动定时器0
    16. TF0 = 0; // 清除定时器0溢出标志位
    17. while(1) { // 无限循环
    18. if(TF0 == 1) { // 如果定时器0溢出 爆表
    19. TF0 = 0; // 清除定时器0溢出标志位
    20. cnt++; // 增加计数器 'cnt' 的值
    21. // 重新设置定时器初值
    22. TL0 = 0x00;
    23. TH0 = 0xDC;
    24. if(cnt == 100) { // 如果计数器 'cnt' 达到 100(即经过1秒)
    25. cnt = 0; // 重置计数器 'cnt'
    26. led1 = !led1; // 翻转 led1 的状态
    27. led2 = !led2; // 翻转 led2 的状态
    28. }
    29. }
    30. }
    31. }

    1.4 定时器中断方式控制 (相当于多线程)

    中断寄存器

    • 定时器中断方式控制led
    1. #include "reg52.h" // 包含51系列单片机寄存器定义文件
    2. sbit led = P3^6; // 定义一个位变量led,连接到P3端口的第6位(LED1
    3. sbit led1 = P3^7; // 定义一个位变量led1,连接到P3端口的第7位(LED2
    4. int cnt = 0; // 定义一个整数变量cnt,用来统计定时器溢出的次数
    5. // 定义定时器0初始化函数
    6. void Time0Init()
    7. {
    8. // 1. 配置定时器0工作模式为16位计时模式
    9. TMOD = 0x01; // 设置TMOD寄存器为0x01,定时器016位定时器模式
    10. // 2. 设置定时器初值,以生成大约10ms的定时
    11. TL0 = 0x00; // 设置定时器08位初值为0x00
    12. TH0 = 0xDC; // 设置定时器08位初值为0xDC(即0xDC00
    13. // 3. 启动定时器0
    14. TR0 = 1; // 启动定时器0,使其开始计时
    15. TF0 = 0; // 清除定时器0的溢出标志位(初始为0
    16. // 4. 启用定时器0中断
    17. ET0 = 1; // 使能定时器0中断,使单片机能够响应定时器0的中断请求
    18. // 5. 启用总中断
    19. EA = 1; // 启用全局中断,使单片机能够响应所有中断请求
    20. }
    21. void main()
    22. {
    23. led = 1; // 将LED1点亮(即将P3^6置为高电平)
    24. led1 = 0; // 将LED2熄灭(即将P3^7置为低电平)
    25. Time0Init(); // 调用定时器初始化函数,设置定时器0并启动定时器
    26. while(1) {
    27. // 无限循环,程序在这里等待中断事件发生
    28. // 这部分代码可以执行其他任务,但本例中为空
    29. }
    30. }
    31. // 定时器0中断处理函数 interrupt 1 定时器0的优先级
    32. void Time0Handler() interrupt 1
    33. {
    34. cnt++; // 每次定时器0溢出时,计数器cnt增加1
    35. // 重新设置定时器0的初值,保持定时周期不变
    36. TL0 = 0x00; // 重新加载定时器08位初值为0x00
    37. TH0 = 0xDC; // 重新加载定时器08位初值为0xDC(即0xDC00
    38. if (cnt == 30) { // 如果定时器0溢出30次(约300ms)
    39. cnt = 0; // 重置计数器cnt为0
    40. // 翻转LED的状态
    41. led = !led; //300ms翻转LED1的状态
    42. led1 = !led1; //300ms翻转LED2的状态
    43. }
    44. }

    这段代码是用来在51系列单片机中配置定时器0,使其每隔1秒钟翻转一个LED的状态。下面是对每一部分的详细解释:

    1. 头文件和变量定义
    1. #include "reg52.h"
    2. sbit led = P3^6; // 定义一个位变量led,连接到P3端口的第6位(LED1
    3. sbit led1 = P3^7; // 定义一个位变量led1,连接到P3端口的第7位(LED2
    4. int cnt = 0; // 定义一个整数变量cnt,用来统计定时器溢出次数
    • #include "reg52.h":包含51系列单片机的寄存器定义文件。
    • sbit led = P3^6;:将单片机的P3端口的第6位定义为 led,用于控制LED的开关。
    • sbit led1 = P3^7;:将P3端口的第7位定义为 led1,虽然在代码中没有使用。
    • int cnt = 0;:定义一个计数器 cnt,用于跟踪定时器0的溢出次数。
    2. Time0Init 函数
    1. void Time0Init()
    2. {
    3. //1. 配置定时器0工作模式位16位计时
    4. TMOD = 0x01;
    5. //2. 给初值,定一个10ms出来
    6. TL0=0x00;
    7. TH0=0xDC;
    8. //3. 开始计时
    9. TR0 = 1;
    10. TF0 = 0;
    11. //4. 打开定时器0中断
    12. ET0 = 1;
    13. //5. 打开总中断EA
    14. EA = 1;
    15. }
    • TMOD = 0x01;:将 TMOD 寄存器的值设置为 0x01,将定时器0配置为模式1(16位定时器模式)。低4位 0001 表示定时器0的工作模式。
    • TL0 = 0x00;TH0 = 0xDC;:设置定时器0的初始值。TH0TL0 设置为 0xDC00,这样定时器从 0xDC00 开始计数。
    • TR0 = 1;:启动定时器0。
    • TF0 = 0;:清除定时器0的溢出标志位。
    • ET0 = 1;:允许定时器0的中断。
    • EA = 1;:允许总中断,使单片机能够响应所有中断请求。
    3. main 函数
    1. void main()
    2. {
    3. led = 1; // 初始时点亮LED
    4. Time0Init(); // 初始化定时器0
    5. while(1){
    6. // 无限循环,等待中断发生
    7. }
    8. }
    • led = 1;:在程序开始时,将 led 设为1,点亮LED。
    • Time0Init();:调用初始化定时器0的函数。
    • while(1){}:无限循环,程序在这里等待中断事件发生。实际的操作由中断处理函数完成。
    4. 定时器0中断处理函数
    1. void Time0Handler() interrupt 1
    2. {
    3. cnt++; // 统计溢出次数
    4. // 重新设置定时器初值
    5. TL0=0x00;
    6. TH0=0xDC;
    7. if(cnt == 100) { //100次溢出表示1
    8. cnt = 0; // 重置计数器
    9. led = !led; // 翻转LED状态
    10. }
    11. }
    • void Time0Handler() interrupt 1:定义了一个中断服务函数,用于处理定时器0的中断。interrupt 1 表示这是定时器0的中断处理函数。
    • cnt++;:每次定时器0溢出时,计数器 cnt 增加1。
    • TL0 = 0x00;TH0 = 0xDC;:重新加载定时器初值,保持定时器周期不变。
    • if(cnt == 100):检查 cnt 是否达到100。每100次溢出表示1秒(因为10毫秒 × 100 = 1000毫秒,即1秒)。
      • cnt = 0;:重置 cnt 以开始新的计时周期。
      • led = !led;:每秒钟翻转LED的状态。
    总结
    • 初始化Time0Init 函数设置定时器0的工作模式和初值,并开启定时器中断。
    • 主程序main 函数设置LED初始状态,并无限循环等待中断。
    • 中断处理Time0Handler 函数在每次定时器0溢出时执行,统计溢出次数,并每1秒翻转一次LED的状态。

    • 定时器中断方式控制led,led灯多线程 控制
    1. #include "reg52.h"
    2. // 定义LED控制的位变量
    3. sbit led = P3^6; // LED1 连接到P3端口的第6
    4. sbit led1 = P3^7; // LED2 连接到P3端口的第7
    5. int cnt = 0; // 用于计数定时器溢出次数的变量
    6. // 定时器0初始化函数
    7. void Time0Init()
    8. {
    9. // 1. 配置定时器0工作模式为16位计时模式
    10. TMOD = 0x01; // 设置定时器016位计时器模式(模式1
    11. // 2. 给定初值,设置一个10ms的定时周期
    12. TL0 = 0x00; // 设置定时器0的低8位初值
    13. TH0 = 0xDC; // 设置定时器0的高8位初值
    14. // (0xDC0016位定时器初值,用来生成10ms的定时周期)
    15. // 3. 开始计时
    16. TR0 = 1; // 启动定时器0
    17. TF0 = 1; // 设置定时器0的溢出标志位(启动时应清零,但此处设为1可能是为确保中断服务函数能被触发)
    18. // 4. 打开定时器0中断
    19. ET0 = 1; // 使能定时器0中断
    20. // 5. 打开总中断EA
    21. EA = 1; // 使能总中断,允许所有中断请求
    22. }
    23. // 延时函数
    24. void Delay300ms() //@11.0592MHz
    25. {
    26. unsigned char i, j, k;
    27. i = 3; // 外循环计数
    28. j = 26; // 中循环计数
    29. k = 223; // 内循环计数
    30. do
    31. {
    32. do
    33. {
    34. while (--k); // 内循环延时
    35. } while (--j); // 中循环延时
    36. } while (--i); // 外循环延时
    37. }
    38. // 主函数
    39. void main()
    40. {
    41. led = 1; // 初始化时将LED1点亮
    42. led1 = 0; // 初始化时将LED2熄灭
    43. Time0Init(); // 调用定时器0初始化函数
    44. while(1) {
    45. // 无限循环
    46. led1 = 0; // LED2熄灭
    47. Delay300ms(); // 延时300ms
    48. led1 = 1; // LED2点亮
    49. Delay300ms(); // 延时300ms
    50. }
    51. }
    52. // 定时器0中断服务函数
    53. void Time0Handler() interrupt 1
    54. {
    55. cnt++; // 每次定时器0溢出时,计数器cnt增加1
    56. // 重新给定时器0初值,以保持定时周期
    57. TL0 = 0x00; // 重新加载定时器0的低8位初值
    58. TH0 = 0xDC; // 重新加载定时器0的高8位初值
    59. if(cnt == 30) { //30次溢出表示约1秒(10ms * 30 = 300ms)
    60. cnt = 0; // 重置计数器cnt,以开始新的计时周期
    61. led = !led; // 翻转LED1的状态
    62. }
    63. }

    当然,下面是对你提供的代码的详细解释,逐步解释每一部分的功能和目的:

    1. 头文件和变量定义
    1. #include "reg52.h"
    2. // 定义LED控制的位变量
    3. sbit led = P3^6; // LED1 连接到P3端口的第6
    4. sbit led1 = P3^7; // LED2 连接到P3端口的第7
    5. int cnt = 0; // 用于计数定时器溢出次数的变量
    • #include "reg52.h":包括一个头文件,这个文件通常包含对51系列单片机寄存器的定义。
    • sbit led = P3^6;sbit led1 = P3^7;:将 ledled1 分别定义为 P3 端口的第6位和第7位,控制对应的LED灯。sbit 是位变量的定义方式,用于操作单片机的特定位。
    • int cnt = 0;:定义一个全局变量 cnt,用来计数定时器溢出次数。
    2. 定时器0初始化函数
    1. void Time0Init()
    2. {
    3. // 1. 配置定时器0工作模式为16位计时模式
    4. TMOD = 0x01; // 设置定时器016位定时器模式(模式1
    5. // 2. 给定初值,设置一个10ms的定时周期
    6. TL0 = 0x00; // 设置定时器0的低8位初值
    7. TH0 = 0xDC; // 设置定时器0的高8位初值
    8. // (0xDC0016位定时器初值,用来生成10ms的定时周期)
    9. // 3. 开始计时
    10. TR0 = 1; // 启动定时器0
    11. TF0 = 1; // 设置定时器0的溢出标志位(启动时应清零,但此处设为1可能是为确保中断服务函数能被触发)
    12. // 4. 打开定时器0中断
    13. ET0 = 1; // 使能定时器0中断
    14. // 5. 打开总中断EA
    15. EA = 1; // 使能总中断,允许所有中断请求
    16. }
    • 配置定时器模式
      • TMOD = 0x01;:设置定时器0为模式1(16位定时器模式)。TMOD 寄存器的低4位设置定时器0的模式,0x01 表示模式1,即16位计时器。
    • 设置定时初值
      • TL0 = 0x00;TH0 = 0xDC;:设置定时器0的低8位(TL0)和高8位(TH0)的初值。这里的初值 0xDC00(16位)用来生成一个10ms的定时周期。具体的10ms周期计算基于单片机的时钟频率(11.0592 MHz)。
    • 启动定时器和中断
      • TR0 = 1;:启动定时器0,开始计时。
      • TF0 = 1;:设置溢出标志位。这通常在定时器启动时应清除,但此处设为1可能是为了确保中断服务函数能被触发。
      • ET0 = 1;:使能定时器0的中断,允许定时器溢出时触发中断。
      • EA = 1;:使能所有中断,允许中断请求的处理。
    3. 延时函数
    1. void Delay300ms() //@11.0592MHz
    2. {
    3. unsigned char i, j, k;
    4. i = 3; // 外循环计数
    5. j = 26; // 中循环计数
    6. k = 223; // 内循环计数
    7. do
    8. {
    9. do
    10. {
    11. while (--k); // 内循环延时
    12. } while (--j); // 中循环延时
    13. } while (--i); // 外循环延时
    14. }
    • 延时函数
      • Delay300ms() 用来实现一个大约300ms的延时。
      • 使用嵌套的 do-while 循环来耗费时间。外层循环 i 控制循环次数,中层循环 j 和内层循环 k 控制每次循环的延时。具体的延时时间取决于单片机的时钟频率(11.0592 MHz)。
    4. 主函数
    1. void main()
    2. {
    3. led = 1; // 初始化时将LED1点亮
    4. led1 = 0; // 初始化时将LED2熄灭
    5. Time0Init(); // 调用定时器0初始化函数
    6. while(1) {
    7. // 无限循环
    8. led1 = 0; // LED2熄灭
    9. Delay300ms(); // 延时300ms
    10. led1 = 1; // LED2点亮
    11. Delay300ms(); // 延时300ms
    12. }
    13. }
    • 主函数
      • 初始化时将LED1点亮 (led = 1;),LED2熄灭 (led1 = 0;)。
      • 调用 Time0Init() 初始化定时器0。
      • 进入无限循环,在其中交替点亮和熄灭LED2,每次切换后调用 Delay300ms() 实现300ms的延时。
    5. 定时器0中断服务函数
    1. void Time0Handler() interrupt 1
    2. {
    3. cnt++; // 每次定时器0溢出时,计数器cnt增加1
    4. // 重新给定时器0初值,以保持定时周期
    5. TL0 = 0x00; // 重新加载定时器0的低8位初值
    6. TH0 = 0xDC; // 重新加载定时器0的高8位初值
    7. if(cnt == 30) { //30次溢出表示约1秒(10ms * 30 = 300ms)
    8. cnt = 0; // 重置计数器cnt,以开始新的计时周期
    9. led = !led; // 翻转LED1的状态
    10. }
    11. }
    • 定时器0中断服务函数
      • void Time0Handler() interrupt 1:这是定时器0的中断服务函数。interrupt 1 表示它处理定时器0的中断请求。
      • cnt++:每次定时器0溢出时,计数器 cnt 增加1。
      • 重新设置定时器0的初值 (TL0TH0),以保持定时器的计时周期。
      • cnt 达到30时(每30次10ms溢出约300ms),重置 cnt 并翻转LED1的状态。

    二、PWM开发SG90

    2.1 简介

    PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进 行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的 时间占据整个信号周期的百分比,例如方波的占空比就是50%.

    • 脉冲宽度调制
    • 通过占空比编码模拟信号
    • 占空比 一个周期内,高电平占据时长的百分比

    4毫秒为一个(波形)周期,其中3ms为低电平,1ms为高电平

    什么是占空比 :一个周期内,高电平占据时长的百分比,为25%。

    2.2 如何实现PWM信号输出

    1. 通过芯片内部模块输出,一般观察手册或者芯片IO口都会标明这个是否是PWM口

    如下图增强51,STC15w的

    2. 如果没有集成PWM功能,可以通过IO口软件模拟,相对硬件PWM来说精准度略差 ,怎么模拟;

    搞个50HZ频率的pwm;

    2.3 控制舵机
    1. 什么是舵机

    如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制

    用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等

    常见的有0-90°、0-180°、0-360°

    2. 怎么控制舵机

    向黄色信号线“灌入”PWM信号。

    PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右

    数据:

    0.5ms-------------0度; 2.5% 对应函数中占空比为250

    1.0ms------------45度; 5.0% 对应函数中占空比为500

    1.5ms------------90度; 7.5% 对应函数中占空比为750

    2.0ms-----------135度; 10.0% 对应函数中占空比为1000

    2.5ms-----------180度; 12.5% 对应函数中占空比为1250

    定时器需要定时20ms, 关心的单位0.5ms, 40个的0.5ms,初值0.5m cnt++

    1s = 10ms * 100

    20ms = 0.5ms * 40 \

    • 编程实现

    1. #include "reg52.h"
    2. sbit sg90_con = P1^1; // 定义一个名为 sg90_con 的引脚,与 P1 端口的第 1 位连接
    3. int jiaodu ; // 定义一个整数变量 jiaodu,用于表示角度
    4. int cnt = 0; // 定义一个计数器变量 cnt,用于统计定时器溢出次数
    5. // 延时 2000 毫秒函数
    6. void Delay2000ms() //@11.0592MHz
    7. {
    8. unsigned char i, j, k;
    9. i = 15;
    10. j = 2;
    11. k = 235;
    12. do
    13. {
    14. do
    15. {
    16. while (--k); // 内层循环,k 减到 0
    17. } while (--j); // 中层循环,j 减到 0
    18. } while (--i); // 外层循环,i 减到 0
    19. }
    20. // 定时器0初始化函数
    21. void Time0Init()
    22. {
    23. //1. 配置定时器0工作模式为16位计时
    24. TMOD = 0x01;
    25. //2. 设置初值,定时10ms
    26. TL0=0x33;
    27. TH0=0xFE;
    28. //3. 开始计时
    29. TR0 = 1;
    30. TF0 = 0;
    31. //4. 打开定时器0中断
    32. ET0 = 1;
    33. //5. 打开总中断EA
    34. EA = 1;
    35. }
    36. // 延时 300 毫秒函数
    37. void Delay300ms() //@11.0592MHz
    38. {
    39. unsigned char i, j, k;
    40. i = 3;
    41. j = 26;
    42. k = 223;
    43. do
    44. {
    45. do
    46. {
    47. while (--k); // 内层循环,k 减到 0
    48. } while (--j); // 中层循环,j 减到 0
    49. } while (--i); // 外层循环,i 减到 0
    50. }
    51. void main()
    52. {
    53. Delay300ms(); // 让硬件稳定一下
    54. Time0Init(); // 初始化定时器
    55. jiaodu = 1; // 初始角度是 0 度,高电平时间为 0.5ms
    56. cnt = 0;
    57. sg90_con = 1; // 一开始从高电平开始
    58. // 每隔两秒切换一次角度
    59. while(1){
    60. jiaodu = 3; // 90度,高电平时间为 1.5ms
    61. cnt = 0;
    62. Delay2000ms();
    63. jiaodu = 1; // 0度,高电平时间为 0.5ms
    64. cnt = 0;
    65. Delay2000ms();
    66. }
    67. }
    68. // 定时器0中断处理函数
    69. void Time0Handler() interrupt 1
    70. {
    71. cnt++; // 统计溢出次数
    72. // 重新设置定时器初值
    73. TL0=0x33;
    74. TH0=0xFE;
    75. // 控制PWM波
    76. if(cnt < jiaodu){
    77. sg90_con = 1; // 设置高电平
    78. }else{
    79. sg90_con = 0; // 设置低电平
    80. }
    81. if(cnt == 40){ // 溢出40次,经过20ms
    82. cnt = 0; // 重新开始计数
    83. sg90_con = 1; // 开始新的PWM周期,从高电平开始
    84. }
    85. }
    详细解释
    1. 头文件和变量定义
      • #include "reg52.h":包含51单片机的头文件。
      • sbit sg90_con = P1^1;:定义舵机控制引脚,连接到P1.1。
      • int jiaodu;int cnt = 0;:用于控制舵机角度和计数器的变量。
    1. 延时函数
      • Delay2000ms()Delay300ms():这两个函数通过嵌套的空循环实现延时,用于产生约2000毫秒和300毫秒的延时。
    1. 定时器初始化函数
      • Time0Init():配置定时器0为16位计时模式,设置初始值,启动定时器,并开启定时器中断和全局中断。
    1. 主函数
      • main():主函数初始化定时器,并在一个无限循环中每隔2秒切换舵机的角度。jiaodu 设置为1表示0度,设置为3表示90度。
    1. 定时器中断处理函数
      • Time0Handler():定时器0溢出时调用此函数。每次溢出时计数器 cnt 增加,设置新的初始值,并根据 cntjiaodu 控制舵机信号引脚 sg90_con 的高低电平,从而产生PWM波。
    工作原理
    • PWM信号生成
      • 中断处理函数通过计数器 cnt 控制 sg90_con 的高低电平时间,从而生成PWM信号。每个PWM周期为20ms,其中高电平时间由 jiaodu 控制。
    • 舵机控制
      • 主函数通过设置 jiaodu 控制舵机角度,每隔2秒改变一次角度。通过 Delay2000ms() 函数实现延时。
    • 中断处理
      • 每次定时器0溢出时,进入中断处理函数。计数器 cnt 增加,并根据 cnt 的值控制PWM波的高低电平。当 cnt 达到40次溢出时(相当于20ms),重置 cnt 并开始新的PWM周期。

    主函数和中断一起执行 ,如果cnt 大于角度的时候,是低电压,中断函数cnt继续加加,直到加到等于40的时候,这个周期结束,进入下一个周期,

    三、 超声波测距

    3.1 简介

    型号:HC-SR04

    接线参考:模块除了两个电源引脚外,还有TRIG,ECHO引脚,这两个引脚分别接我们开发板的P1.5和

    P1.6端口

    超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度, 计算出模块到前方障碍物的距离。

    • 怎么让它发送波

    Trig ,给Trig端口至少10us的高电平

    • 怎么知道它开始发了

    Echo信号,由低电平跳转到高电平,表示开始发送波

    • 怎么知道接收了返回波

    Echo,由高电平跳转回低电平,表示波回来了

    • 怎么算时间

    Echo引脚维持高电平的时间!

    波发出去的那一下,开始启动定时器

    波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间

    • 怎么算距离

    距离 = 速度 (340m/s)* 时间/2

    3.2 超声波的时序图

    3.3 超声波测距代码实现
    1. #include "reg52.h"
    2. //距离小于10cm ,D5 亮,6灭,反之想反
    3. sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7
    4. sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6
    5. sbit Trig = P1^5; // 发送声波
    6. sbit Echo = P1^6; // 接收声波
    7. void Delay10us() //@11.0592MHz //声波的持续时间 10微妙
    8. {
    9. unsigned char i;
    10. i = 2;
    11. while (--i);
    12. }
    13. /*
    14. 十进制2左移1位,变成20。相当于乘以10
    15. 二禁止1左移1位,变成102)。相当于乘以2,左移8位,乘以28次方=256*/
    16. void startHC() //Trig 输出10ms的高电平 启动发波
    17. {
    18. Trig = 0; //发声波 低电压
    19. Trig = 1; //发声波 高电压 维持10
    20. Delay10us();
    21. Trig = 0; //发声波 低电压
    22. }//设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
    23. void Time0Init() //不用关心初值 定时器
    24. {
    25. TMOD &= 0xF0; //设置定时器模式
    26. TMOD |= 0x01; //设置定时器模式
    27. TH0 = 0; //16进制计时
    28. TL0 = 0;
    29. // 设置定时器-0工作模块1.初值为0,不着急启动定时器、
    30. }
    31. double get_distance()
    32. {
    33. double time;
    34. //定时器数据清零,以便下一次测距
    35. TH1 = 0;
    36. TL1 = 0;
    37. startHC(); //调用超声波函数,启动发波;
    38. while(Echo == 0); // 当接收端由低电压转换至高电压时,循环结束 表示声波发出
    39. // 启动定时器
    40. TR0 = 1; // 开始计时
    41. // 3、Echo,由高电平跳转回低电平,表示波回来了
    42. // 停止计时
    43. while(Echo == 1); // 当接收端由高电压转换至低电压时,循环结束,表示声波返回
    44. TR0 = 0; // 停止计时
    45. //4. 计算出中间经过多少时间 (公式)
    46. time = (TH0 * 256 + TL0)*1.085;//us为单位
    47. //5. 距离 = 速度 (340m/s)* 时间/2
    48. dis = time * 0.017;
    49. double dis; //返回一个数值
    50. }
    51. void openStatusLight() // 开启状态灯
    52. {
    53. D5 = 0;
    54. D6 = 1;
    55. }
    56. void closeStatusLight() // 关闭状态灯
    57. {
    58. D5 = 1;
    59. D6 = 0;
    60. }
    61. void main()
    62. {
    63. double dis; // 距离
    64. Time0Init(); //初始化定时器
    65. while(1){
    66. dis = get_distance(); // 计算距离
    67. // 判断距离是否小于10cm
    68. if(dis < 10){ // 如果小于10cm
    69. openStatusLight(); // 调用开启函数
    70. }else{ // 否则。其他情况
    71. closeStatusLight(); // 调用关闭函数
    72. }
    73. }
    74. }

    四、本节项目感应开关盖垃圾桶

    4.1 项目概述
    • 功能描述
        • 检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
        • 发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
        • 按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
    • 硬件说明
        • SG90舵机,超声波模块,震动传感器,蜂鸣器
    • 接线说明

    舵机控制口 P1.1;超声波Trig接 P1.5 ,Echo接 P1.6 ;蜂鸣器接 P2.0 口; 震动传感器接 P3.2`口(外部 中断0)

    4.2 编程实现
    • 开发步骤:

    1. 舵机和超声波代码整合

      • 舵机用定时器0
      • 超声波用定时器1
      • 实现物体靠近后,自动开盖,2秒后关盖

    2. 查询的方式添加按键控制

    3. 查询的方式添加震动控制

    4. 使用外部中断0配合震动控制

    代码:

    1. #include "reg52.h"
    2. sbit sg90_con = P1^1;
    3. sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7
    4. sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6
    5. sbit Trig = P1^5;
    6. sbit Echo = P1^6;
    7. int jiaodu ; // 舵机的角度
    8. int cnt = 0; //爆表的累计次数
    9. void Delay2000ms() //@11.0592MHz // 延迟2
    10. {
    11. unsigned char i, j, k;
    12. i = 15;
    13. j = 2;
    14. k = 235;
    15. do
    16. {
    17. do
    18. {
    19. while (--k);
    20. } while (--j);
    21. } while (--i);
    22. }
    23. void Delay10us() //@11.0592MHz
    24. {
    25. unsigned char i;
    26. i = 2;
    27. while (--i);
    28. }
    29. void startHC() //Trig 输出10ms的高电平 启动发波
    30. {
    31. Trig = 0;
    32. Trig = 1;
    33. Delay10us();
    34. Trig = 0;
    35. }
    36. void Time0Init1() // 初始化定时器0,用于舵机控制
    37. {
    38. //1. 配置定时器0工作模式位16位计时
    39. TMOD &= 0xF0; //设置定时器模式
    40. TMOD |= 0x01;
    41. //2. 给初值,定一个10ms出来
    42. TL0=0x33;
    43. TH0=0xFE;
    44. //3. 开始计时
    45. TR0 = 1;
    46. TF0 = 0;
    47. //4. 打开定时器0中断
    48. ET0 = 1;
    49. //5. 打开总中断EA
    50. EA = 1;
    51. }
    52. void Time0Init2() // 初始化定时器1,用于超声波控制
    53. {
    54. TMOD &= 0x0F; //设置定时器模式
    55. TMOD |= 0x10; //设置定时器模式
    56. TH1 = 0;
    57. TL1 = 0;
    58. // 设置定时器-0工作模块1.初值为0,不着急启动定时器、
    59. }
    60. void Delay300ms() //@11.0592MHz
    61. {
    62. unsigned char i, j, k;
    63. i = 3;
    64. j = 26;
    65. k = 223;
    66. do
    67. {
    68. do
    69. {
    70. while (--k);
    71. } while (--j);
    72. } while (--i);
    73. }
    74. void initSG90_0()
    75. {
    76. jiaodu = 1; //初始角度是0度,0.5ms,溢出1就是0.5,高电平
    77. cnt = 0;
    78. sg90_con = 1; //一开始从高电平开始
    79. }
    80. double get_distance()
    81. {
    82. double time;
    83. double dis;
    84. //定时器数据清零,以便下一次测距
    85. TH1 = 0;
    86. TL1 = 0;
    87. //1. Trig ,给Trig端口至少10us的高电平
    88. startHC();
    89. // 2、Echo信号,由低电平跳转到高电平,表示开始发送波
    90. // 波发出去的那一下,开始启动定时器
    91. while(Echo == 0);
    92. // 启动定时器
    93. TR1 = 1;
    94. // 3、Echo,由高电平跳转回低电平,表示波回来了
    95. // 停止计时
    96. while(Echo == 1);
    97. TR1 = 0;
    98. //4. 计算出中间经过多少时间
    99. time = (TH1 * 256 + TL1)*1.085;//us为单位
    100. //5. 距离 = 速度 (340m/s)* 时间/2
    101. dis = time * 0.017;
    102. return dis;
    103. }
    104. void openStatusLight() {
    105. D5 = 0; // 点亮D5
    106. D6 = 1; // 熄灭D6
    107. }
    108. void closeStatusLight() {
    109. D5 = 1; // 熄灭D5
    110. D6 = 0; // 点亮D6
    111. }
    112. void openlajitong() {
    113. jiaodu = 3; // 90度,1.5ms高电平
    114. cnt = 0;
    115. Delay2000ms();
    116. }
    117. void closelajitong() {
    118. jiaodu = 1; // 0度,0.5ms高电平
    119. cnt = 0;
    120. Delay2000ms();
    121. }
    122. void main()
    123. {
    124. double dis;
    125. Delay300ms(); // 让硬件稳定一下
    126. Time0Init1(); // 初始化定时器1
    127. Time0Init2(); // 初始化定时器2
    128. initSG90_0(); // 初始化舵机的角度
    129. // 每隔两秒切换一次角度
    130. while(1){
    131. dis = get_distance(); // 计算距离
    132. if(dis < 10){ // 判断距离
    133. // 如果距离小于10 调用开启函数
    134. openStatusLight(); //
    135. openlajitong();
    136. }else{ // 如果距离大于10 调用关闭函数
    137. closeStatusLight();
    138. closelajitong();
    139. }
    140. }
    141. }
    142. void Time0Handler() interrupt 1 // 定时器中断
    143. {
    144. cnt++; //统计爆表的次数,cnt = 1的时候,报表了1
    145. //重新给初值
    146. TL0=0x33;
    147. TH0=0xFE;
    148. // 控制PWM波
    149. if(cnt < jiaodu){
    150. sg90_con = 1 ;
    151. }else{
    152. sg90_con = 0 ;
    153. }
    154. if(cnt == 40){//爆表40次,经过了20ms
    155. cnt = 0; //100次表示1s,重新让cnt从0开始,计算下一次的1s
    156. sg90_con = 1 ;
    157. }
    158. }
    • 测距开关盖添加按键开盖功能
      • 51单片机KY1 按键
      • 遥控发送接收433M
        • https://wenku.baidu.com/view/8fe8f444bed5b9f3f80f1c33.html
        • 默认低电平,按键之后是高电平。
        • 遥控控制开关
    1. #include "reg52.h"
    2. // 定义各个IO口
    3. sbit D5 = P3^7; // LED D5连接到P3.7
    4. sbit D6 = P3^6; // LED D6连接到P3.6
    5. sbit SW1 = P2^1; // 开关 SW1连接到P2.1
    6. sbit Trig = P1^5; // 超声波传感器Trig引脚连接到P1.5
    7. sbit Echo = P1^6; // 超声波传感器Echo引脚连接到P1.6
    8. sbit sg90_con = P1^1; // SG90舵机控制引脚连接到P1.1
    9. sbit D0_ON = P1^2; // LED D0_ON连接到P1.2
    10. sbit D1_OFF = P1^3; // LED D1_OFF连接到P1.3
    11. int jiaodu ; // 舵机的角度
    12. int cnt = 0; //爆表的累计次数
    13. void Delay2000ms() //@11.0592MHz // 延迟2
    14. {
    15. unsigned char i, j, k;
    16. i = 15;
    17. j = 2;
    18. k = 235;
    19. do
    20. {
    21. do
    22. {
    23. while (--k);
    24. } while (--j);
    25. } while (--i);
    26. }
    27. void Delay10us() //@11.0592MHz
    28. {
    29. unsigned char i;
    30. i = 2;
    31. while (--i);
    32. }
    33. void startHC() //Trig 输出10ms的高电平 启动发波
    34. {
    35. Trig = 0;
    36. Trig = 1;
    37. Delay10us();
    38. Trig = 0;
    39. }
    40. void Time0Init1() // 初始化定时器0,用于舵机控制
    41. {
    42. //1. 配置定时器0工作模式位16位计时
    43. TMOD &= 0xF0; //设置定时器模式
    44. TMOD |= 0x01;
    45. //2. 给初值,定一个10ms出来
    46. TL0=0x33;
    47. TH0=0xFE;
    48. //3. 开始计时
    49. TR0 = 1;
    50. TF0 = 0;
    51. //4. 打开定时器0中断
    52. ET0 = 1;
    53. //5. 打开总中断EA
    54. EA = 1;
    55. }
    56. void Time0Init2() // 初始化定时器1,用于超声波控制
    57. {
    58. TMOD &= 0x0F; //设置定时器模式
    59. TMOD |= 0x10; //设置定时器模式
    60. TH1 = 0;
    61. TL1 = 0;
    62. // 设置定时器-0工作模块1.初值为0,不着急启动定时器、
    63. }
    64. void Delay300ms() //@11.0592MHz
    65. {
    66. unsigned char i, j, k;
    67. i = 3;
    68. j = 26;
    69. k = 223;
    70. do
    71. {
    72. do
    73. {
    74. while (--k);
    75. } while (--j);
    76. } while (--i);
    77. }
    78. void initSG90_0()
    79. {
    80. jiaodu = 1; //初始角度是0度,0.5ms,溢出1就是0.5,高电平
    81. cnt = 0;
    82. sg90_con = 1; //一开始从高电平开始
    83. }
    84. double get_distance()
    85. {
    86. double time;
    87. double dis;
    88. //定时器数据清零,以便下一次测距
    89. TH1 = 0;
    90. TL1 = 0;
    91. //1. Trig ,给Trig端口至少10us的高电平
    92. startHC();
    93. // 2、Echo信号,由低电平跳转到高电平,表示开始发送波
    94. // 波发出去的那一下,开始启动定时器
    95. while(Echo == 0);
    96. // 启动定时器
    97. TR1 = 1;
    98. // 3、Echo,由高电平跳转回低电平,表示波回来了
    99. // 停止计时
    100. while(Echo == 1);
    101. TR1 = 0;
    102. //4. 计算出中间经过多少时间
    103. time = (TH1 * 256 + TL1)*1.085;//us为单位
    104. //5. 距离 = 速度 (340m/s)* 时间/2
    105. dis = time * 0.017;
    106. return dis;
    107. }
    108. void openStatusLight() {
    109. D5 = 0; // 点亮D5
    110. D6 = 1; // 熄灭D6
    111. }
    112. void closeStatusLight() {
    113. D5 = 1; // 熄灭D5
    114. D6 = 0; // 点亮D6
    115. }
    116. void openlajitong() {
    117. jiaodu = 3; // 90度,1.5ms高电平
    118. cnt = 0;
    119. Delay2000ms();
    120. }
    121. void closelajitong() {
    122. jiaodu = 1; // 0度,0.5ms高电平
    123. cnt = 0;
    124. Delay2000ms();
    125. }
    126. void main()
    127. {
    128. double dis;
    129. Delay300ms(); // 让硬件稳定一下
    130. Time0Init1(); // 初始化定时器1
    131. Time0Init2(); // 初始化定时器2
    132. initSG90_0(); // 初始化舵机的角度
    133. // 每隔两秒切换一次角度
    134. while(1){
    135. dis = get_distance(); // 计算距离
    136. if(dis < 10 || SW1 == 0 || D0_ON == 1){
    137. openStatusLight();
    138. openDusbin();
    139. }else if (D1_OFF == 1){
    140. //关盖,灯状态,D5
    141. closeStatusLight();
    142. closeDusbin();
    143. }else{
    144. closeStatusLight();
    145. closeDusbin();
    146. }
    147. }
    148. }
    149. void Time0Handler() interrupt 1 // 定时器中断
    150. {
    151. cnt++; //统计爆表的次数,cnt = 1的时候,报表了1
    152. //重新给初值
    153. TL0=0x33;
    154. TH0=0xFE;
    155. // 控制PWM波
    156. if(cnt < jiaodu){
    157. sg90_con = 1 ;
    158. }else{
    159. sg90_con = 0 ;
    160. }
    161. if(cnt == 40){//爆表40次,经过了20ms
    162. cnt = 0; //100次表示1s,重新让cnt从0开始,计算下一次的1s
    163. sg90_con = 1 ;
    164. }
    165. }
    • 测距开关盖添加振动传感器开盖功能
    1. #include "reg52.h"
    2. // 定义各个IO口
    3. sbit D5 = P3^7; // LED D5连接到P3.7
    4. sbit D6 = P3^6; // LED D6连接到P3.6
    5. sbit SW1 = P2^1; // 开关 SW1连接到P2.1
    6. sbit Trig = P1^5; // 超声波传感器Trig引脚连接到P1.5
    7. sbit Echo = P1^6; // 超声波传感器Echo引脚连接到P1.6
    8. sbit sg90_con = P1^1; // SG90舵机控制引脚连接到P1.1
    9. sbit D0_ON = P1^2; // LED D0_ON连接到P1.2
    10. sbit D1_OFF = P1^3; // LED D1_OFF连接到P1.3
    11. sbit vibrate = P3^2; // 振动传感器连接到P3.2
    12. sbit beep = P2^0;
    13. char jiaodu; // 舵机的角度变量
    14. char jd_bak;
    15. char cnt = 0;// 定时器溢出次数累计变量
    16. char mark_vibrate = 0;
    17. // 延迟2
    18. void Delay2000ms() //@11.0592MHz
    19. {
    20. unsigned char i, j, k;
    21. i = 15;
    22. j = 2;
    23. k = 235;
    24. do {
    25. do {
    26. while (--k);
    27. } while (--j);
    28. } while (--i);
    29. }
    30. // 延迟10微秒
    31. void Delay10us() //@11.0592MHz
    32. {
    33. unsigned char i;
    34. i = 2;
    35. while (--i);
    36. }
    37. // Trig输出10微秒的高电平以启动超声波传感器
    38. void startHC()
    39. {
    40. Trig = 0;
    41. Trig = 1;
    42. Delay10us();
    43. Trig = 0;
    44. }
    45. // 初始化定时器0,用于舵机控制
    46. void Time0Init1()
    47. {
    48. TMOD &= 0xF0; // 设置定时器模式
    49. TMOD |= 0x01; // 配置定时器0工作模式为16位计数
    50. TL0 = 0x33; // 定时器初值
    51. TH0 = 0xFE; // 定时器初值
    52. TR0 = 1; // 开始计时
    53. TF0 = 0; // 清除定时器溢出标志
    54. ET0 = 1; // 打开定时器0中断
    55. EA = 1; // 打开总中断
    56. }
    57. // 初始化定时器1,用于超声波控制
    58. void Time0Init2()
    59. {
    60. TMOD &= 0x0F; // 设置定时器模式
    61. TMOD |= 0x10; // 配置定时器1工作模式为16位计数
    62. TH1 = 0; // 定时器1初值
    63. TL1 = 0; // 定时器1初值
    64. }
    65. // 延迟300毫秒
    66. void Delay300ms() //@11.0592MHz
    67. {
    68. unsigned char i, j, k;
    69. i = 3;
    70. j = 26;
    71. k = 223;
    72. do {
    73. do {
    74. while (--k);
    75. } while (--j);
    76. } while (--i);
    77. }
    78. // 初始化舵机角度为0度(0.5ms高电平)
    79. void initSG90_0()
    80. {
    81. jiaodu = 1; // 初始角度是0
    82. cnt = 0;
    83. sg90_con = 1; // 一开始从高电平开始
    84. }
    85. // 获取距离
    86. double get_distance()
    87. {
    88. double time;
    89. double dis;
    90. TH1 = 0; // 定时器1数据清零
    91. TL1 = 0;
    92. startHC(); // 启动超声波传感器
    93. while(Echo == 0); // 等待Echo信号变高
    94. TR1 = 1; // 启动定时器1
    95. while(Echo == 1); // 等待Echo信号变低
    96. TR1 = 0; // 停止定时器1
    97. time = (TH1 * 256 + TL1) * 1.085; // 计算时间,单位为微秒
    98. dis = time * 0.017; // 计算距离,单位为厘米
    99. return dis;
    100. }
    101. // 打开状态灯
    102. void openStatusLight() {
    103. D5 = 0; // 点亮D5
    104. D6 = 1; // 熄灭D6
    105. }
    106. // 关闭状态灯
    107. void closeStatusLight() {
    108. D5 = 1; // 熄灭D5
    109. D6 = 0; // 点亮D6
    110. }
    111. // 打开垃圾桶
    112. void openlajitong() {
    113. char n;
    114. jiaodu = 3; //901.5ms高电平
    115. //舵机开盖
    116. if(jd_bak != jiaodu){
    117. cnt = 0;
    118. beep = 0;
    119. for(n=0;n<2;n++)
    120. Delay150ms();
    121. beep = 1;
    122. Delay2000ms();
    123. }
    124. jd_bak = jiaodu;
    125. }
    126. // 关闭垃圾桶
    127. void closelajitong() {
    128. char n;
    129. //关盖
    130. for(n=0;n<2;n++)
    131. Delay150ms();
    132. jd = 1; //0
    133. jd_bak = jd;
    134. cnt = 0;
    135. Delay150ms();
    136. }
    137. void EX0_Init()
    138. {
    139. //打开外部中断
    140. EX0 = 1;
    141. //低电平触发
    142. IT0 = 0;
    143. }
    144. // 主函数
    145. void main()
    146. {
    147. double dis;
    148. Delay300ms(); // 让硬件稳定一下
    149. Time0Init1(); // 初始化定时器0
    150. Time0Init2(); // 初始化定时器1
    151. EX0_Init();
    152. initSG90_0(); // 初始化舵机角度
    153. while(1) {
    154. dis = get_distance(); // 获取距离
    155. if(dis < 10 || SW1 == 0 || D0_ON == 1 || mark_vibrate == 1 ) { // 距离小于10cm或SW1按下或D0_ON为高电平
    156. openStatusLight();
    157. openlajitong();
    158. } else if (D1_OFF == 1) { // D1_OFF为高电平
    159. closeStatusLight();
    160. closelajitong();
    161. } else { // 其他情况
    162. closeStatusLight();
    163. closelajitong();
    164. }
    165. }
    166. }
    167. // 定时器中断处理函数
    168. void Time0Handler() interrupt 1
    169. {
    170. cnt++; // 累计定时器溢出次数
    171. TL0 = 0x33; // 重新设置定时器初值
    172. TH0 = 0xFE;
    173. if(cnt < jiaodu) {
    174. sg90_con = 1; // 输出高电平
    175. } else {
    176. sg90_con = 0; // 输出低电平
    177. }
    178. if(cnt == 40) { // 溢出40次,经过20ms
    179. cnt = 0; // 重置计数
    180. sg90_con = 1;
    181. }
    182. }
    183. void Ex0_Handler() interrupt 0 // 振动传感器输出低电平 中断
    184. {
    185. mark_vibrate = 1;
    186. }
  • 相关阅读:
    路由之间的转跳及传参
    ThreeJs学习
    测试开发技能实践-搭建ELK日志管理系统
    肝不完这份HTTP八股文的你,再强大也是假的
    SpringMVC 04 RestFul风格
    纽约时报个人叙事赛及纽约时报学生评论赛选哪个?
    java计算机毕业设计家庭财务管理系统设计与实现MyBatis+系统+LW文档+源码+调试部署
    接口的用法、常量接口、微观接口和宏观接口(JAVA基础六)
    【知识】从音频CS4334 DAC转换的电路引发的一些知识
    掌握4C原则,设计高效的系统架构
  • 原文地址:https://blog.csdn.net/2301_79405674/article/details/140912103