学习STC51单片机14(芯片为STC89C52RC)

接下来我们进入学会了HC---SR04 还有舵机那么现在我们将他们融合在一起,用超声波来引导舵机的转动

我们这个最后的成果是做一个智能垃圾桶

成品是这样的,是不是可有意思了

成品视频

  1. 现在我们将舵机的代码和超声波测距模块的代码整合到一起,实现目的超声波来引导舵机的转动

这边基本上就是整合代码了, 这边最主要的就是要把定时器1和定时器0都拿出来用,分别用于舵机的pwm波的计算,还有超声波Echo高电平持续的时,所以我们要在初始化两个定时器,都是一个用法,还有的就是为了main函数里面不会那么多代码,看上去整洁,和需要找问题的时候封装函数。这边openDusbin 和closeDusbin都是封装的函数,还有一个就是超声波定时器里面运行控制位TR要先设置为1,先不能启动,到Echo到高电平时候再开始启动。

加上按键触发舵机

这个就简单了直接加上去就好了

不浪费空间直接把这个地方的代码展示出来

就这样OK了

接着加上了震动传感器

直接上代码

#include "reg52.h"

#include <intrins.h> // ??nop()??

sbit D5 = P3^7; // ??(??<10cm??)

sbit D6 = P3^6; // ??(??=10cm??)

sbit Trig = P1^5; // ???????

sbit Echo = P1^6; // ???????

sbit SG90 = P1^1;

sbit sw1 = P2^1;

sbit vibrate = P3^2;

int count=0;

int jiaodu;

unsigned char i; //¶¨ÒåÑ­>>·±äÁ¿

char mark_vibrate = 0;

void Delay300ms(void) //@11.0592MHz

{

unsigned char data i, j, k;

nop();

i = 3;

j = 26;

k = 223;

do

{

do

{

while (--k);

} while (--j);

} while (--i);

}

void Delay10us(void) //@11.0592MHz

{

unsigned char data i;

i = 2;

while (--i);

}

void Delay50ms() //@11.0592MHz

{

unsigned char i, j;

i = 90;

j = 163;

do

{

while (--j);

} while (--i);

}

void Delay100ms() //@11.0592MHz

{

unsigned char i, j;

i = 183;

j = 105;

do

{

while (--j);

} while (--i);

}

void Time1_Init()

{

TMOD &= 0x0F;

TMOD |= 0x10;

TH1 = 0; //³õʼ>>¯¼ÆÊý¼Ä´æÆ÷

TL1 = 0;

TR1 = 0; //³õʼ²>>Æô¶¯¶¨Ê±Æ÷

}

void Timer0_Init()

{

TMOD &= 0xF0;

TMOD |= 0x01;

TL0 = 0x33;

TH0 = 0xFE;

TF0 = 0;

TR0 = 1;

ET0 = 1;

EA=1;

}

void Delay10ms(void) //@11.0592MHz

{

unsigned char data i, j;

i = 18;

j = 235;

do

{

while (--j);

} while (--i);

}

// ´¥·¢³¬Éù²¨²â¾à

void Trigger_HC_SR04()

{

Trig = 0;

Delay10us();

Trig = 1; // ????10µs????????

Delay10us();

Trig = 0;

}

void checkBefore()

{

// Éϵç×Ô¼ì

for(i=0; i<3; i++) {

D5 = 0;

D6 = 1; // >>ƵÆÁÁ

Delay100ms();

D5 = 1;

D6 = 0; //À¶µÆÁÁ

Delay100ms();

}

}

void openDusbin()

{

D5 = 0; D6 = 1;

jiaodu = 3;//90¶È 1.5msµÄ¸ßµçƽ

count=0;

Delay300ms();//¸ø¶æ>>úµÄʱ¼ä£¬Íê³É¶¯×÷ºó±£³Ö¶¯×÷2s

}

void closeDusbin()

{

D5 = 1; D6 = 0;

jiaodu=1;//0¶È

count=0;

Delay100ms();

}

void sg90Init()

