完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
五、避障小车制作
1.超声波模块接线 从商家的资料知道,TRIG和ECHO接单片机引脚,而OUT口,在我学习这个模块的过程中发现很多文章都没用这个东西,因此在这里我也不打算用,VCC口接5V。 从上篇的原理图看,我本来打算超声波的TRIG和ECHO引脚分别接PB8和PB9的,但在上篇中我也提到了我的c8t6的PB引脚有问题。所以在接线时,我放弃了接PB引脚改为接PA11、PA12。 如图,通过飞线的方法从PA11、PA12中引出两条线在连接超声波,于是超声波就可以用了。 2.工作原理 还是商家的资料,我们就知道了超声波模块的大致原理。更加详细的超声波介绍可以看看这个文章:STM32的超声波测距程序 3. 超声波避障程序 cs.c #include “cs.h” #include “stm32f10x.h” #include “delay.h” /*记录定时器溢出次数*/ uint overcount=0; /*设置中断优先级*/ void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructer; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructer.NVIC_IRQChannelSubPriority=0; NVIC_InitStructer.NVIC_IRQChannel=TIM4_IRQn; NVIC_InitStructer.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructer); } /*初始化模块的GPIO以及初始化定时器TIM2*/ void CH_SR04_Init(void) { GPIO_InitTypeDef GPIO_InitStructer; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); /*TRIG触发信号*/ GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz; //原来接PB 8、PB 9不能用,后改为PA 11,PA 12就能用 GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructer.GPIO_Pin=GPIO_Pin_11; GPIO_Init(GPIOA, &GPIO_InitStructer); /*ECHO回响信号*/ GPIO_InitStructer.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_InitStructer.GPIO_Pin=GPIO_Pin_12; GPIO_Init(GPIOA, & GPIO_InitStructer); GPIO_ResetBits(GPIOA,GPIO_Pin_4); /*定时器TIM2初始化*/ TIM_DeInit(TIM4); TIM_TimeBaseInitStructer.TIM_Period=999;//定时周期为1000 TIM_TimeBaseInitStructer.TIM_Prescaler=71; //分频系数72 TIM_TimeBaseInitStructer.TIM_ClockDivision=TIM_CKD_DIV1;//不分频 TIM_TimeBaseInitStructer.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructer); TIM_ClearFlag(TIM4,TIM_FLAG_Update); TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//开启更新中断 NVIC_Config(); TIM_Cmd(TIM4,DISABLE);//关闭定时器使能 } float Senor_Using(void) //测距函数 { float length=0,sum=0; u16 tim; uint i=0; /*测5次数据计算一次平均值*/ while(i!=5) { PAout(11)=1; //拉高信号,作为触发信号 delay_us(20); //高电平信号超过10us PAout(11)=0; /*等待回响信号*/ while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_12)==RESET); TIM_Cmd(TIM4,ENABLE);//回响信号到来,开启定时器计数 i+=1; //每收到一次回响信号+1,收到5次就计算均值 while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_12)==SET);//回响信号消失 TIM_Cmd(TIM4,DISABLE);//关闭定时器 tim=TIM_GetCounter(TIM4);//获取计TIM4数寄存器中的计数值,一边计算回响信号时间 length=(tim+overcount*1000)/58.0;//通过回响信号计算距离 sum=length+sum; TIM4-》CNT=0; //将TIM4计数寄存器的计数值清零 overcount=0; //中断溢出次数清零 delay_ms(10); } length=sum/5; return length;//距离作为函数返回值 } void TIM4_IRQHandler(void) //中断,当回响信号很长是,计数值溢出后重复计数,用中断来保存溢出次数 { if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除中断标志 overcount++; } } cs.h #ifndef __CS_H #define __CS_H #include “stm32f10x.h” #include “delay.h” #include “sys.h” #define uint unsigned int #define TRIG_Send PBout(8) #define ECHO_Reci PBin(9) void CH_SR04_Init(void); //超声波模块相关配置初始化 float Senor_Using(void); //测距函数,返回值即为距离 void NVIC_Config(void); //中断配置 #endif 避障主函数 注意因为我没用舵机,所以自己打算通过小车自身的转动来代替舵机,于是就有了这样奇怪的代码。 //头文件 #include “stm32f10x.h” #include “moter.h” #include “cs.h” #include “xunji.h” #include “delay.h” #include “sys.h” #include “lanya.h” int main(void) { float length_res[5]; //用来存放测距结果 SystemInit(); // 配置系统时钟为72M delay_init(); //延时初始化 xunji_config(); //循迹初始化 TIM3_PWM_Init(); //电机pwm TIM3 CH_SR04_Init(); //超声波定时器 TIM4 USART_Config(); //蓝牙串口 //避障循环 while(1) { length_res[0] =Senor_Using(); //测前方距离放在数组里 delay_ms(100); if(length_res[0]》30.00) //如果前方距离大于30cm 前进 { CarGo(); } if(length_res[0]《30.00) //如果前方距离小于30厘米 停车测左右距离 { CarStop(); delay_ms(100); CarRightAround(); //掉头 delay_ms(1000); CarStop(); delay_ms(100); CarLeftAround(); delay_ms(370); //检测左边约45度的距离 CarStop(); delay_ms(100); length_res[1] =Senor_Using(); //把测量结果放进数组 CarRightAround(); delay_ms(600); //检测右边约45度的距离 CarStop(); delay_ms(100); length_res[4] =Senor_Using(); //把测量结果放进数组 CarLeftAround(); delay_ms(370); //回正 CarStop(); delay_ms(100); if(length_res[1]》length_res[4]) //如果左边的距离大于右边的距离 { do { length_res[0] =Senor_Using(); //重复测前方的距离同时左转 delay_ms(10); CarLeft(); delay_ms(100); } while(length_res[0]《30.00); //一直转到前方距离大于30cm } if(length_res[1]《length_res[4]) //如果右边的距离大于左边的距离 { do { length_res[0] =Senor_Using(); //重复测前方的距离同时右转 delay_ms(10); CarRight(); delay_ms(100); } while(length_res[0]《30.00); //一直转到前方距离大于30cm } } } } 六、蓝牙遥控小车制作 1.模块介绍+接线 JDY-31有六个脚我只用了这四个就可以实现蓝牙控制。 引脚说明 1 、 TXD 串口输出,接开发板上的UART-Rx 2 、 RXD 串口输入,接开发板上的UART-Tx 3、 GND接地 4、 VCC接3.6V-6V(我接了5V) 接线 RXD接PA9 TXD接PA10 3.蓝牙遥控小车程序 lanya.c #include “lanya.h” static void NVIC_Configuration(void) //中断配置 { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 } void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 // USART1_TX PA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9 //USART1_RX PA.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10 /* USARTx configured as follow: - BaudRate = 9600 baud 波特率 - Word Length = 8 Bits 数据长度 - One Stop Bit 停止位 - No parity 校验方式 - Hardware flow control disabled (RTS and CTS signals) 硬件控制流 - Receive and transmit enabled 使能发送和接收 */ // 配置串口的工作参数 // 配置波特率 USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); // 串口中断优先级配置 NVIC_Configuration(); // 使能串口接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断 // 使能串口 USART_Cmd(USART1, ENABLE); // 清除发送完成标志 //USART_ClearFlag(USART1, USART_FLAG_TC); } //串口的中断服务函数 void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) //检查指定的 USART1 中断发生与否 { USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除 USART1 的中断待处理位 } } lanya.h #ifndef __LANYA_H #define __LANYA_H #include “stm32f10x.h” #include 《stdio.h》 void USART_Config(void); #endif 主函数 //头文件 #include “stm32f10x.h” #include “moter.h” #include “cs.h” #include “xunji.h” #include “delay.h” #include “sys.h” #include “lanya.h” u8 flag; //定义一个蓝牙的标志位 int main(void) { SystemInit(); // 配置系统时钟为72M delay_init(); //延时初始化 xunji_config(); //循迹初始化 TIM3_PWM_Init(); //电机pwm TIM3 CH_SR04_Init(); //超声波定时器 TIM4 USART_Config(); //蓝牙串口 //蓝牙数据接收判断函数 while(1) { flag= USART_ReceiveData(USART1); //返回 USART1 最近接收到的数据 switch(flag) { case ‘0’: CarStop(); break ; case ‘1’: CarLeft(); break ; case ‘2’: CarRight(); break ; case ‘3’: CarBack(); break ; case ‘4’: CarGo(); break ; case ‘5’: CarLeftAround(); break ; case ‘6’: CarRightAround(); break ; default: CarStop(); break ; } } } 4.蓝牙串口APP APP设置介绍 总结 至此,制作智能小车的经历就记录和分享完了。 请记住:本文的智能小车的代码都只是为了实现每个模块能使用,所以这些代码只处于能用的水准。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
568浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 13:20 , Processed in 0.830299 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号