1、功能分析
本项目需要实现,要当物体经过一个点后,记录当前时间,并将时间上传到上位机的功能。分析项目需求,1、需要检测物体经过固定点,因此选用了超声测距模块来检测物体靠近;2、需要记录当前时间,因此选用DS1302时间模块,同时配上纽扣电池,维持模块持续走时功能;3、需要将时间上传,并记录,因此选用常用的蓝牙模块HC-05,使用蓝牙方式传输到上位机。
2、模块介绍
1)、超声模块HC-SR04
该模块TRIG管脚为触发控制信号输入脚,ECHO为回传信号输出脚。当向TRIG脚输入一个大于10uS的高电平后,模块会自动发出8个40KHz的方波,并检测回波。检测到回波后,ECHO会产生高电平响应,该电平持续时间极为方波发送到返回的时间,因此测试距离L=(340/Ton)/2,式中340为声速,Ton为ECHO高电平持续时间,因为时间为方波发送到返回时间,距离为目标距离两倍,因此除以2。该模块技术参数如下表所示。
参数 | 数据 |
---|---|
工作电压 | DC 5V |
工作电流 | 15mA |
测试距离 | 2cm-4m |
测量角度 | 15度 |
2)、时间模块DS1302
该模块可以计算2100年之前的年月日和星期,还具备闰年调整能力。该芯片还具备两个VCC管脚,除VCC1为5V常规供电脚外,还有VCC2管脚可以接纽扣电池作为备用供电,保证掉电走时功能。芯片时间写入与读写采用简单同步串行方式,通信通过3个管脚:1、复位。2、数据线。3、时间线。
3)、蓝牙模块JDY-31
该蓝牙模块为从机。并且兼容HC-05从机。模块采用5V供电,使用UART方式通信。上电后LED闪烁,表明模块正在等待配对,可在蓝牙列表找到改模块,名为JDY-31,初始密码为1234。配对连接后,LED变为常亮。
3、各模块应用程序
//测距模块HC-SR04
int HCSR_TRG(void)
{
if(hcsr_cd == 0) //距上次测距60ms后
{
TRIG = 1; //Trig持续13uS(>10uS)高电平
delay_us(13);
TRIG = 0;
while(!ECHO);//等到Echo为高
HAL_Delay(1);//Echo接收到高电平后等到1mS,L=0.001*340= 34cm
if(ECHO)
hcflag=0; //34cm内没有东西
else
{
hcflag=1; //34cm内有东西
}
hcsr_cd = 60; //每次测距期间,最好有60ms间隔
}
return hcflag;
//仅检测有无物体靠近,不需要测量具体距离,因此不做距离运算
}
//DS1302时间模块
void ds1302_read_time(void)
{
time_buf[1]=ds1302_read_byte(ds1302_year_add); //年
time_buf[2]=ds1302_read_byte(ds1302_month_add); //月
time_buf[3]=ds1302_read_byte(ds1302_date_add); //日
time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时
time_buf[5]=ds1302_read_byte(ds1302_min_add); //分
time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;//秒,屏蔽秒的第7位,避免超出59
time_buf[7]=ds1302_read_byte(ds1302_day_add); //周
if(sec_buf != time_buf[6]) //秒缓存
{
sec_buf = time_buf[6];
LED1 = !LED1;
sec_flag=1;
}
//不断对秒进行读取,每秒改变LED电平,使之闪烁,表明系统正常工作
}
void ds1302_send_time()
{
readtime[0]=(time_buf[0]>>4)+'0'; //分离出年千位
readtime[1]=(time_buf[0]&0x0F)+'0'; //分离出年百位
readtime[2]=(time_buf[1]>>4)+'0'; //分离出年十位
readtime[3]=(time_buf[1]&0x0F)+'0'; //分离出年个位
readtime[4]='-';
readtime[5]=(time_buf[2]>>4)+'0'; //分离出月十位
readtime[6]=(time_buf[2]&0x0F)+'0'; //分离出月个位
readtime[7]='-';
readtime[8]=(time_buf[3]>>4)+'0'; //分离出日十位
readtime[9]=(time_buf[3]&0x0F)+'0'; //分离出日个位
readtime[10]=' ';
readtime[11]=(time_buf[4]>>4)+'0'; //分离出小时十位
readtime[12]=(time_buf[4]&0x0F)+'0'; //分离出小时个位
readtime[13]=':';
readtime[14]=(time_buf[5]>>4)+'0'; //分离出分钟十位
readtime[15]=(time_buf[5]&0x0F)+'0'; //分离出分钟个位
readtime[16]=':';
readtime[17]=(time_buf[6]>>4)+'0'; //分离出秒钟十位
readtime[18]=(time_buf[6]&0x0F)+'0'; //分离出秒钟个位
readtime[20]=':';
//读取的时间为int型,而uart发送为char型,因此需要进行转换,将数字改为对应的ASCII码,即+‘0’
HAL_UART_Transmit(&UART1_Handler,readtime,21,1000); //uart发送时间,通过蓝牙发送到PC
}
蓝牙模块即开启对应IO的Uart功能,注意波特率应设为为9600,一个停止位,无奇偶校验位。此处不再贴出。
4、主程序
初始化各模块后,即等到超声检测模块响应,当模块检测到34CM内有物体时,向DS1302读取当前时间,但由于DS1302不能对毫秒进行计时,因此选择读取系统内部定时器作为毫秒值,该值在每次1302的秒位跳变时清零,重新开始计数。读取系统定时器时间后,即刻将该时间通过蓝牙发送到上位机进行显示。
int main()
{
HAL_Init(); //初始化HAL库
SystemClock_Init(RCC_PLL_MUL9); //设置时钟,72M
SysTick_Init(72);
USART1_Init(9600); //初始化uart,波特率为9600
LED_Init();
ds1302_init();
HC_SRInit();
TRIG =0;
while(1)
{
if(USART1_RX_STA&0x8000) //收到上位机数据后发送“OK”应答信号
{
HAL_UART_Transmit(&UART1_Handler,ack,4,1000);//发送ms数组
USART1_RX_STA=0;
}
if(HCSR_TRG()&&(pastflag==0)) //避免物体持续遮挡时,持续发送时间到PC
{
SendTimetoPC();
pastflag = 1;
}
pastflag = HCSR_TRG();
ds1302_read_time(); //读取时间
if(sec_flag == 1) //每秒清空定时器时间,用作毫秒读取
{
sec_flag = 0;
HAL_WriteTick(0);
}
}
}
void SendTimetoPC(void)
{
ds1302_read_time();
alpha= HAL_GetTick(); //读取毫秒时间
ms[2] = alpha%10+'0';
ms[1] = ((alpha %100) / 10) + '0';
ms[0] = (alpha/100) + '0'; //取出每一位,并 int -> char
ds1302_send_time(); //发送DS1302时间 年-月-日 时:分:秒
HAL_UART_Transmit(&UART1_Handler,ms,5,1000);//发送ms数组 //发送毫秒 :毫秒 \r\n
}