宁波网站建设怎么做,怎么登录已注册的网站,wordpress作者信息,自行车网站模板前言
单片机资源数据包_2023
一、超声波测距原理
二、超声波测距的应用
1.超声波的发射
2.单片机知识补充#xff1a;定时器
3.超声波的接收与计时
4.距离的计算
1#xff09;定时器1为16位自动重载#xff0b;1T11.0592MHz
2#xff09;定时器1为16位自动重载定时器
3.超声波的接收与计时
4.距离的计算
1定时器1为16位自动重载1T11.0592MHz
2定时器1为16位自动重载12T11.0592MHz
3定时器1为16位自动重载1T12MHz
4定时器1为16位自动重载12T11.0592MHz
总结
5.代码完善 三、完整代码展示 前言
关于蓝桥杯比赛时会提供的资料前几篇都有提到这里就不在赘述了只放一个下载链接
单片机资源数据包_2023
除了基础部分的按键、LED灯数码管扫描还有温度传感器AD/DA转化EEPROM存储器RTC之外还有三个模块考试的时候可能会考分别是超声波NE555和串口。近几年的题也是越来越难这三个模块也逐渐出现在了省赛的舞台上当然如果进国赛了这几个模块就都可能考了。提升篇主要针对这三个模块进行介绍。
由于这三个模块比赛时不会提供底层代码所以许多都需要咱们自己来完成所以不同人写的代码差异性可能会更大。此外这些代码会涉及到单片机运行的底层知识关于单片机基础部分的内容提升篇也会尽可能介绍一部分当然如果你不会也没关系文章会教你如何用stc生成或者查数据手册就算不知道原理小背一背也是能自己实现的
一、超声波测距原理
超声波测距的原理很简单就是超声波发送装置先发送一段超声波然后开始计时一直等到接收端接收到反射回来的超声波然后停止计时。记录的这段时间T就是超声波碰到物体在返回的时间超声波的速度一般取340m/s那么物体距离超声波测距装置的距离SV*T/2.很好理解这里就不在画图进行过多介绍了。 发射
接收 这两张分别是在原理图上的超声波发射和接收电路这里也不过多介绍。 在使用超声波之前我们需要正确配置跳线帽。 也就是将J2 2x3的排针的A1和A相连B1与B相连这样超声波发送端就与P10相连了接收端就与P11相连了。换言之超声波的数据发送引脚TXP10数据接收引脚RXP11。
二、超声波测距的应用
第一章已经介绍了超声波测距的原理无非是发送计时接收信号数据处理把时间信息转化为距离信息接下来咱们一一实现着三个步骤
1.超声波的发射
超声波的发送就是需要我们通过TX引脚发送8个40KHz的超声波信号具体为什么测距需要用40KHz的超声波可以自行百度。
我们知道40KHz的信号一个周期就是25微秒那半个周期就约13us。理论上我们只需让TX置为1然后延时13us然后在让TX置为0再延时13us就完成了一个40KHz信号的发射。放在一个for循环内即可完成发送8个40KHz的信号。
但是实际在用的时候延时13us往往不够难以读取到有效的数据当然读者可以自行测试也就修改一个延时函数的功夫这里把延时改为14us如果读取的数据仍旧存在问题如突然跳到一个特别大的值然后又突然回归正常等我们可以适当增加延时。对应到代码上的话我们可以通过微调Delay14us内的i的值来增大延时下面是发送TX与RX的引脚定义与发送超声波的代码 sbit TXP1^0; sbit RXP1^1; void Delay14us(void) //11.0592MHz { unsigned char data i; _nop_(); i 45;//11.0592MHz的单片机使用stc生成14us延时时i等于36这里稍微增大了i让延时增大 while (--i); } void send_wave(void)//发送超声波的函数 { unsigned char i0; for(i0;i8;i)//发送8个40KHz的超声波 { TX1;Delay14us(); TX0;Delay14us(); } } 2.单片机知识补充定时器
在进行第二步计时之前需要先“科普”一下51系列单片机的基础知识。
单片机的数据手册可以通过新版的STC-ISP下载或者点击下边的蓝字进行下载/查看 STC15用户手册点击查看或下载
对于15单片机的定时器也有许多这里只挑对于超声波有用的寄存器讲。
这有一段STC-ISP生成的代码系统频率为11.0592MHz定时器1定时长度为1ms定时器模式为16位自动重时钟频率为1T的定时器1的初始化代码 void Timer1_Init(void) //1毫秒11.0592MHz { AUXR | 0x40; //定时器时钟1T模式 TMOD 0x0F; //设置定时器模式 TL1 0xCD; //设置定时初始值 TH1 0xD4; //设置定时初始值 TF1 0; //清除TF1标志 TR1 1; //定时器1开始计时 } 首先先解释一下为什么是定时器1而不是定时器0呢因为定时器0我们在比赛时百分百要用到而其他定时器或者说需不需要额外的定时器则是需要根据题目要求来判定所以我们定时器0里面有我们需要运行的代码我们可以开一个单独的定时器1来完成超声波注意超声波检查需要一个单独的定时器。
然后我们再看代码第一行AUXR是辅助寄存器用于控制时钟是1T还是12T这个1T就是指不分频或者说1倍分频12T就是指12分频。数据手册上也有但是我们可以直接用STC-ISP来生成1T或者12T的代码就不在赘述了。
对于第二行TMOD寄存器是用来控制定时器模式的定时器主要有定时和计数功能。
定时就是我们经常使用的模式计数器模式我们在NE555会用到。而在超声波测距时我们恰恰是需要定时器去计时。
定时模式又有16位自动重载16位自动重载8位自动重载等模式注意不是所有8051系列单片机都有这些模式的我们一般用16位自动重载自动重载的意思就是定时器溢出之后定时器中断定时器的TL和TH值会自动重新变为初始值而不需要代码重置。 TL1 0xCD; //设置定时初始值 TH1 0xD4; //设置定时初始值 这两个就是刚才提到的TL和TH这里是定时器1的TL和TH所以是TL1和TH1两个都是8位二进制数合在一块刚好是16位二进制其中TH1是高八位TL1是低八位定时器开始计数时他们就会自增1直到溢出。根据它俩的初始值不同我们可以设置出不同时间长度的定时器。
当定时器的TH1和TL1溢出时TF1就会被置为1同时引起定时器中断当然前提是允许中断。
当TR11时定时器开始计时TR10时定时器停止计时。
综上如果我们想用定时器1计时的话就不能一开始就开启定时器计时需要等我们发送完超声波之后再开始计时也就是令TR1 1并且需要先将 TL1和TH1置为0这样方便我们计算。等接收到信号之后我们需要将TR1置为0停止计时此时TH1和TL1存的数据就是从开始计时到结束计时这一段的时间了当然这个时间的单位可不是s呦。除此之外如果长时间没有收到返回的超声波信号一直等到TH1和TL1从0累加到溢出也就是使TF11了那说明没有检测到有效信号我们也需要进行单独处理。
3.超声波的接收与计时
当发送完超声波之后我们立即开始计时。当超声波接收端RX检测到信号时会被置为1也就是当检测到RX为1时说明检测到超声波返回的信号了我们也立刻停止计时这段时间ultar_t就是超声波从发生到反射回来的时间也就是超声波走了一个来回的时间。接下来我们用代码来实现这个功能 send_wave(); TR11;//开始计时 while((RX1)(TF10));//计时的条件没有收到反射回来的超声波且定时器没有溢出 TR10;//停止计时 if(TF11)//定时器溢出说明在一段时间内没收到反射回的超声波代码/硬件/真的是因为距离太远都有可能导致没收到信号 { TF10; ultar_t0;//这个值可以随意设置总之就是如果没有接收到反射回来的超声波时要如何显示的值。。这里是接收到反射回来的超声波就显示0 } else//跳出那个while循环不是因为TF11了就是因为RX0了这个else的情况就是RX0;也可以写成else if(RX0); { ultar_tTH1; ultar_t8; ultar_t|TL1; } 注意这里对TF11的情况也进行了处理也就是没检测到信号的情况。
4.距离的计算
我们已经求得了时间ultar_t但是这个时间的单位不是S也不是ms等需要先进行转化成真正的时间才能用于距离的计算关于距离的计算又涉及到了单片机的知识这里根据单片机设置的频率不同和定时器时钟模式不同分开介绍。
1定时器1为16位自动重载1T11.0592MHz void Timer1_Init(void) //11.0592MHz { AUXR | 0x40; //定时器时钟1T模式 TMOD 0x0F; //设置定时器模式 TL1 0x00; //设置定时初始值 TH1 0x00; //设置定时初始值 TF1 0; //清除TF1标志 //TR1 1; //定时器1开始计时 } 实际的时间ultar_t*1/11059200秒
距离remoteultar_t*1/11059200*340*100/2厘米
2定时器1为16位自动重载12T11.0592MHz void Timer1_Init(void) //1微秒11.0592MHz { AUXR | 0xBF; //定时器时钟1T模式 TMOD 0x0F; //设置定时器模式 TL1 0x00; //设置定时初始值 TH1 0x00; //设置定时初始值 TF1 0; //清除TF1标志 //TR1 1; //定时器1开始计时 } 实际的时间ultar_t*1/11059200*12秒
距离remoteultar_t*1/11059200*12*340*100/2厘米
3定时器1为16位自动重载1T12MHz
初始化函数与1相同
实际的时间ultar_t*1/12000000*12秒
距离remoteultar_t*1/12000000*12*340*100/2厘米
4定时器1为16位自动重载12T11.0592MHz
初始化函数与2相同
实际的时间ultar_t*1/12000000*12秒
距离remoteultar_t*1/12000000*12*340*100/2厘米
总结
实际的距离等于ultar_t*1/主频*分频倍数*340*100/2厘米
对于1T和12T12T就是十二分频简单点说就是定时器记录的最长时间变为1T的十二倍同时精度也变为原来的12倍但是其实1T模式下最远检测的距离等于65535*1/11059200*340*100/2≈100cm100cm已经很远了我用这个超声波时测到70就已经很难了所以一般情况下1T模式而且不对超过100cm进行处理也足够了。
对于主频率比赛的时候有时候会要求使用12MHz的主频近几年来可谓是大概率会这样要求我们需要通过isp更改单片机内部的设置。关于主频的设置我们只需在下载程序之前调一下IRC频率下载程序之后会把单片机内部的设置一同更改了。我们也可以使用“检测MCU”选项检测当前单片机内部的一些设置。 5.代码完善
与LED灯闪烁类似我们并不期望无时无刻地发送与接收而是每隔一定时间发送接受一次再加上刚才关于距离计算的代码以及每轮之后将相关数据清空我们可以总结出超声波测距过程的代码 if(count_ultar1) { count_ultar0; send_wave(); TR11;//开始计时 while((RX1)(TF10));//计时的条件没有收到反射回来的超声波且定时器没有溢出 TR10;//停止计时 if(TF11)//定时器溢出说明在一段时间内没收到反射回的超声波代码/硬件/真的是因为距离太远都有可能导致没收到信号 { TF10; ultar_t0;//这个值可以随意设置总之就是如果没有接收到反射回来的超声波时要如何显示的值。。这里是接收到反射回来的超声波就显示0 } else//跳出那个while循环不是因为TF11了就是因为RX0了这个else的情况就是RX0;也可以写成else if(RX0); { ultar_tTH1; ultar_t8; ultar_t|TL1; } remote(unsigned int)(ultar_t*0.0015);//定时器1是1T。注意需要修改Timer1_Init()内的内容 //remote(unsigned int)(ultar_t*0.0184);//定时器1是12T ultar_t0; TH10; TL10; } Delay100ms(); } count_ultar为0时200ms之后会被定时器置为1也就是每200ms发送接收一次超声波。 unsigned int ultar_t0; bit count_ultar0; void Timer0_Isr(void) interrupt 1 { if(count_ultar0) { if(count_200200) { count_ultar1; count_2000; } } 三、完整代码展示
现在完成以下功能对刚才介绍的功能进行演示
1.单片机主频率设置为11.0592MHz
2.通过超声波读取距离信息并显示到前三位数码管上单位CM
main.c
#include stc15.h
#include intrins.hcode unsigned char Seg_Table[]
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0xFF
};#define NIXIE_CHECK() P2|0xC0;P20xDF;P20x1F;
#define NIXIE_ON() P2|0xE0;P20xFF;P20x1F;void Timer0_Init(void); //1毫秒11.0592MHz
void Delay100ms(void); //11.0592MHz
void send_wave(void);
void Timer1_Init(void); //1毫秒11.0592MHzunsigned char location0;
unsigned char Nixie_num[]{10,10,10,10,10,10,10,10};
bit count_ultar0;//时间标志位
unsigned int remote0;//距离信息
unsigned int ultar_t0;//超声波往返的时间信息注意必须用uint不能用uchar
sbit TXP1^0;//定义超声波的TX
sbit RXP1^1;//定义超声波的RX
void main()
{Timer0_Init();Timer1_Init();EA1;Delay100ms();while(1){if(count_ultar1){count_ultar0;send_wave();TR11;//开始计时while((RX1)(TF10));//计时的条件没有收到反射回来的超声波且定时器没有溢出TR10;//停止计时if(TF11)//定时器溢出说明在一段时间内没收到反射回的超声波代码/硬件/真的是因为距离太远都有可能导致没收到信号{TF10;ultar_t0;//这个值可以随意设置总之就是如果没有接收到反射回来的超声波时要如何显示的值。。这里是接收到反射回来的超声波就显示0}else//跳出那个while循环不是因为TF11了就是因为RX0了这个else的情况就是RX0;也可以写成else if(RX0);{ultar_tTH1;ultar_t8;ultar_t|TL1;}remote(unsigned int)(ultar_t*0.0015);//定时器1是1T。注意需要修改Timer1_Init()内的内容//remote(unsigned int)(ultar_t*0.0184);//定时器1是12Tultar_t0;TH10;TL10;}//数码管显示距离信息Nixie_num[0]remote/100%10;Nixie_num[1]remote/10%10;Nixie_num[2]remote/1%10;Delay100ms();}
}unsigned int count_2000;
void Timer0_Isr(void) interrupt 1
{P00x01location;NIXIE_CHECK();P0Seg_Table[Nixie_num[location]];NIXIE_ON();if(location8)location0;if(count_ultar0)//如果标志位为0{if(count_200200)//200ms后,将时间标志位置为1{count_ultar1;count_2000;}}
}void Timer0_Init(void) //1毫秒11.0592MHz
{AUXR | 0x80; //定时器时钟1T模式TMOD 0xF0; //设置定时器模式TL0 0xCD; //设置定时初始值TH0 0xD4; //设置定时初始值TF0 0; //清除TF0标志TR0 1; //定时器0开始计时ET0 1; //使能定时器0中断
}
void Timer1_Init(void) //1毫秒11.0592MHz
{AUXR | 0x40; //定时器时钟1T模式//AUXR 0xBF; //定时器时钟12T模式TMOD 0x0F; //设置定时器模式TL1 0x00; //设置定时初始值TH1 0x00; //设置定时初始值TF1 0; //清除TF1标志//TR1 1; //定时器1开始计时
}void Delay100ms(void) //11.0592MHz
{unsigned char data i, j, k;_nop_();_nop_();i 5;j 52;k 195;do{do{while (--k);} while (--j);} while (--i);
}
void Delay14us(void) //11.0592MHz
{unsigned char data i;_nop_();i 45;//11.0592MHz的单片机使用stc生成14us延时时i等于36这里稍微增大了i让延时增大while (--i);
}void send_wave(void)//发送超声波的函数
{unsigned char i0;for(i0;i8;i)//发送8个40KHz的超声波{TX1;Delay14us();TX0;Delay14us();}
}