第十六课:扩展课!万能的电子开关
航模用的电子开关主要用途就是检测接收机的PWM信号,控制其他设备的供电。因此,它的用途实际上非常广泛:控制灯带、控制点火器、控制喇叭……而实际上,它的程序非常简单!
马上你就会恍然大悟,原来只需要几行代码,就可以实现曾经遥不可及的功能。
随着你们学习的越来越多,其实现在已经有能力去独立做一些简单的小东西了。
本次课程完全没有涉及到任何新知识,都是过去知识点的组合。
本课的主要内容:自主发挥,项目练手
1.1 测量PWM信号
前面学到,舵机测试仪控制舵机的信号,是用PWM高电平时间的长度,1ms~2ms;航模接收机的输出信号,也是一样的。
电子开关的原理,就是把自己“伪装”成一个“舵机”,如果收到1ms的高电平信号,就关闭开关;如果收到2ms的高电平信号,就打开开关。
现在如果还没有航模接收机,可以先用舵机测试仪代替。
如何测量高电平的时间?你是不是有些似曾相识。对的,在《红外接收机》课程中,已经学过了检测低电平时间。
只需要把红外接收的程序稍微修改下,就是一个万能的电子开关!
检测高电平时间:
while(IN==1)//如果引脚一直为高电平,一直循环
{
Delay10us();
time=time+1;//每循环一次,就记录了10us时间
}
判断高电平时间:
if(time>90&&time<120)OUT=0;//允许一定的误差,0.9ms~1.2ms高电平信号都可以关闭开关
if(time>180&&time<210)OUT=1;//允许一定的误差,1.8ms~2.1ms高电平信号都可以打开开关
简单例程:
#include<reg51.h>
#include<intrins.h>
sfr P3M0=0xb2; //声明 引脚输出模式寄存器
sbit IN=P3^4; //定义PWM输入引脚
sbit OUT=P3^3; //定义输出引脚
unsigned int time; //记录时间
void Delay10us() //@12.000MHz
{
unsigned char i;
_nop_();//使用《舵机测试仪》课程中调整过的延时程序
_nop_();
i = 24;
while (--i);
}
main()
{
OUT=0; //先关闭输出
P3M0=8; //P3.3引脚大电流模式
while(1)
{
if(IN==1) //收到PWM高电平,开始测量
{
time=0;//先把时间清零
while(IN==1)//如果引脚一直为高电平,一直循环
{
Delay10us();
time=time+1;//每循环一次,就记录了10us时间
}
//引脚变成低电平,循环结束
if(time>90&&time<120)//0.9ms~1.2ms高电平
{
OUT=0;//关闭开关
}
if(time>180&&time<210)//1.8ms~2.1ms高电平
{
OUT=1;//打开开关
}
}
}
}
1.2 项目扩展
电子开关的强大就在于它灵活的扩展性:
扩展方向1:夜航灯控
不仅能控制灯带的亮灭,通过编程,还能够实现多种模式:开关变化一次,灯带切换一个模式,如常亮、爆闪、双闪……等;
扩展方向2:点火器
开关动作后,点火两秒钟自动关闭;
扩展方向3:左右转向灯
1.5ms高电平舵机在中间,小于1.4说明左转弯亮左灯,大于1.6说明右转弯亮右灯;
扩展方向4:多路开关
控制四路,开关变化一次切换一路开关;
5:……………………………………
6:……………………………………
各种各样电子开关能实现的功能,只有你想不到,没有做不到。学会单片机,有什么需求直接自己动手实现!
在这里,给出一个实现一路灯控的例程,更多的功能,就要靠你自己的发挥练习了:
顺便学点小知识
知识点(53) #define 声明替换
写程序中我们经常遇到要写“unsigned char”这么一长串英文,有没有什么办法能够更简便点?在C程序中,还提供了一种替换机制:
#define A B//如果声明了这句话,那么以后在程序中写A,编译时会自动被系统替换成B。
利用这个机制,可以简写,比如:
#define u8 unsigned char//“unsigned char”是0~255的8位二进制数,我们以后可以简写为“u8”
#define u16 unsigned int//“unsigned int”是0~65535的16位二进制数,我们以后可以简写为“u16”
知识点(54) n++;自己加一
同样是为了简写程序,以后遇到“n=n+1;”这样自己增加1的,可以用两个加号代替:“n++;”
同样的,“n=n-1;”也可以简写为“n--;”
#include<reg51.h>
#include<intrins.h> //使用Nop()需要先声明
#define u8 unsigned char//“unsigned char”是0~255的8位二进制数,我们以后可以简写为“u8”
#define u16 unsigned int//“unsigned int”是0~65535的16位二进制数,我们以后可以简写为“u16”
sfr P3M0=0xb2; //声明 引脚输出模式寄存器
sbit IN=P3^4; //定义PWM输入引脚
sbit OUT=P3^3; //定义输出引脚
u16 time; //记录时间
u16 delay_time; //记录时间
u8 Key1; //把高电平时间变化当做学过的按键处理
u8 Key1_old; //记录Key1过去出现低电平
u8 mode; //模式
u8 step; //步骤
void Delay10us() //@12.000MHz
{
unsigned char i;
_nop_();//使用《舵机测试仪》课程中调整过的延时程序
_nop_();
i = 24;
while (--i);
}
main()
{
OUT=0; //先关闭输出
P3M0=8; //P3.3引脚大电流模式
Key1_old=1;
while(1)
{
Delay10us();//系统周期10us
//模式处理与《七色光芒》几乎相同
if(mode==0)//模式0,关闭
{
OUT=0;
}
if(mode==1)//模式1,打开
{
OUT=1;
}
if(mode==2)//模式2,闪烁
{
delay_time++;
if(delay_time>20000)//每过0.2秒
{
delay_time=0;
if(OUT==1)OUT=0;//变化一次
else OUT=1;
}
}
if(mode==3)//模式3,双闪
{
delay_time++;
if(delay_time>20000)//每过0.2秒
{
delay_time=0;
step++;
if(step>5)step=0;//双闪变化较多,分为6个步骤
}
if(step==0)//步骤0,亮
{
OUT=1;
}
if(step==1)//步骤1,灭
{
OUT=0;
}
if(step==2)//步骤2,亮
{
OUT=1;
}
if(step==3)//步骤3,灭
{
OUT=0;
}
if(step==4)//步骤4,灭
{
OUT=0;
}
if(step==5)//步骤5,灭
{
OUT=0;
}
}
if(IN==1) //收到PWM高电平,开始测量
{
time=0;//先把时间清零
while(IN==1)//如果引脚一直为高电平,一直循环
{
Delay10us();
time=time+1;//每循环一次,就记录了10us时间
}
//引脚变成低电平,循环结束
if(time>90&&time<120)//0.9ms~1.2ms高电平
{
Key1=1;//相当于按键还没按下
}
if(time>180&&time<210)//1.8ms~2.1ms高电平
{
Key1=0;//相当于按键按下
}
if(Key1==1&&Key1_old==0)//如果本次是1并且上次是0,检测到0~1的变化
{
mode++;
if(mode>3)mode=0;//检测到信号的变化,切换模式
}
Key1_old=Key1; //保存
}
}
}
谢谢分享,学习了 好东西,能分享,这是境界啊! {:1_9:}{:1_9:}{:1_9:}{:1_9:}{:1_9:}{:1_9:}
楼主,辛苦了。 学习了谢谢分享 体育日体育 与人突然如 学习了,谢谢大佬分享 现在才知道萝莉大神有这么多教程,我看我是离不开萝莉了{:1_12:}{:1_12:} 真好。开源后有很多玩法。谢谢了 正在慢慢的学代码门外汉吃力啊 路过,
赞赞赞,强势围观
怎么不出视频教程
看程序还是有点懵啊!
本帖最后由 Myth 于 2016-12-15 08:35 编辑
我觉得萝莉老师可以出个收费视频教程。
写这么清楚的教程还不满足,收点智商税也不为过。 嗯嗯,好好学习下……
Myth 发表于 2016-12-15 08:23 static/image/common/back.gif
我觉得泡泡老师可以出个收费视频教程。
写这么清楚的教程还不满足,收点智商税也不为过。 ...
你跑错地方了吧?
Dk. 发表于 2016-12-15 08:33
你跑错地方了吧?
看到五楼的回复有感而发。。。好吧确实说错人了。。。
Myth 发表于 2016-12-15 08:34 static/image/common/back.gif
看到五楼的回复有感而发。。。好吧确实说错人了。。。
好吧,如果收费的话搞不起来的
强寺顶贴
厉害了
厉害,学习一下
路过,,收藏了,感谢楼主的无私分享
在学习,等待更新。。。。。。。。。。。。。。 我爱萝丽爱萝丽 发表于 2016-12-15 04:55
1.1 测量PWM信号
祝贺萝莉大神又开新帖
感谢大神解惑成功点亮jlx12864
我一直想做一个简易的高脉宽测试仪
看了老师的新帖感觉有点眉目了
如果利用电子开关的核心程序
来测接收机输出的高脉宽并用数码管
显示出来是否只要把time拆成个十百千位显示出来就可以 ldy7474 发表于 2016-12-15 23:09
祝贺萝莉大神又开新帖
感谢大神解惑成功点亮jlx12864
我一直想做一个简易的高脉宽测试仪
是的 我爱萝丽爱萝丽 发表于 2016-12-16 00:47
是的
好很好非常好这样就不用外部中断了真好我一直在头痛用15w204外部中断被数码管占用这短短的几行代码完全解决问题哈哈…