1. 初探单片机中断(188.33)
- 中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的
- 中断请求
- 中断嵌套
- 中断查询次序
- 如果使用C语言编程,中断查询次序号就是中断号,例如:
2. 定时器中断相关寄存器(189.34)
- 中断寄存器
- CPU能响应定时器0中断的条件:需要配置IE寄存器的bit1: ET0 bit7:EA
- ET0中断允许要置1 ET0 = 1
- EA总中断要置1 EA = 1
- 硬件内部设计逻辑如图:
3. 定时器中断方式控制LED(192.35)
- 代码(10. 定时器03中断)
#include "reg52.h"
#include <intrins.h>
sbit led=P3^7;
sbit led1=P3^6;
int cnt=0;
void Timer0Init()
{
//1.配置定时器0工作模式为16位计时
TMOD=0x01;
//2.给初值,定一个10ms出来
TH0=0xDC;
TL0=0x00;
//3.打开定时器0中断
ET0=1;
//4.打开EA总中断
EA=1;
//5.开始计时
TR0=1;//定时器0开始计时
//TF0=0;//软件清零
}
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
led=1;//主函数另一个灯持续执行亮灭
//led1=1;
Timer0Init();
while(1)
{
led1 = !led1;
Delay300ms();
}
}
void Timer0Helper() interrupt 1//中断处理函数,记得加中断号//属于后台任务
{//CPU响应中断时,硬件清零TF0
cnt++;//统计爆表的次数
//重新给初值
TH0=0xDC;
TL0=0x00;
//爆表n次,才让led翻转状态
if(cnt==100)//爆表n次,经过了10n的ms
{
led=!led;//爆表了100次,就是经过了1000ms,那么翻转led的状态
cnt=0;//重新让cnt从0开始,计算下一次的10nms
}
}
4. 初识PWM(190.36)
4.1 PWM简介
- 脉冲宽度调制
- 通过占空比编码模拟信号
- 占空比 一个周期内,高电平占据时长的百分比
- 电平的变化 引起pwm的波形来控制sg90舵机
4.2 如何实现PWM信号输出
- 通过芯片内部模块输出,一般观察手册或者芯片IO口都会标明这个是否是PWM口
如下图增强51,STC15w的CPU(更稳定)
- 如果没有集成PWM功能,可以通过IO口软件模拟,相对硬件PWM来说精准度略差
怎么模拟:搞个50Hz频率的PWM
5. sg90舵机基本认知(191.37)
- 什么是舵机
- 如下图所示,最便宜的舵机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.5ms cnt++
- 1s = 10ms * 100
- 20ms = 0.5ms * 40
6. 舵机编程实战(193.38)
- 编程思路
- 代码(11. 舵机控制)
#include "reg52.h"
#include <intrins.h>
sbit sg90_con=P1^1;
int cnt=0;
int degree;
void Timer0Init()
{
//1.配置定时器0工作模式为16位计时
TMOD=0x01;
//2.给初值,定一个0.5ms出来
TH0=0xFE;
TL0=0x33;
//3.打开定时器0中断
ET0=1;
//4.打开EA总中断
EA=1;
//5.开始计时
TR0=1;//定时器0开始计时
//TF0=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 Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
Delay300ms();//让硬件稳定一下
Timer0Init();//初始化定时器
degree=1; //初始角度是0度,0.5ms,定时器溢出1次就是0.5,高电平
cnt=0;
sg90_con=1;//一开始就从高电平开始
//每隔两秒切换一次角度
while(1)//若棒子0度没找准,校准:可将while内的注释掉,角度不做切换,去烧写即可校准
{
degree=3;//切到90度位 1.5ms高电平
cnt=0;//保持同步
Delay2000ms();
degree=1;//切到0度位 0.5ms高电平
cnt=0;
Delay2000ms();
}
}
void Timer0Helper() interrupt 1//中断处理函数,记得加中断号//属于后台任务
{//CPU响应中断时,硬件清零TF0
cnt++;//统计爆表的次数
//重新给初值
TH0=0xFE;
TL0=0x33;
//控制PWM波
if(cnt<degree)
{
sg90_con=1;
}else
{
sg90_con=0;
}
if(cnt==40)//爆表40次,经过了20ms
{
cnt=0;//重新让cnt从0开始,计算下一次的0.5*40=20ms
sg90_con=1;
}
}
7. 超声波测距传感器认知(194.39)
7.1 简介
- 型号:HC-SR04
- 接线参考:模块除了两个电源引脚外,还有TRIG,ECHO引脚,这两个引脚分别接我们开发板的P1.5和P1.6端口
超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度,计算出模块到前方障碍物的距离。
-
怎么让它发送波
- Trig ,给Trig端口至少10us的高电平
-
怎么知道它开始发送了
- Echo信号,由低电平跳转到高电平,表示开始发送波
-
怎么知道接收了返回波
- Echo,由高电平跳转回低电平,表示波回来了
-
怎么算时间
Echo引脚维持高电平的时间!- 波发出去的那一刻,开始启动定时器;
- 波返回来的拿一刻,开始停止定时器;
计算出中间经过多少时间。
-
怎么算距离
- 距离 = 速度 (340m/s)* 时间/2
7.2 超声波的时序图
8. 从零编程实现超声波测距(195.40)
- 代码(12. 超声波测距)
#include "reg52.h"
#include <intrins.h>
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
{
unsigned char i;
i = 2;
while (--i);
}
void Delay200ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 2;
j = 103;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer0Init()
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TH0 = 0;
TL0 = 0;//设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
}
/*十进制2左移1位,变成20。相当于乘以10
二禁止1左移1位,变成10(2)。相当于乘以2,左移8位,乘以2的8次方=256;*/
void startHC()
{
trig=0;
trig=1;
Delay10us();
trig=0;
}
void main()
{
double time;
double dis;
Timer0Init();
while(1)
{
//1.Trig ,给Trig端口至少10us的高电平
Delay200ms();//老一批超声波模块带晶振,所以不用加延时
startHC();
//2.Echo信号由低电平跳转到高电平,表示开始发送波
while(echo==0);//条件不满足时,就会由低电平调到高电平
//波发出去的那一刻,开始启动定时器;
TR0=1;
//3.Echo信号由高电平跳转回低电平,表示波回来了
while(echo==1);
//波返回来的拿一刻,开始停止定时器;
TR0=0;
//4.计算出中间经过多少时间。
time=(TH0*256 + TL0)*1.085;//us为单位
//5.距离 = 速度 (340m/s)* 时间/2 340m/s=34000cm/1000ms=34cm/ms=34cm/1000us=0.034cm/us
dis=time * 0.017;
if(dis<10)//距离小于10cm,D5亮D6灭,否则相反现象
{
D5=0;
D6=1;
}
else
{
D5=1;
D6=0;
}
//定时器数据清零,以便下一次测距
TH0 = 0;
TL0 = 0;
}
}