{

jiaodu =1;//³õʼ>>¯½Ç¶È0¶È 0.5msµÄ¸ßµçƽ 1¾ÍÊǶ¨Ê±Æ÷Òç³ö1´Î

count = 0;//count³õʼֵ

SG90 = 1;//Ò>>¿ªÊ¼¸ßµçƽ¿ªÊ¼

Delay10ms();//ΪÁ˵ÚÒ>>´ÎÍêÕûµÄ²¨ÐÎ>>­³ö

}

void Ex0_Init()

{

//´ò¿ªÍⲿÖжÏ

EX0 =1;

//µÍµçƽ´¥·¢

IT0 =0;

}

void main()

{

unsigned int Time; //

unsigned int Distance; //

unsigned int timeout; //³¬Ê±¼ÆÊýÆ÷

//³õʼ>>¯¶¨Ê±Æ÷

Time1_Init();

Timer0_Init();

Ex0_Init();

checkBefore();

sg90Init();

//D5 = 1;

//D6 = 0;

//Delay100ms(); // ???????

while(1)

{

// ¼ì²âEchoµÄ³õʼµçƽ(³õʼÊÇµÍµçÆ½) ×÷Ϊ³õʼÌõ¼þÎÒÃÇÒª½øÐмì²âÒ>>Ï£¬ÓпÉÄܵÄÊÂÇé

if(Echo == 1) {

D5 = 0; D6 = 0; //Ë<<µÆÁÁ£¬±¨¾¯

Delay100ms();

continue;//Èç¹ûÕæµÄÊÇ¸ßµçÆ½ÄÇÎÒÃǾÍÌø¹ý±¾´Î²âÁ¿

}

//´¥·¢²â¾à

Trigger_HC_SR04();

// µÈ´ýEcho±ä¸ß(Ìí¼Ó³¬Ê±£ºÔ¼10ms)

timeout = 10000;

while(Echo == 0 && --timeout);

if(timeout == 0) {

D5 = 0; D6 = 0; // Èç¹û³¬Ê±Ë<<µÆÁÁ(±¨¾¯)

Delay50ms();//±£³Ö±¨¾¯×´Ì¬50ms

continue;

}

// Æô¶¯¶¨Ê±Æ÷

TH1 = 0;

TL1 = 0;

TR1 = 1;

timeout = 65535;

while(Echo == 1 && --timeout);

TR1 = 0;

if(timeout != 0) {

Time = (TH1 * 256 + TL1) * 1.085;

Distance = Time * 17 / 1000;

if(Distance < 10 || sw1 == 0 || mark_vibrate == 1) {

openDusbin();

mark_vibrate=0;

} else {

closeDusbin();

}

}else{

D5 = 1; D6 = 1;

}

Delay300ms();

}

}

void Timer0_Isr() interrupt 1

{

count++;

//ÖØÐ¸ø³õÖµ

TL0 = 0x33;

TH0 = 0xFE;

//¿ØÖÆPWM²¨

if(count<jiaodu){//jiaodu¾ÍÊÇcount´Ó0¿ªÊ¼¸ßµçƽռÁ˶àÉÙµÄÕ¼¿Õ±È

SG90 = 1;

}else{

SG90 = 0;

}

//Ò>>¸öÖÜÆÚ½áÊøÉèÖÃÏÂÒ>>ÖÜÆÚµÄµçÆ½×´Ì¬ºÍcountµÄ´ÎÊý

if(count==40){

SG90=1;

count = 0;

}

}

void Ex0_Handler() interrupt 0

{

mark_vibrate = 1;

}

主要区别就是我们本来有两种理想的方法可以加入震动传感器的,第一种就是使用查询法,但是我们发现了一种现象,怎么好像代码一点问题都没有但是,确不起效果呢???

真相只有一个!!

因为Vibrate被感受振动的时候的低电平没有按键的稳定和持久,所以用查询法是比较不好的,就是比较信号弱,那么按键为什么可以呢??因为跟按键比的话人按按键的时间肯定更长的,对于电路来说已经非常足够了,但是对于传感器他这个是一闪而过的,自然不行,比较弱不好

