赞
踩
C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器或者计数器使用。
确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时,每经过1个机器周期,计数存储器的值就加1。而当配置为计数器时,每来一个负跳变信号(信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。
标准C51有2个定时器/计数器:T0和T1。他们的使用方法一致。C52相比C51多了一个T2
在51单片机中,定时器和计数器的主要区别在于它们的工作方式和用途:
定时器的本质原理: 每经过一个机器周期,就加1 :寄存器
思考:
晶振(晶体震荡器),又称数字电路的“心脏”,是各种电子产品里面必不可少的频率元器件。数字电
路的所有工作都离不开时钟,晶振的好坏、晶振电路设计的好坏,会影响到整个系统的稳
时钟周期也称为振荡周期,定义为时钟频率的倒数。时钟周期是计算机中最基本的、最小的时间单
位。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。更小的时钟周
期就意味着更高的工作频率
机器周期也称为CPU周期。在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶
段(如取指、译码、执行等),每一阶段完成一个基本操作。完成一个基本操作所需要的时间称为
机器周期。一般情况下,一个机器周期由若干个时钟周期组成
当晶振频率是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 微秒
相关寄存器:
在T8H0/1和TL0/1寄存器中加1,默认是从0开始数数,最多能数65536下,累计计时71ms ,71毫秒
就不让他从0开始数数,10ms需要数9216下,你让他从65536-9126=56320(16进制表示为
0xDC00)开始数数
这样TL0=0x00;TH0=0xDC
TCON寄存器的bit5(TF0)能表示爆表:当爆表的时候,硬件会修改bit5(TF0)位上面的数据,改成 1(置1),如果不用中断,我们代码清零。
TCON寄存器的bit4,TRO通过编程让这个位为1的时候,开始计时,相当于按下了闹钟
定时器模式寄存器:TMOD来选择定时器模式,选择工作方式1,TMOD的bit0 bit1配置成0 1 :16 位的定时器功能
8421法进制的转换,二进制转16进制(方便人类来看,对计算机底层来说,不关心二进制010101010)。
配寄存器推荐用按位操作,清零的时候,对应的需要清零的位与上0,不需要清零的位与上1
置1的时候,需要置1的位置或1,不需要置一的位置或0
AUXR,降低单片机时钟对外界的辐射。
- #include "reg52.h"
-
- sbit led1 = P3^6; // 定义 led1 变量,指向 P3.6 引脚
- sbit led2 = P3^7; // 定义 led2 变量,指向 P3.7 引脚
-
- void main()
- {
- // 1.配置定时器0工作模式为16位计数器模式
-
- int cnt = 0; // 定义一个整数变量 'cnt' 用于计数
-
- led1 = 1; // 初始化 led1 为高电平(假设高电平点亮)
- led2 = 0; // 初始化 led2 为低电平(假设低电平熄灭)
- TMOD = 0x01; // 配置定时器0为模式1(16位定时器模式)
-
- // 2.设置定时器初值,使其每10ms产生一次溢出
-
- TL0 = 0x00; // 设置定时器0低8位初值为 0x00
- TH0 = 0xDC; // 设置定时器0高8位初值为 0xDC
-
- // 3.启动计时
-
- TR0 = 1; // 启动定时器0
- TF0 = 0; // 清除定时器0溢出标志位
-
- while(1) { // 无限循环
- if(TF0 == 1) { // 如果定时器0溢出 爆表
- TF0 = 0; // 清除定时器0溢出标志位
-
- cnt++; // 增加计数器 'cnt' 的值
-
- // 重新设置定时器初值
- TL0 = 0x00;
- TH0 = 0xDC;
- if(cnt == 100) { // 如果计数器 'cnt' 达到 100(即经过1秒)
- cnt = 0; // 重置计数器 'cnt'
- led1 = !led1; // 翻转 led1 的状态
- led2 = !led2; // 翻转 led2 的状态
- }
- }
- }
- }

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

这段代码是用来在51系列单片机中配置定时器0,使其每隔1秒钟翻转一个LED的状态。下面是对每一部分的详细解释:
- #include "reg52.h"
-
- sbit led = P3^6; // 定义一个位变量led,连接到P3端口的第6位(LED1)
- sbit led1 = P3^7; // 定义一个位变量led1,连接到P3端口的第7位(LED2)
- 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的溢出次数。Time0Init
函数- void Time0Init()
- {
- //1. 配置定时器0工作模式位16位计时
- TMOD = 0x01;
- //2. 给初值,定一个10ms出来
- TL0=0x00;
- TH0=0xDC;
- //3. 开始计时
- TR0 = 1;
- TF0 = 0;
- //4. 打开定时器0中断
- ET0 = 1;
- //5. 打开总中断EA
- EA = 1;
- }
TMOD = 0x01;
:将 TMOD
寄存器的值设置为 0x01
,将定时器0配置为模式1(16位定时器模式)。低4位 0001
表示定时器0的工作模式。TL0 = 0x00;
和 TH0 = 0xDC;
:设置定时器0的初始值。TH0
和 TL0
设置为 0xDC00
,这样定时器从 0xDC00
开始计数。TR0 = 1;
:启动定时器0。TF0 = 0;
:清除定时器0的溢出标志位。ET0 = 1;
:允许定时器0的中断。EA = 1;
:允许总中断,使单片机能够响应所有中断请求。main
函数- void main()
- {
- led = 1; // 初始时点亮LED
- Time0Init(); // 初始化定时器0
- while(1){
- // 无限循环,等待中断发生
- }
- }
led = 1;
:在程序开始时,将 led
设为1,点亮LED。Time0Init();
:调用初始化定时器0的函数。while(1){}
:无限循环,程序在这里等待中断事件发生。实际的操作由中断处理函数完成。- void Time0Handler() interrupt 1
- {
- cnt++; // 统计溢出次数
- // 重新设置定时器初值
- TL0=0x00;
- TH0=0xDC;
- if(cnt == 100) { // 每100次溢出表示1秒
- cnt = 0; // 重置计数器
- led = !led; // 翻转LED状态
- }
- }
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的状态。- #include "reg52.h"
-
- // 定义LED控制的位变量
- sbit led = P3^6; // LED1 连接到P3端口的第6位
- sbit led1 = P3^7; // LED2 连接到P3端口的第7位
-
- int cnt = 0; // 用于计数定时器溢出次数的变量
-
- // 定时器0初始化函数
- void Time0Init()
- {
- // 1. 配置定时器0工作模式为16位计时模式
- TMOD = 0x01; // 设置定时器0为16位计时器模式(模式1)
-
- // 2. 给定初值,设置一个10ms的定时周期
- TL0 = 0x00; // 设置定时器0的低8位初值
- TH0 = 0xDC; // 设置定时器0的高8位初值
- // (0xDC00 是 16位定时器初值,用来生成10ms的定时周期)
-
- // 3. 开始计时
- TR0 = 1; // 启动定时器0
- TF0 = 1; // 设置定时器0的溢出标志位(启动时应清零,但此处设为1可能是为确保中断服务函数能被触发)
-
- // 4. 打开定时器0中断
- ET0 = 1; // 使能定时器0中断
-
- // 5. 打开总中断EA
- EA = 1; // 使能总中断,允许所有中断请求
- }
-
- // 延时函数
- void Delay300ms() //@11.0592MHz
- {
- unsigned char i, j, k;
-
- i = 3; // 外循环计数
- j = 26; // 中循环计数
- k = 223; // 内循环计数
- do
- {
- do
- {
- while (--k); // 内循环延时
- } while (--j); // 中循环延时
- } while (--i); // 外循环延时
- }
-
- // 主函数
- void main()
- {
- led = 1; // 初始化时将LED1点亮
- led1 = 0; // 初始化时将LED2熄灭
- Time0Init(); // 调用定时器0初始化函数
- while(1) {
- // 无限循环
- led1 = 0; // LED2熄灭
- Delay300ms(); // 延时300ms
- led1 = 1; // LED2点亮
- Delay300ms(); // 延时300ms
- }
- }
-
- // 定时器0中断服务函数
- void Time0Handler() interrupt 1
- {
- cnt++; // 每次定时器0溢出时,计数器cnt增加1
-
- // 重新给定时器0初值,以保持定时周期
- TL0 = 0x00; // 重新加载定时器0的低8位初值
- TH0 = 0xDC; // 重新加载定时器0的高8位初值
-
- if(cnt == 30) { // 每30次溢出表示约1秒(10ms * 30 = 300ms)
- cnt = 0; // 重置计数器cnt,以开始新的计时周期
- led = !led; // 翻转LED1的状态
- }
- }

当然,下面是对你提供的代码的详细解释,逐步解释每一部分的功能和目的:
- #include "reg52.h"
-
- // 定义LED控制的位变量
- sbit led = P3^6; // LED1 连接到P3端口的第6位
- sbit led1 = P3^7; // LED2 连接到P3端口的第7位
-
- int cnt = 0; // 用于计数定时器溢出次数的变量
#include "reg52.h"
:包括一个头文件,这个文件通常包含对51系列单片机寄存器的定义。sbit led = P3^6;
和 sbit led1 = P3^7;
:将 led
和 led1
分别定义为 P3 端口的第6位和第7位,控制对应的LED灯。sbit
是位变量的定义方式,用于操作单片机的特定位。int cnt = 0;
:定义一个全局变量 cnt
,用来计数定时器溢出次数。- void Time0Init()
- {
- // 1. 配置定时器0工作模式为16位计时模式
- TMOD = 0x01; // 设置定时器0为16位定时器模式(模式1)
-
- // 2. 给定初值,设置一个10ms的定时周期
- TL0 = 0x00; // 设置定时器0的低8位初值
- TH0 = 0xDC; // 设置定时器0的高8位初值
- // (0xDC00 是 16位定时器初值,用来生成10ms的定时周期)
-
- // 3. 开始计时
- TR0 = 1; // 启动定时器0
- TF0 = 1; // 设置定时器0的溢出标志位(启动时应清零,但此处设为1可能是为确保中断服务函数能被触发)
-
- // 4. 打开定时器0中断
- ET0 = 1; // 使能定时器0中断
-
- // 5. 打开总中断EA
- EA = 1; // 使能总中断,允许所有中断请求
- }

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;
:使能所有中断,允许中断请求的处理。- void Delay300ms() //@11.0592MHz
- {
- unsigned char i, j, k;
-
- i = 3; // 外循环计数
- j = 26; // 中循环计数
- k = 223; // 内循环计数
- do
- {
- do
- {
- while (--k); // 内循环延时
- } while (--j); // 中循环延时
- } while (--i); // 外循环延时
- }
Delay300ms()
用来实现一个大约300ms的延时。do-while
循环来耗费时间。外层循环 i
控制循环次数,中层循环 j
和内层循环 k
控制每次循环的延时。具体的延时时间取决于单片机的时钟频率(11.0592 MHz)。- void main()
- {
- led = 1; // 初始化时将LED1点亮
- led1 = 0; // 初始化时将LED2熄灭
- Time0Init(); // 调用定时器0初始化函数
- while(1) {
- // 无限循环
- led1 = 0; // LED2熄灭
- Delay300ms(); // 延时300ms
- led1 = 1; // LED2点亮
- Delay300ms(); // 延时300ms
- }
- }
led = 1;
),LED2熄灭 (led1 = 0;
)。Time0Init()
初始化定时器0。Delay300ms()
实现300ms的延时。- void Time0Handler() interrupt 1
- {
- cnt++; // 每次定时器0溢出时,计数器cnt增加1
-
- // 重新给定时器0初值,以保持定时周期
- TL0 = 0x00; // 重新加载定时器0的低8位初值
- TH0 = 0xDC; // 重新加载定时器0的高8位初值
-
- if(cnt == 30) { // 每30次溢出表示约1秒(10ms * 30 = 300ms)
- cnt = 0; // 重置计数器cnt,以开始新的计时周期
- led = !led; // 翻转LED1的状态
- }
- }
void Time0Handler() interrupt 1
:这是定时器0的中断服务函数。interrupt 1
表示它处理定时器0的中断请求。cnt++
:每次定时器0溢出时,计数器 cnt
增加1。TL0
和 TH0
),以保持定时器的计时周期。cnt
达到30时(每30次10ms溢出约300ms),重置 cnt
并翻转LED1的状态。PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进 行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的 时间占据整个信号周期的百分比,例如方波的占空比就是50%.
4毫秒为一个(波形)周期,其中3ms为低电平,1ms为高电平
什么是占空比 :一个周期内,高电平占据时长的百分比,为25%。
1. 通过芯片内部模块输出,一般观察手册或者芯片IO口都会标明这个是否是PWM口
如下图增强51,STC15w的
2. 如果没有集成PWM功能,可以通过IO口软件模拟,相对硬件PWM来说精准度略差 ,怎么模拟;
搞个50HZ频率的pwm;
如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制
用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等
常见的有0-90°、0-180°、0-360°
向黄色信号线“灌入”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 \
- #include "reg52.h"
-
- sbit sg90_con = P1^1; // 定义一个名为 sg90_con 的引脚,与 P1 端口的第 1 位连接
-
- int jiaodu ; // 定义一个整数变量 jiaodu,用于表示角度
- int cnt = 0; // 定义一个计数器变量 cnt,用于统计定时器溢出次数
-
- // 延时 2000 毫秒函数
- void Delay2000ms() //@11.0592MHz
- {
- unsigned char i, j, k;
- i = 15;
- j = 2;
- k = 235;
- do
- {
- do
- {
- while (--k); // 内层循环,k 减到 0
- } while (--j); // 中层循环,j 减到 0
- } while (--i); // 外层循环,i 减到 0
- }
-
- // 定时器0初始化函数
- void Time0Init()
- {
- //1. 配置定时器0工作模式为16位计时
- TMOD = 0x01;
- //2. 设置初值,定时10ms
- TL0=0x33;
- TH0=0xFE;
- //3. 开始计时
- TR0 = 1;
- TF0 = 0;
- //4. 打开定时器0中断
- ET0 = 1;
- //5. 打开总中断EA
- EA = 1;
- }
-
- // 延时 300 毫秒函数
- void Delay300ms() //@11.0592MHz
- {
- unsigned char i, j, k;
- i = 3;
- j = 26;
- k = 223;
- do
- {
- do
- {
- while (--k); // 内层循环,k 减到 0
- } while (--j); // 中层循环,j 减到 0
- } while (--i); // 外层循环,i 减到 0
- }
-
- void main()
- {
- Delay300ms(); // 让硬件稳定一下
- Time0Init(); // 初始化定时器
- jiaodu = 1; // 初始角度是 0 度,高电平时间为 0.5ms
- cnt = 0;
- sg90_con = 1; // 一开始从高电平开始
-
- // 每隔两秒切换一次角度
- while(1){
-
- jiaodu = 3; // 90度,高电平时间为 1.5ms
- cnt = 0;
- Delay2000ms();
- jiaodu = 1; // 0度,高电平时间为 0.5ms
- cnt = 0;
- Delay2000ms();
- }
- }
-
- // 定时器0中断处理函数
- void Time0Handler() interrupt 1
- {
- cnt++; // 统计溢出次数
- // 重新设置定时器初值
- TL0=0x33;
- TH0=0xFE;
-
- // 控制PWM波
- if(cnt < jiaodu){
- sg90_con = 1; // 设置高电平
- }else{
- sg90_con = 0; // 设置低电平
- }
- if(cnt == 40){ // 溢出40次,经过20ms
- cnt = 0; // 重新开始计数
- sg90_con = 1; // 开始新的PWM周期,从高电平开始
- }
- }

