目录
一、相关知识
1.关于超声波模块
2.注意事项
二、所要实现的功能
三、代码实现
1. 参数定义
2.138译码器通道选择函数
3.初始化系统
4.延时函数
5.单个数码管显示函数
6.数码管动态显示
7.定时器初始化函数
8.定时器0执行函数
9.12us延时产生40KHz频率
10.发送超声波信号函数
11.计算测得距离函数
12.完整代码
四、运行图片
蓝桥杯板子上的基础模块到这里也就告一段落了,基本上就是这些模块,比赛的时候就是各种模块和定时器之间的配合使用。
一、相关知识
1.关于超声波模块
CX20106A是一款红外线检波接收的专用芯片,常用于电视机红外遥控接收器。当CX20106A接收到40KHz的信号时(第五脚200K的电阻决定了其频率为40KHz),会在OUT脚输出一个低电平下降脉冲。这个信号甚至可以接到单片机的外部中断引脚,作为中断信号的输入。
2.注意事项
①需要先发送超声波信号,那么我们产生8个40KHz的信号(40KHz周期就是25us,由于是个奇数,所以取周期为24us,半个周期12us);
②超声波测距公式为:x = 340 * t / 2 (m/s)。声音在空气中传播速度大约为340m/s,具体数值会随温度变化。注意单位,并且除以2是因为包括往返两次距离;
③满足测距的条件为接收端收到信号,并且定时器计数没有溢出。
二、所要实现的功能
用超声波测距测出距离并且在数码管上进行显示。
三、代码实现
1. 参数定义
#include <STC15F2K60S2.H>
#include "Delay_ms.h"
#include "intrins.h"
sbit TX = P1^0; // 超声波发送端
sbit RX = P1^1; // 超声波接收端
unsigned int distance = 0; // 超声波测得距离
unsigned char code SMG_Duanma[19] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0x00
}; // 0~F - . 全部
2.138译码器通道选择函数
// 通道选择函数
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = (P2 & 0x1f) | 0x00; // 0
break;
case 4:
P2 = (P2 & 0x1f) | 0x80; // Y4C
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; // Y5C
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; // Y6C
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; // Y7C
break;
}
}
3.初始化系统
// 初始化系统
void System_Init(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff;
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
// 关闭通道选择
HC138_Init( 0 );
}
4.延时函数
void Delay_tms( unsigned int t )
{
int i;
while( t-- )
{
for( i=115 ; i>0 ; i-- )
{}
}
}
5.单个数码管显示函数
// 数码管显示
void SMG_Light( unsigned char pos , unsigned char dat)
{
HC138_Init( 6 );
P0 = 0x01 << pos;
HC138_Init( 7 );
P0 = dat;
}
6.数码管动态显示
// 数码管显示
void SMG_Show(void)
{
SMG_Light( 0 , 0xff );
Delay_tms( 5 );
SMG_Light( 1 , 0xff );
Delay_tms( 5 );
SMG_Light( 2 , 0xff );
Delay_tms( 5 );
SMG_Light( 3 , 0xff );
Delay_tms( 5 );
SMG_Light( 4 , 0xff );
Delay_tms( 5 );
SMG_Light( 5 , SMG_Duanma[ distance / 100 ] );
Delay_tms( 5 );
SMG_Light( 6 , SMG_Duanma[ distance / 10 % 10 ] );
Delay_tms( 5 );
SMG_Light( 7 , SMG_Duanma[ distance % 10 ] );
Delay_tms( 5 );
}
7.定时器初始化函数
// 定时器0初始化
void Timer0_Init(void)
{
TMOD = 0x00;
ET0 = 1;
TR0 = 0;
EA = 1;
TH0 = 0;
TL0 = 0;
TF0 = 0; // 清除溢出标志位,当定时器0溢出时,TF0 = 1
}
8.定时器0执行函数
// 定时器0执行函数
void Timer0() interrupt 1
{
TH0 = 0;
TL0 = 0;
}
9.12us延时产生40KHz频率
// 12us延时,产生40KHz频率
void Delay12us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
10.发送超声波信号函数
// 发送超声波信号,产生8个40KHz的信号(那么周期就是25us,由于是个奇数,所以取周期为24us,半个周期12us)
void Send_Wave(void)
{
int i;
for( i=0 ; i<8 ; i++ )
{
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
11.计算测得距离函数
// 超声波测距-公式为:x = 340 * t / 2 (m/s)。注意单位,并且除以2是因为往返距离
void Get_Distance(void)
{
Send_Wave(); // 发送超声波信号
TR0 = 1; // 定时器0启动,开始测距
while( ( RX == 1 ) && ( TF0 == 0 ) ); // 接收端收到信号,并且定时器计数没溢出
TR0 = 0; // 关闭定时器,计算时间
if( TF0 == 0 )
{
// time = TH0;
// time <<= 8;
// time |= TL0; // 获取时间t
// distance = 340 * ( ( TH0 << 8 ) | TL0 ) / 1000000 / 2 * 100; // 计算距离,乘以100是把米换算为厘米
distance = ( ( TH0 << 8 ) | TL0 ) * 0.017;
SMG_Show();
}
else
{
TF0 = 0;
distance = 999;
SMG_Show();
}
TH0 = 0; // 时间清零
TL0 = 0;
}
12.完整代码
#include <STC15F2K60S2.H>
#include "Delay_ms.h"
#include "intrins.h"
sbit TX = P1^0; // 超声波发送端
sbit RX = P1^1; // 超声波接收端
unsigned int distance = 0; // 超声波测得距离
unsigned char code SMG_Duanma[19] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0x00
}; // 0~F - . 全部
// 通道选择函数
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = (P2 & 0x1f) | 0x00; // 0
break;
case 4:
P2 = (P2 & 0x1f) | 0x80; // Y4C
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; // Y5C
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; // Y6C
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; // Y7C
break;
}
}
// 初始化系统
void System_Init(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff;
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
// 关闭通道选择
HC138_Init( 0 );
}
// 12us延时
void Delay12us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
// 数码管显示
void SMG_Light( unsigned char pos , unsigned char dat)
{
HC138_Init( 6 );
P0 = 0x01 << pos;
HC138_Init( 7 );
P0 = dat;
}
// 数码管显示
void SMG_Show(void)
{
SMG_Light( 0 , 0xff );
Delay_tms( 5 );
SMG_Light( 1 , 0xff );
Delay_tms( 5 );
SMG_Light( 2 , 0xff );
Delay_tms( 5 );
SMG_Light( 3 , 0xff );
Delay_tms( 5 );
SMG_Light( 4 , 0xff );
Delay_tms( 5 );
SMG_Light( 5 , SMG_Duanma[ distance / 100 ] );
Delay_tms( 5 );
SMG_Light( 6 , SMG_Duanma[ distance / 10 % 10 ] );
Delay_tms( 5 );
SMG_Light( 7 , SMG_Duanma[ distance % 10 ] );
Delay_tms( 5 );
}
// 定时器0初始化
void Timer0_Init(void)
{
TMOD = 0x00;
ET0 = 1;
TR0 = 0;
EA = 1;
TH0 = 0;
TL0 = 0;
TF0 = 0; // 清除溢出标志位,当定时器0溢出时,TF0 = 1
}
// 定时器0执行函数
void Timer0() interrupt 1
{
TH0 = 0;
TL0 = 0;
}
// 发送超声波信号,产生8个40KHz的信号(那么周期就是25us,由于是个奇数,所以取周期为24us,半个周期12us)
void Send_Wave(void)
{
int i;
for( i=0 ; i<8 ; i++ )
{
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
// 超声波测距-公式为:x = 340 * t / 2 (m/s)。注意单位,并且除以2是因为往返距离
void Get_Distance(void)
{
Send_Wave(); // 发送超声波信号
TR0 = 1; // 定时器0启动,开始测距
while( ( RX == 1 ) && ( TF0 == 0 ) ); // 接收端收到信号,并且定时器计数没溢出
TR0 = 0; // 关闭定时器,计算时间
if( TF0 == 0 )
{
// time = TH0;
// time <<= 8;
// time |= TL0; // 获取时间t
// distance = 340 * ( ( TH0 << 8 ) | TL0 ) / 1000000 / 2 * 100; // 计算距离,乘以100是把米换算为厘米
distance = ( ( TH0 << 8 ) | TL0 ) * 0.017;
SMG_Show();
}
else
{
TF0 = 0;
distance = 999;
SMG_Show();
}
TH0 = 0; // 计算一次距离,时间清零一次
TL0 = 0;
}
int main(void)
{
System_Init();
Timer0_Init();
while(1)
{
Get_Distance();
}
}