if(jd_bak !=jd){

count = 0;

D5=1;

D6=0;

Delay1000ms();

这个是我们的关盖子的时候延时有1000ms 我们这个低电平信号的时间都超不过这个时间 ,所以就捕获不到了,所以我们不能用查询法,那么我们既然知道了传感器信号触发时间在这个延时里面,那么我们就可以用中断来解决这个问题

这里我们使用外部中断(新知识点)

因为我们定时器0已经开了EA总中断了,所以这边就没有设置EA

这边我们了解一下外部中断0 EX0就是中断允许位,而且我们震动传感器感受振动的时候会传低电平,所以我们直接用IT0 ,这个是触发条件,和之前不一样,之前的溢出中断,还需要配置定时器模式,时间TH0 TL0 之类的,这个不用,这个只需要这样写

初始化外部中断

外部中断函数

好的继续解决问题 ,那么我们用查询法,没有用,那么我们用外部中断,触发条件是低电平触发,那么我们可以设置一个状态位,这样会比较的稳定

这个引脚也是有固定的,根据手册来的

说明有些引脚是专门有自己的特殊作用的

接着说

因为我们震动传感器只要震动,那就会触发中断,那么走中断函数

让mark_vibrate为1,满足我们的条件

这样就可以用震动的效果来开盖子,也就是操作舵机了,但是别忘了,要将mark_vibrate重置为0,方便下一次的使用;

最后加上蜂鸣器

最后加上我们的蜂鸣器,那我们肯定要将可以用的设备都用上

这个也是很简单,加上两行代码,主要知道他是低电平触发就好了

beep就是蜂鸣器,延时个50ms ,刚刚好,因为长时间真的很吵。

好了结束了

最后优化一下代码,我们发现如果收一直放在超声波前面,他就会一直抽抽抽的,因为我们的代码逻辑是超声波检测后开盖,然后闭盖,但是我们手只要一直放在这,他就会一直执行开盖闭盖,就是舵机还没到0度的时候又要到90度了,那么我们该怎么解决呢

在全局变量处添加状态标志:

int jd_bak=0;

这样子搞就好了,这个是常用的小技巧就等于是设置记录上一次的角度,如果是jdbak和jiaodu是一样的话就说明角度没有变化,那就不执行if里面的语句,if里面的语句就是正常我们开盖各个工作的状态,也就是证明超声波还是检测的到手,人还在丢垃圾,就不会执行closeDusbin关盖子的代码,只有移开之后,超声波检测不到了之后才会去走else的代码,然后开盖和闭盖之后,都要把自己的一个状态给jd_bak,因为对于下一步来讲,现在这一步已经是上一次的角度了,能懂吗......思路就是这样

总结一下:在这边最重要的就是要学会舵机的控制,和超声波测距这两个技能,理解他们的原理,这两个是属于大头技术,和代码,其他,因为基本功能就靠这两个,其他的都是辅助。所以要经常去复习代码....

相关推荐
一枚码农出身的猎头1 小时前
【招聘】硬件工程师/项目经历/产品经理(智能水电表、AIOT硬件方向)
嵌入式硬件·产品经理·智能硬件
【0931】1 小时前
英语学习5.24
学习
龙湾开发1 小时前
C++ vscode配置c++开发环境
开发语言·c++·笔记·vscode·学习
岂是尔等觊觎2 小时前
PCB设计教程【入门篇】——电路分析基础-元件数据手册
经验分享·笔记·嵌入式硬件·学习·pcb工艺
#眼镜&2 小时前
STC89C52RC/LE52RC
嵌入式硬件
jerry6092 小时前
蒙特卡洛树搜索 (MCTS)
人工智能·笔记·深度学习·学习·算法·机器学习
韩明君2 小时前
前端学习笔记——Promis.All
前端·笔记·学习
江畔柳前堤3 小时前
PyQt学习系列11-综合项目:多语言文件管理器
开发语言·网络·python·学习·django·pyqt
MaoXian_n3 小时前
[ARM][汇编] 02.ARM 汇编常用简单指令
arm开发·驱动开发·单片机·嵌入式硬件
爱凤的小光3 小时前
Opencv常见学习链接(待分类补充)
人工智能·opencv·学习