#include "reg52.h"
:包含51单片机的头文件。sbit sg90_con = P1^1;
:定义舵机控制引脚,连接到P1.1。int jiaodu;
和 int cnt = 0;
:用于控制舵机角度和计数器的变量。Delay2000ms()
和 Delay300ms()
:这两个函数通过嵌套的空循环实现延时,用于产生约2000毫秒和300毫秒的延时。Time0Init()
:配置定时器0为16位计时模式,设置初始值,启动定时器,并开启定时器中断和全局中断。main()
:主函数初始化定时器,并在一个无限循环中每隔2秒切换舵机的角度。jiaodu
设置为1表示0度,设置为3表示90度。Time0Handler()
:定时器0溢出时调用此函数。每次溢出时计数器 cnt
增加,设置新的初始值,并根据 cnt
和 jiaodu
控制舵机信号引脚 sg90_con
的高低电平,从而产生PWM波。cnt
控制 sg90_con
的高低电平时间,从而生成PWM信号。每个PWM周期为20ms,其中高电平时间由 jiaodu
控制。jiaodu
控制舵机角度,每隔2秒改变一次角度。通过 Delay2000ms()
函数实现延时。cnt
增加,并根据 cnt
的值控制PWM波的高低电平。当 cnt
达到40次溢出时(相当于20ms),重置 cnt
并开始新的PWM周期。主函数和中断一起执行 ,如果cnt 大于角度的时候,是低电压,中断函数cnt继续加加,直到加到等于40的时候,这个周期结束,进入下一个周期,
型号:HC-SR04
接线参考:模块除了两个电源引脚外,还有TRIG,ECHO引脚,这两个引脚分别接我们开发板的P1.5和
P1.6端口
超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度, 计算出模块到前方障碍物的距离。
Trig ,给Trig端口至少10us的高电平
Echo信号,由低电平跳转到高电平,表示开始发送波
Echo,由高电平跳转回低电平,表示波回来了
Echo引脚维持高电平的时间!
波发出去的那一下,开始启动定时器
波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
距离 = 速度 (340m/s)* 时间/2
- #include "reg52.h"
-
- //距离小于10cm ,D5 亮,6灭,反之想反
-
- sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
- sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
-
- sbit Trig = P1^5; // 发送声波
- sbit Echo = P1^6; // 接收声波
-
- void Delay10us() //@11.0592MHz //声波的持续时间 10微妙
- {
- unsigned char i;
-
- i = 2;
- while (--i);
- }
- /*
- 十进制2左移1位,变成20。相当于乘以10
- 二禁止1左移1位,变成10(2)。相当于乘以2,左移8位,乘以2的8次方=256;*/
- void startHC() //Trig 输出10ms的高电平 启动发波
- {
- Trig = 0; //发声波 低电压
- Trig = 1; //发声波 高电压 维持10秒
- Delay10us();
-
- Trig = 0; //发声波 低电压
-
- }//设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
-
- void Time0Init() //不用关心初值 定时器
- {
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
-
- TH0 = 0; //16进制计时
- TL0 = 0;
-
- // 设置定时器-0工作模块1.初值为0,不着急启动定时器、
-
- }
- double get_distance()
- {
- double time;
- //定时器数据清零,以便下一次测距
- TH1 = 0;
- TL1 = 0;
- startHC(); //调用超声波函数,启动发波;
-
- while(Echo == 0); // 当接收端由低电压转换至高电压时,循环结束 表示声波发出
- // 启动定时器
- TR0 = 1; // 开始计时
- // 3、Echo,由高电平跳转回低电平,表示波回来了
- // 停止计时
- while(Echo == 1); // 当接收端由高电压转换至低电压时,循环结束,表示声波返回
- TR0 = 0; // 停止计时
-
- //4. 计算出中间经过多少时间 (公式)
- time = (TH0 * 256 + TL0)*1.085;//us为单位
- //5. 距离 = 速度 (340m/s)* 时间/2
- dis = time * 0.017;
- double dis; //返回一个数值
- }
- void openStatusLight() // 开启状态灯
- {
- D5 = 0;
- D6 = 1;
- }
- void closeStatusLight() // 关闭状态灯
- {
- D5 = 1;
- D6 = 0;
- }
- void main()
- {
-
- double dis; // 距离
-
- Time0Init(); //初始化定时器
-
- while(1){
-
- dis = get_distance(); // 计算距离
-
- // 判断距离是否小于10cm
- if(dis < 10){ // 如果小于10cm
- openStatusLight(); // 调用开启函数
- }else{ // 否则。其他情况
- closeStatusLight(); // 调用关闭函数
- }
-
- }
- }

舵机控制口 P1.1;超声波Trig接 P1.5 ,Echo接 P1.6 ;蜂鸣器接 P2.0 口; 震动传感器接 P3.2`口(外部 中断0)
1. 舵机和超声波代码整合
2. 查询的方式添加按键控制
3. 查询的方式添加震动控制
4. 使用外部中断0配合震动控制
代码:
- #include "reg52.h"
-
- sbit sg90_con = P1^1;
- sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
- sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
-
-
- sbit Trig = P1^5;
- sbit Echo = P1^6;
-
- int jiaodu ; // 舵机的角度
- int cnt = 0; //爆表的累计次数
-
- void Delay2000ms() //@11.0592MHz // 延迟2秒
- {
- unsigned char i, j, k;
-
- i = 15;
- j = 2;
- k = 235;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
-
- void Delay10us() //@11.0592MHz
- {
- unsigned char i;
-
- i = 2;
- while (--i);
- }
-
- void startHC() //Trig 输出10ms的高电平 启动发波
- {
- Trig = 0;
- Trig = 1;
- Delay10us();
-
- Trig = 0;
-
- }
- void Time0Init1() // 初始化定时器0,用于舵机控制
- {
- //1. 配置定时器0工作模式位16位计时
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01;
- //2. 给初值,定一个10ms出来
- TL0=0x33;
- TH0=0xFE;
- //3. 开始计时
- TR0 = 1;
- TF0 = 0;
- //4. 打开定时器0中断
- ET0 = 1;
- //5. 打开总中断EA
- EA = 1;
- }
-
- void Time0Init2() // 初始化定时器1,用于超声波控制
- {
- TMOD &= 0x0F; //设置定时器模式
- TMOD |= 0x10; //设置定时器模式
-
- TH1 = 0;
- TL1 = 0;
-
- // 设置定时器-0工作模块1.初值为0,不着急启动定时器、
-
- }
- void Delay300ms() //@11.0592MHz
- {
- unsigned char i, j, k;
- i = 3;
- j = 26;
- k = 223;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
-
- void initSG90_0()
- {
- jiaodu = 1; //初始角度是0度,0.5ms,溢出1就是0.5,高电平
- cnt = 0;
- sg90_con = 1; //一开始从高电平开始
- }
- double get_distance()
- {
- double time;
- double dis;
- //定时器数据清零,以便下一次测距
- TH1 = 0;
- TL1 = 0;
- //1. Trig ,给Trig端口至少10us的高电平
- startHC();
-
- // 2、Echo信号,由低电平跳转到高电平,表示开始发送波
- // 波发出去的那一下,开始启动定时器
- while(Echo == 0);
-
- // 启动定时器
- TR1 = 1;
-
- // 3、Echo,由高电平跳转回低电平,表示波回来了
- // 停止计时
- while(Echo == 1);
-
- TR1 = 0;
-
- //4. 计算出中间经过多少时间
- time = (TH1 * 256 + TL1)*1.085;//us为单位
- //5. 距离 = 速度 (340m/s)* 时间/2
- dis = time * 0.017;
- return dis;
- }
- void openStatusLight() {
- D5 = 0; // 点亮D5
- D6 = 1; // 熄灭D6
- }
-
- void closeStatusLight() {
- D5 = 1; // 熄灭D5
- D6 = 0; // 点亮D6
- }
-
- void openlajitong() {
- jiaodu = 3; // 90度,1.5ms高电平
- cnt = 0;
- Delay2000ms();
- }
-
- void closelajitong() {
- jiaodu = 1; // 0度,0.5ms高电平
- cnt = 0;
- Delay2000ms();
- }
- void main()
- {
- double dis;
- Delay300ms(); // 让硬件稳定一下
- Time0Init1(); // 初始化定时器1
- Time0Init2(); // 初始化定时器2
- initSG90_0(); // 初始化舵机的角度
-
-
- // 每隔两秒切换一次角度
- while(1){
- dis = get_distance(); // 计算距离
-
- if(dis < 10){ // 判断距离
- // 如果距离小于10 调用开启函数
- openStatusLight(); //
- openlajitong();
- }else{ // 如果距离大于10 调用关闭函数
- closeStatusLight();
- closelajitong();
- }
- }
- }
- void Time0Handler() interrupt 1 // 定时器中断
- {
- cnt++; //统计爆表的次数,cnt = 1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- // 控制PWM波
- if(cnt < jiaodu){
- sg90_con = 1 ;
- }else{
- sg90_con = 0 ;
- }
- if(cnt == 40){//爆表40次,经过了20ms
- cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- sg90_con = 1 ;
-
- }
-
- }

- #include "reg52.h"
-
- // 定义各个IO口
- sbit D5 = P3^7; // LED D5连接到P3.7口
- sbit D6 = P3^6; // LED D6连接到P3.6口
- sbit SW1 = P2^1; // 开关 SW1连接到P2.1口
- sbit Trig = P1^5; // 超声波传感器Trig引脚连接到P1.5口
- sbit Echo = P1^6; // 超声波传感器Echo引脚连接到P1.6口
- sbit sg90_con = P1^1; // SG90舵机控制引脚连接到P1.1口
- sbit D0_ON = P1^2; // LED D0_ON连接到P1.2口
- sbit D1_OFF = P1^3; // LED D1_OFF连接到P1.3口
-
- int jiaodu ; // 舵机的角度
- int cnt = 0; //爆表的累计次数
-
- void Delay2000ms() //@11.0592MHz // 延迟2秒
- {
- unsigned char i, j, k;
-
- i = 15;
- j = 2;
- k = 235;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
- void Delay10us() //@11.0592MHz
- {
- unsigned char i;
-
- i = 2;
- while (--i);
- }
- void startHC() //Trig 输出10ms的高电平 启动发波
- {
- Trig = 0;
- Trig = 1;
- Delay10us();
-
- Trig = 0;
-
- }
- void Time0Init1() // 初始化定时器0,用于舵机控制
- {
- //1. 配置定时器0工作模式位16位计时
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01;
- //2. 给初值,定一个10ms出来
- TL0=0x33;
- TH0=0xFE;
- //3. 开始计时
- TR0 = 1;
- TF0 = 0;
- //4. 打开定时器0中断
- ET0 = 1;
- //5. 打开总中断EA
- EA = 1;
- }
- void Time0Init2() // 初始化定时器1,用于超声波控制
- {
- TMOD &= 0x0F; //设置定时器模式
- TMOD |= 0x10; //设置定时器模式
-
- TH1 = 0;
- TL1 = 0;
-
- // 设置定时器-0工作模块1.初值为0,不着急启动定时器、
-
- }
- void Delay300ms() //@11.0592MHz
- {
- unsigned char i, j, k;
- i = 3;
- j = 26;
- k = 223;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
- void initSG90_0()
- {
- jiaodu = 1; //初始角度是0度,0.5ms,溢出1就是0.5,高电平
- cnt = 0;
- sg90_con = 1; //一开始从高电平开始
- }
- double get_distance()
- {
- double time;
- double dis;
- //定时器数据清零,以便下一次测距
- TH1 = 0;
- TL1 = 0;
- //1. Trig ,给Trig端口至少10us的高电平
- startHC();
-
- // 2、Echo信号,由低电平跳转到高电平,表示开始发送波
- // 波发出去的那一下,开始启动定时器
- while(Echo == 0);
-
- // 启动定时器
- TR1 = 1;
-
- // 3、Echo,由高电平跳转回低电平,表示波回来了
- // 停止计时
- while(Echo == 1);
-
- TR1 = 0;
-
- //4. 计算出中间经过多少时间
- time = (TH1 * 256 + TL1)*1.085;//us为单位
- //5. 距离 = 速度 (340m/s)* 时间/2
- dis = time * 0.017;
- return dis;
- }
- void openStatusLight() {
- D5 = 0; // 点亮D5
- D6 = 1; // 熄灭D6
- }
- void closeStatusLight() {
- D5 = 1; // 熄灭D5
- D6 = 0; // 点亮D6
- }
- void openlajitong() {
- jiaodu = 3; // 90度,1.5ms高电平
- cnt = 0;
- Delay2000ms();
- }
- void closelajitong() {
- jiaodu = 1; // 0度,0.5ms高电平
- cnt = 0;
- Delay2000ms();
- }
- void main()
- {
- double dis;
- Delay300ms(); // 让硬件稳定一下
- Time0Init1(); // 初始化定时器1
- Time0Init2(); // 初始化定时器2
- initSG90_0(); // 初始化舵机的角度
-
- // 每隔两秒切换一次角度
- while(1){
- dis = get_distance(); // 计算距离
- if(dis < 10 || SW1 == 0 || D0_ON == 1){
- openStatusLight();
- openDusbin();
- }else if (D1_OFF == 1){
- //关盖,灯状态,D5灭
- closeStatusLight();
- closeDusbin();
- }else{
- closeStatusLight();
- closeDusbin();
- }
- }
- }
- void Time0Handler() interrupt 1 // 定时器中断
- {
- cnt++; //统计爆表的次数,cnt = 1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- // 控制PWM波
- if(cnt < jiaodu){
- sg90_con = 1 ;
- }else{
- sg90_con = 0 ;
- }
- if(cnt == 40){//爆表40次,经过了20ms
- cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- sg90_con = 1 ;
- }
- }

- #include "reg52.h"
-
- // 定义各个IO口
- sbit D5 = P3^7; // LED D5连接到P3.7口
- sbit D6 = P3^6; // LED D6连接到P3.6口
- sbit SW1 = P2^1; // 开关 SW1连接到P2.1口
- sbit Trig = P1^5; // 超声波传感器Trig引脚连接到P1.5口
- sbit Echo = P1^6; // 超声波传感器Echo引脚连接到P1.6口
- sbit sg90_con = P1^1; // SG90舵机控制引脚连接到P1.1口
- sbit D0_ON = P1^2; // LED D0_ON连接到P1.2口
- sbit D1_OFF = P1^3; // LED D1_OFF连接到P1.3口
- sbit vibrate = P3^2; // 振动传感器连接到P3.2口
- sbit beep = P2^0;
-
-
-
- char jiaodu; // 舵机的角度变量
- char jd_bak;
- char cnt = 0;// 定时器溢出次数累计变量
- char mark_vibrate = 0;
-
- // 延迟2秒
- void Delay2000ms() //@11.0592MHz
- {
- unsigned char i, j, k;
- i = 15;
- j = 2;
- k = 235;
- do {
- do {
- while (--k);
- } while (--j);
- } while (--i);
- }
-
- // 延迟10微秒
- void Delay10us() //@11.0592MHz
- {
- unsigned char i;
- i = 2;
- while (--i);
- }
-
- // Trig输出10微秒的高电平以启动超声波传感器
- void startHC()
- {
- Trig = 0;
- Trig = 1;
- Delay10us();
- Trig = 0;
- }
-
- // 初始化定时器0,用于舵机控制
- void Time0Init1()
- {
- TMOD &= 0xF0; // 设置定时器模式
- TMOD |= 0x01; // 配置定时器0工作模式为16位计数
- TL0 = 0x33; // 定时器初值
- TH0 = 0xFE; // 定时器初值
- TR0 = 1; // 开始计时
- TF0 = 0; // 清除定时器溢出标志
- ET0 = 1; // 打开定时器0中断
- EA = 1; // 打开总中断
- }
-
- // 初始化定时器1,用于超声波控制
- void Time0Init2()
- {
- TMOD &= 0x0F; // 设置定时器模式
- TMOD |= 0x10; // 配置定时器1工作模式为16位计数
- TH1 = 0; // 定时器1初值
- TL1 = 0; // 定时器1初值
- }
-
- // 延迟300毫秒
- void Delay300ms() //@11.0592MHz
- {
- unsigned char i, j, k;
- i = 3;
- j = 26;
- k = 223;
- do {
- do {
- while (--k);
- } while (--j);
- } while (--i);
- }
-
- // 初始化舵机角度为0度(0.5ms高电平)
- void initSG90_0()
- {
- jiaodu = 1; // 初始角度是0度
- cnt = 0;
- sg90_con = 1; // 一开始从高电平开始
- }
-
- // 获取距离
- double get_distance()
- {
- double time;
- double dis;
- TH1 = 0; // 定时器1数据清零
- TL1 = 0;
- startHC(); // 启动超声波传感器
- while(Echo == 0); // 等待Echo信号变高
- TR1 = 1; // 启动定时器1
- while(Echo == 1); // 等待Echo信号变低
- TR1 = 0; // 停止定时器1
- time = (TH1 * 256 + TL1) * 1.085; // 计算时间,单位为微秒
- dis = time * 0.017; // 计算距离,单位为厘米
- return dis;
- }
-
- // 打开状态灯
- void openStatusLight() {
- D5 = 0; // 点亮D5
- D6 = 1; // 熄灭D6
- }
-
- // 关闭状态灯
- void closeStatusLight() {
- D5 = 1; // 熄灭D5
- D6 = 0; // 点亮D6
- }
-
- // 打开垃圾桶
- void openlajitong() {
- char n;
- jiaodu = 3; //90度 1.5ms高电平
- //舵机开盖
- if(jd_bak != jiaodu){
- cnt = 0;
- beep = 0;
- for(n=0;n<2;n++)
- Delay150ms();
- beep = 1;
- Delay2000ms();
- }
-
- jd_bak = jiaodu;
-
- }
-
- // 关闭垃圾桶
- void closelajitong() {
- char n;
- //关盖
- for(n=0;n<2;n++)
- Delay150ms();
- jd = 1; //0度
- jd_bak = jd;
- cnt = 0;
- Delay150ms();
- }
- void EX0_Init()
- {
- //打开外部中断
- EX0 = 1;
- //低电平触发
- IT0 = 0;
- }
- // 主函数
- void main()
- {
- double dis;
- Delay300ms(); // 让硬件稳定一下
- Time0Init1(); // 初始化定时器0
- Time0Init2(); // 初始化定时器1
- EX0_Init();
- initSG90_0(); // 初始化舵机角度
-
- while(1) {
- dis = get_distance(); // 获取距离
- if(dis < 10 || SW1 == 0 || D0_ON == 1 || mark_vibrate == 1 ) { // 距离小于10cm或SW1按下或D0_ON为高电平
- openStatusLight();
- openlajitong();
- } else if (D1_OFF == 1) { // D1_OFF为高电平
- closeStatusLight();
- closelajitong();
- } else { // 其他情况
- closeStatusLight();
- closelajitong();
- }
- }
- }
-
- // 定时器中断处理函数
- void Time0Handler() interrupt 1
- {
- cnt++; // 累计定时器溢出次数
- TL0 = 0x33; // 重新设置定时器初值
- TH0 = 0xFE;
- if(cnt < jiaodu) {
- sg90_con = 1; // 输出高电平
- } else {
- sg90_con = 0; // 输出低电平
- }
- if(cnt == 40) { // 溢出40次,经过20ms
- cnt = 0; // 重置计数
- sg90_con = 1;
- }
-
- }
-
- void Ex0_Handler() interrupt 0 // 振动传感器输出低电平 中断
- {
- mark_vibrate = 1;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。