建立免费个人网站个人可以做社区网站
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:45
当前位置: 首页 > news >正文
建立免费个人网站,个人可以做社区网站,优质视频素材网站,工商银行手机银行app下载项目框图 ST-link接线 实物图#xff1a; 正面#xff1a; 反面#xff1a; 相关内容 使用L9110S电机模块 电机驱动模块L9110S详解 | 良许嵌入式 测速模块 语音模块SU-03T 网站#xff1a;智能公元/AI产品零代码平台 一、让小车动起来 新建文件夹智能小车项目 在里面…项目框图 ST-link接线 实物图 正面 反面 相关内容 使用L9110S电机模块 电机驱动模块L9110S详解 | 良许嵌入式 测速模块 语音模块SU-03T 网站智能公元/AI产品零代码平台 一、让小车动起来 新建文件夹智能小车项目 在里面复制19-串口打印功能 重命名为01-让小车动起来 新建文件夹motor如下图所示 打开项目 加载文件 先更改引脚 然后分装函数 前进后退左转右转停止函数 PB0、PB1引脚控制的是左轮 当PB0引脚为高电平PB1引脚为低电平的时候左轮向前走 当PB0引脚为低电平PB1引脚为高电平的时候左轮向后走 当PB0引脚与PB1引脚电平相同的时候左轮停止 PB2、PB10引脚控制的是右轮 当PB2引脚为高电平PB10引脚为低电平的时候右轮向前走 当PB2引脚为低电平PB10引脚为高电平的时候右轮向后走 当PB2引脚与PB10引脚电平相同的时候右轮停止 #include motor.h//初始化电机函数 void motor_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开时钟HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟//调用GPIO初始化函数gpio_initstruct.Pin GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10; // 两个LED对应的引脚gpio_initstruct.Mode GPIO_MODE_OUTPUT_PP; // 推挽输出gpio_initstruct.Pull GPIO_PULLUP; // 上拉gpio_initstruct.Speed GPIO_SPEED_FREQ_HIGH; // 高速HAL_GPIO_Init(GPIOB, gpio_initstruct);motor_stop(); } //前进 void motor_go_forward(void) {//左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);//右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); } //后退 void motor_go_backward(void) {//左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);//右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); } //左转 void motor_go_left(void) {//左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);//想要一个轮子不动就让它两个引脚都等于reset或者setHAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);//右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); } //右转 void motor_go_right(void) {//左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);//右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); } //停止 void motor_stop(void) {//左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); //右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); }二、串口控制小车 注意串口控制小车与蓝牙控制小车类似 想要实现的效果是 M1:前进 M2:后退 M3:左转 M4:右转 其他M停止 复制01-让小车动起来 重命名为02-串口控制小车 将蓝牙模块的文件粘贴到改项目中进行修改 打开项目文件 加载文件 将蓝牙模块的串口2代码粘贴到02项目中 将接收到的串口2的数据打印到串口1中 编译 调试代码 烧录 记得把串口2连接上用两个串口助手显示结果 串口助手1-连接串口1-用于接收串口2发送过来的数据-波特率是115200 串口助手2-连接串口2-用于发送数据M1\M2\M3\M4\其他数据-波特率是9600 注意在烧录完代码之后一切准备就绪发现在串口2中发送输入串口1接收不到这时候不要慌先把两个串口助手断开然后再次选择串口号连接串口这时候在输入数据就会有反应了。 注意如果你的电脑中usb接口不足板子选择使用面包板接电就会出现一个小错误面包板中只有一个3V3在供电这个时候使用杜邦线给32板子接电就会出现在串口2中输入M1前进之后再输入M2后退小车会停下来串口助手1中会显示hello word。如下图所示 再次输入M2小车会后退这是因为供电不足电压不稳所以想要达到输入M1就是前进输入M2就是后退解决办法需要使用USB外接电源供电。 三、蓝牙控制小车 将上述的串口控制小车中的串口2所接的引脚替换成蓝牙模块 然后手机连接蓝牙 输入数据小车就会行动 要注意蓝牙所设置的波特率不然不能正确接收数据 蓝牙当初所设置的波特率是115200所以要在主函数中调用蓝牙初始化函数时更改波特率 四、点动控制小车 当摁下前进按键的时候小车就会疯狂的向前走那么现在要实现当摁一下前进小车就前进一下实现点动控制小车。 复制项目文件02重命名为点动控制小车 打开项目 只添加这两行代码即可 剩下的在软件上完成 原理 在主函数的while函数中有一个停止的函数小车最开始的状态就是停止状态想让小车开始移动就要打断这个while循环所以就要用到中断所以点动的代码要在中断函数中写所以在中断回调函数中有让其移动的代码将这个代码延时一下比如10ms。那么程序在执行完移动代码之后就会执行这个延时函数然后再回到while循环中执行停止小车的函数所以就实现了10ms的点动而需要长时间的移动小车就要在软件中找补了。 在串口助手中 把蓝牙摘下去换上串口2记得串口2的波特率已经改为115200了 串口助手2可以使用数据流循环发送设置好发送的间隔就可以实现长时间的移动。 设置的时间太长没办法将小车动作连续起来 时间太短小车跑的太快 其实这个整套下来像是将片段的小车移动整合起来变成一个连续的小车移动 将小车独立出来的接线 现在小车的串口2连接蓝牙模块 ST-LINK和串口1可以在烧录完代码之后拔掉 32的5V电压和GND可以连接面包板的正负极 面包板的电压计算四块1.5V的电压1.546V 五、PWM调速控制小车 小车接收到不同的电压值跑的速度也是不一样的 电压越大速度越快并不是电压越大越好小心烧掉板子 为了避免小车一开始速度就很快可以使用PWM调速 小车的电机与32板子连接的电压是3.3V所以小车全速前进的时候电压是3.3V如果把电压降低至2V小车的速度就会降下来1.5V更慢。 复制01项目重命名为04-PWM调速控制小车 复制呼吸灯实验中BSP文件中的pwm文件夹 粘贴到04-PWM调速控制小车的BSP文件中 打开项目加载文件 记得加载HAL库中的定时器文件tim.ctim_er.c 编译无错 修改pwm文件 将这个的TIM4修改为TIM2TIM2的两个通道在这里用到 因为TIM4的两个通道GPIO口可能会占用到 这里就要注意做项目前要对资源进行合理的分配这很重要 这里需要更改电机的引脚 想要达成每个电机使用不同的通道 这里不用看PB引脚的通道因为左轮用一个通道右轮用一个通道所以PB引脚的通道并不重要不需要关注。 这里注意通用定时器 代码修改如下 这里注意原来我pwm_init函数中的参数是psc在前arr在后然后主函数中声明pwm_init();时写的参数20-1,72-1,这里传参的顺序错了所以在这里pwm文件中调换了psc和arr的顺序。 复习CCR是什么 主函数代码如下 产生的疑问 STM33F103C8T6智能小车项目中使用循迹PWM调速小车时小车电机实际接线的引脚是PA0接A-1A、PB1接A-1B、PA1接B-1A、PB10接B-1B和PWM定义的接口引脚是PA0和PA1但是在小车电机文件中定义的引脚是PB0接A-1A、PB1接A-1B、PB2 接B-1A、PB10接B-1B这时候使用pwm调节CRR的值可以控制小车车速但是为什么项目所定义的电机文件中的引脚和小车实际接线的引脚不一致的情况下小车还可以动 DeepSeek回答 关于STM32F103C8T6智能小车项目中电机实际接线与代码中定义的引脚不一致但小车仍然可以动的原因。我需要仔细分析这个问题并给出合理的解释。 首先用户提到实际接线是PA0接A-1APB1接A-1BPA1接B-1APB10接B-1B。而代码中定义的引脚是PB0接A-1APB1接A-1BPB2接B-1APB10接B-1B。但使用PWM调节CCR应该是PWM的捕获/比较寄存器来控制车速小车却能动。这看起来矛盾因为引脚定义不一致按理说电机可能不会正常工作或者完全不动。 我需要考虑几个可能性 硬件接线错误但代码中错误地配置了其他引脚比如虽然代码定义的是PB0但实际可能错误地配置了PA0导致两者巧合地对应。这可能是因为代码中的初始化部分错误地将PB0配置为PA0或者存在其他配置问题。 复用功能或引脚映射STM32的某些引脚可能有复用功能或者通过重映射功能改变了实际控制的引脚。例如定时器的通道可能被映射到不同的引脚导致代码中定义的PB0实际上输出到了PA0。 代码中的引脚配置与实际不符但部分引脚正确例如虽然A-1A和B-1A的引脚定义错误但A-1B和B-1B的PB1和PB10正确这样可能有一半的电机驱动正确而另一半可能被其他因素如共地或短路导致电机仍能转动但表现异常。 PWM信号通过其他方式传递可能存在飞线或电路板上的短路导致PWM信号从代码定义的引脚传输到了实际接线的引脚。 接下来我需要进一步分析这些可能性。首先检查代码中的GPIO初始化部分查看是否正确配置了引脚。例如如果代码中错误地将PB0配置为PWM输出但实际硬件连接到了PA0但PA0可能被配置为其他功能如普通GPIO输出这时候如果PA0被设置为高电平可能电机一直全速运行而PWM调节无效。但用户提到可以通过调节CCR控制车速这说明PWM可能确实在起作用。 另一种可能是虽然代码中定义的引脚是PB0、PB2但实际使用的定时器通道对应的引脚是PA0和PA1。例如定时器2的通道1和2可能默认映射到PA0和PA1而代码中错误地配置了PB0和PB2但由于没有重映射实际输出仍然在PA0和PA1。这种情况下即使代码中试图配置PB0和PB2为PWM但由于这些引脚对应的定时器通道不同可能无法输出但用户的情况却可以工作这似乎矛盾。 或者用户可能使用了不同的定时器例如PA0和PA1属于定时器2而PB0、PB1属于定时器3但代码中错误地配置了定时器3到PB0但实际硬件连接到了定时器2的PA0这时候如果代码中错误地配置了定时器3但实际没有启用而PA0可能被其他代码如直接GPIO控制驱动这可能无法解释PWM调速的有效性。 可能需要考虑代码中的具体配置比如使用的定时器和通道以及引脚重映射情况。例如STM32的某些定时器通道可以重映射到其他引脚如果代码中启用了重映射那么实际输出引脚会改变。例如定时器3的通道1默认是PA6但部分重映射后可能是PB4完全重映射可能是PC6。如果用户代码中配置了重映射但实际硬件连接到了默认引脚或者相反可能导致引脚不一致但信号仍然输出。 另外用户提到调节CCR可以控制车速这说明PWM信号确实在正确的引脚上输出。因此可能的情况是虽然代码中定义的引脚名称和实际接线不一致但实际配置的定时器通道对应的物理引脚是正确的。例如代码中定义PB0但实际配置的是定时器3通道1而该通道的引脚可能是PB0但硬件连接到了PA0这似乎矛盾除非存在硬件错误或飞线。 或者用户可能混淆了引脚的定义例如在代码中错误地命名了引脚但实际配置的是正确的引脚。比如代码中将电机A的PWM引脚定义为PB0但在初始化时实际配置的是PA0这可能是代码中的注释或变量名错误而实际代码正确。 另一个可能性是电机驱动模块的使能端被固定启用例如ENA和ENB被接高电平此时电机的方向由IN1和IN2控制而PWM信号实际上控制的是速度但若方向引脚配置正确即使PWM引脚错误地输出高电平电机也会全速运转。但用户提到可以调节速度所以PWM必须有效。 综合来看最可能的解释是代码中实际配置的引脚与变量名或注释中的定义不一致但初始化部分正确配置了实际接线的PA0和PA1。例如虽然在代码的注释或变量名中写的是PB0和PB2但初始化函数中正确地设置了PA0和PA1作为PWM输出。这可能是一个代码书写错误但实际配置正确导致电机正常运行。 或者可能存在引脚复用的情况例如PA0和PB0都被配置为同一个定时器的不同通道但这种情况在STM32中不太可能除非使用了不同的定时器。 需要进一步考虑STM32F103的定时器通道和引脚映射。例如查看PA0和PB0分别属于哪个定时器的哪个通道。PA0对应定时器2的通道1而PB0可能属于定时器3的通道3或者其他定时器。如果代码中配置了定时器2的通道1那么无论变量名如何实际输出会在PA0而如果变量名错误地写成了PB0但初始化代码正确那么电机就能正常工作。 因此问题可能出在代码中的引脚定义变量名与实际初始化时使用的引脚不一致但初始化部分正确配置了实际引脚。例如 在代码中可能有 #define MOTOR_A_PWM_PIN PB0 #define MOTOR_B_PWM_PIN PB2 但在初始化时错误地配置了PA0和PA1 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; // 实际是PA0 或者使用了正确的定时器配置例如Timer2的通道1和2对应的PA0和PA1而变量名错误地写成了PB0和PB2。 因此尽管代码中的定义和实际接线不一致但由于初始化部分正确配置了PA0和PA1所以PWM信号正确输出电机能够运行并且通过调节CCR即定时器的捕获/比较寄存器改变占空比从而控制速度。 总结起来可能的原因是代码中引脚定义的变量名或注释错误但实际的硬件初始化和定时器配置正确导致虽然文档或变量名不一致但实际信号输出正确因此小车可以正常运行。 时效性分析用户问题不依赖时效性数据但为确保准确性当前分析基于 2025年02月25日 的技术背景。 问题核心 在引脚定义与实际接线不一致的情况下小车仍能运行的根本原因在于 代码与硬件实际信号流的匹配性。以下是关键分析 原因解析 1️⃣ PWM信号实际生效的引脚与代码定义不同 可能场景 代码中虽然名义上定义引脚为 PB0 和 PB2但底层驱动如定时器配置可能错误/隐式地指向了 PA0 和 PA1。 示例 c Copy Code // 代码中名义定义引脚为 PB0错误 #define MOTOR_A_PWM_PIN PB0 // 实际初始化时误配置为 PA0正确 TIM_OC1Init(TIM2, pwm_config); // TIM2_CH1 默认映射到 PA0 结果PWM信号通过 PA0/PA1 输出与硬件接线一致因此可调速。 2️⃣ 部分引脚功能重合或短路 可能场景 若 PB0 与 PA0 在硬件上被短接如PCB设计错误或飞线代码对 PB0 的操作会实际影响 PA0。 部分电机驱动模块如L298N的使能端ENA/ENB直接接高电平此时方向引脚如A-1A/A-1B的PWM占空比仍可调速。 3️⃣ 代码未严格绑定引脚定义 可能场景 电机驱动代码通过 定时器通道如 TIM2_CH1控制PWM而非直接依赖引脚名。 示例 c Copy Code // 实际控制PA0的是TIM2_CH1无论引脚名如何定义 HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); // PA0输出PWM 验证方法 示波器/逻辑分析仪检测 检查 PA0 和 PB0 的PWM波形确认实际生效的引脚。 代码调试 跟踪PWM初始化代码验证定时器通道与引脚的映射关系参考《STM32F103参考手册》的定时器复用功能表。 硬件排查 检查是否存在 PB0 与 PA0、PB2 与 PA1 的意外短路。 ️ 解决方案建议 统一代码与硬件定义 修改代码中的引脚定义使其与实际接线一致如将 PB0 改为 PA0。 明确定时器通道映射 在代码中显式配置引脚重映射如需避免隐式依赖默认映射。 示例 c Copy Code GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); // 显式重映射TIM2通道 添加注释与文档 在代码和硬件手册中明确记录引脚对应关系减少后续维护成本。 ✅ 总结 引脚定义不一致但小车能运行本质是 信号流在硬件或代码层被隐式修正。需通过硬件检测和代码审计定位具体原因最终确保定义与实物的严格一致。 六、循迹小车 循迹模块详解 | 良许嵌入式 注意这里的接线改回去了要是不改回去会出错小车会不要电的一直跑 复制01重命名05-循迹小车 循迹模块和红外传感器模块很像所以复制智能台灯的ia_sensor 粘贴到05文件的BSP文件中并且重命名为track 打开文件 加载文件 七、循迹PWM调速 上面循迹小车中可能会出现由于地图太小小车太大太沉电机电压够足导致小车速度太快从而小车在拐弯的时候冲出地图跑道。 为了避免这这种情况的发生可以选择换一张大地图、把小车重量减轻、体积减轻、让小车变得更灵活或者把小车电机电压减少小车速度放慢。 这里使用PWM调速小车 使用PWM的接线 复制04pwm文件重命名为06-循迹pwm调速控制小车 将05中的track文件粘贴到06中 打开工程加载文件 这里注意改变arr和psc的值 因为原来的20-172-1步子太大了 上述中小车可以设置的pwm波为0-20如果设置9太快了如果设置8太慢了所以让它步子小一点这样可以设置的值就更精确了 具体的数值需要结合实际情况自己设定这里95的速度只符合我这里 八、跟随小车 跟随小车要达到的效果是 当两边的跟随模块都检测到东西的时候就向前走当右边检测到东西的时候就向右走否则向左走当都未检测到东西的时候就停止。 复制01重命名为07-跟随小车 将循迹模块的track重命名为followu 打开项目加载文件将所有的track重命名为follow 更改引脚 代码如下 九、避障小车 复制项目文件01重命名为08-避障小车 复制超声波实验和舵机实验的文件粘贴至如下图所示 接线如图所示 打开项目 加载文件 要加入定时器文件 舵机代码可以分装成左转右转中间方便看 超声波的代码就是按照上面的接线改一下引脚就可以直接用了 主函数代码如下 #include sys.h #include delay.h #include uart1.h #include motor.h #include sg90.h #include hcsr04.hint main(void) {HAL_Init(); / 初始化HAL库 /stm32_clock_init(RCC_PLL_MUL9); / 设置时钟, 72Mhz */uart1_init(115200);motor_init();sg90_init();hcsr04_init();printf(hello word!\r\n);double dis_left 0, dis_middle 0, dis_right 0;sg90_turn_middle();while(1) { dis_middle hcsr04_get_lenght();//接收超声波所测的距离if(dis_middle 35)//判断距离是否大于35是向前走motor_go_forward();else if(dis_middle 15)//否则判断距离是否小于15是后退motor_go_backward();else //否则就是距离15并且35{motor_stop(); //先停下来//向左看并测量左侧距离sg90_turn_left();delay_ms(500); //给个时间进行测量dis_left hcsr04_get_lenght(); //存储下左侧的长度//居中sg90_turn_middle(); //超声波传感器回到中间的位置delay_ms(500);//向右看并测量右侧距离sg90_turn_right();delay_ms(500);dis_right hcsr04_get_lenght();//根据距离判断左转还是右转if(dis_left dis_right)motor_go_right();elsemotor_go_left();delay_ms(500); //给个时间反应一下motor_stop(); //电机停一下sg90_turn_middle(); //舵机回到中间的位置}delay_ms(100); //给个时间反应一下} }十、测速模块 接线如下图所示 复制02-串口控制小车 重命名为09-测速小车 新建speed文件 打开项目加载文件 别忘了把定时器的驱动文件加载进来 写头文件 注意测速模块要用到中断每次感受到一个下降沿就中断一次目的为了更好的测速 然后使用定时器每一秒定时一次 代码如下 #include speed.h #include delay.h #include stdio.huint16_t speed_cnt 0; TIM_HandleTypeDef timer_handle {0};//定义结构体//gpio口初始化 void speed_gpio_init(void) {//使能GPIO时钟GPIO_InitTypeDef gpio_initstruct;//定义一个结构体gpio_initstruct//打开时钟-使能GPIO时钟HAL_RCC_GPIOB_CLK_ENABLE();//设置GPIO输入模式//设置AFIO(开启时钟IO口映射)//设置EXTI屏蔽上/下沿//调用GPIO初始化函数gpio_initstruct.Mode GPIO_MODE_IT_FALLING;//下降沿输出//结构体函数的四种类型引脚模式、引脚、引脚上拉下拉、引脚速度gpio_initstruct.Pin GPIO_PIN_12;//LED1对应的引脚gpio_initstruct.Pull GPIO_NOPULL;//上拉HAL_GPIO_Init(GPIOB,gpio_initstruct);//设置NVIC优先级分组设置优先级使能中断HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,0);HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); } //定时器中的初始化 void speed_timer_init(uint16_t arr,uint16_t psc) {timer_handle.Instance TIM2; //选择使用的定时器timer_handle.Init.Prescaler psc; //PSCtimer_handle.Init.Period arr; //ARRtimer_handle.Init.CounterMode TIM_COUNTERMODE_UP;//配置成向上的默认向上的timer_handle.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_DISABLE; //自动重装载禁用自动重装载HAL_TIM_Base_Init(timer_handle);HAL_TIM_Base_Start_IT(timer_handle);//设置使能更新中断和启动计数器 } //初始化speed函数 void speed_init(void) {speed_gpio_init();speed_timer_init(10000-1,7200-1);//一秒中断一次的定时器 }//设置中断服务函数 void EXTI15_10_IRQHandler(void) {HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12); } //回调函数 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {delay_ms(20);if(GPIO_Pin GPIO_PIN_12){if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) GPIO_PIN_RESET){speed_cnt;printf(speed %d\r\n,speed_cnt); //测量出格子的个数}} } //定时器msp函数 void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) {if(htim-Instance TIM2){__HAL_RCC_TIM2_CLK_ENABLE();HAL_NVIC_SetPriority(TIM2_IRQn,2,2);//设置优先级HAL_NVIC_EnableIRQ(TIM2_IRQn);//设置使能中断} }//定时器中断服务函数 void TIM2_IRQHandler(void) {//一般还会调用一个公共处理的服务函数HAL_TIM_IRQHandler(timer_handle); } //定时器中断回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef htim) {if(htim-Instance TIM2){//测量到每一秒转了多少个格子printf(speed %d\r\n,speed_cnt);speed_cnt 0;} } 主函数如下 #include sys.h #include delay.h #include uart1.h #include motor.h #include bluetooth.h #include speed.hint main(void) {HAL_Init(); / 初始化HAL库 /stm32_clock_init(RCC_PLL_MUL9); / 设置时钟, 72Mhz /uart1_init(115200);motor_init();speed_init();bt_init(9600);printf(hello word!\r\n);motor_go_forward(); //让小车前进while(1) { } }十一、测速小车oled显示并上传蓝牙 复制09重命名为10-测速小车oled显示并上传蓝牙 粘贴oled文件 打开项目 加载文件 想把获取到的速度打印到oled上 我们得到的值是数字要将这个数字转换成字符串打印到oled屏幕上 数字转字符串我们使用sprintf 定义一个字符数组 使用memset()先把这个字符数组清空免得之后每次中断之后传进来的数据对其进行干扰 修改oled引脚 编译无错 将蓝牙模块的这个函数的这个位置修改成这样 因为原来使用的sizeof打印子啊手机上间距太大不正常如下所示 所以换成strlen就变成了如下所示 十二、wifi控制小车速度 将蓝牙模块换成esp8266模块 让电脑可以看见小车的速度买也可以使用电脑控制小车前进后退 将esp8266接到串口2 的tx和rx中 复制10重命名11-WiFi控制小车并显示速度 打开项目加载文件 将蓝牙的相关文件删除 编译不出错 使用网络调试助手架构一个服务器 连接esp8266 #include sys.h #include delay.h #include uart1.h #include motor.h #include speed.h #include oled.h #include esp8266.h #include string.hint main(void) {HAL_Init(); / 初始化HAL库 /stm32_clock_init(RCC_PLL_MUL9); / 设置时钟, 72Mhz /uart1_init(115200);motor_init();speed_init();oled_init();esp8266_init(115200); printf(hello word!\r\n);motor_go_forward(); //让小车前进char recv_data[ESP8266_RX_BUF_SIZE];while(1) { //esp8266发送数据esp8266_receive_data(recv_data);if(strstr(recv_data, M1) ! NULL)motor_go_forward();else if(strstr(recv_data, M2) ! NULL)motor_go_backward();else if(strstr(recv_data, M3) ! NULL)motor_go_left();else if(strstr(recv_data, M4) ! NULL)motor_go_right();elsemotor_stop();} }这里没有用到空闲中断不把它注释掉反而会出错 十三、4G控制小车 4G模块引脚接线tx、rx接串口2vcc接串口1中的5vgnd随便找个地方接一下就可以 使用4G模块要使用花生壳进行内网穿透获取外网地址 设置链路 对于4G模块的代码可以直接复用10-测速小车oled显示并上传蓝牙 其中只需要注意4G模块的波特率就好你的4G模块是什么波特率就改什么波特率 连接上4G模块之后 这段代码就不是透传到蓝牙模块上了而是透传到4G模块 所以就可以在网络调试助手上看见了 十四、语音控制小车 接线如下图所示 配置SU-03T点开网站智能公元/AI产品零代码平台 语言选择中文下一步 设置三次 等待SDK烧录完成之后就可以下载固件了 将语音模块接线之后 进行烧录 然后再烧录的exe工具中选择如下文件 记住这个文件不要放到中文路径下路径也不要太长 至此语音文件就烧录完成了 下面是代码部分的编写 复制01重命名12-语音控制小车 打开项目加载文件 记得加入定时器文件 编译无错之后进行下一步 在主函数中写入头文件和初始化函数编译无错进行下一步 记得每次往主函数中融合其他模块的时候要编译测试一下减少错误率 主函数代码如下 #include sys.h #include delay.h #include uart1.h #include motor.h #include follow.h #include hcsr04.h #include sg90.h #include track.hdouble dis_left 0, dis_middle 0, dis_right 0;//循迹模式 void track_mode(void) {if(track_left_flag() TRUE track_right_flag() TRUE)motor_go_forward(); //前进else if(track_left_flag() FALSE track_right_flag() TRUE) //左边压线motor_go_left(); //左转else if(track_left_flag() TRUE track_right_flag() FALSE) //右边压线motor_go_right(); //右转else if(track_left_flag() FALSE track_right_flag() FALSE) // 全部为黑色motor_stop(); //停止 } //跟随模式 void follow_mode(void) {if(follow_left_flag() TRUE follow_right_flag() TRUE)motor_go_forward();else if(follow_left_flag() FALSE follow_right_flag() TRUE)//右边有目标motor_go_right();else if(follow_left_flag() TRUE follow_right_flag() FALSE)//左边有目标motor_go_left();else if(follow_left_flag() FALSE follow_right_flag() FALSE)motor_stop(); } //避障模式 void avoid_mode(void) {dis_middle hcsr04_get_lenght();//接收超声波所测的距离if(dis_middle 35)//判断距离是否大于35是向前走motor_go_forward();else if(dis_middle 15)//否则判断距离是否小于15是后退motor_go_backward();else //否则就是距离15并且35{motor_stop(); //先停下来//向左看并测量左侧距离sg90_turn_left();delay_ms(500); //给个时间进行测量dis_left hcsr04_get_lenght(); //存储下左侧的长度//居中sg90_turn_middle(); //超声波传感器回到中间的位置delay_ms(500);//向右看并测量右侧距离sg90_turn_right();delay_ms(500);dis_right hcsr04_get_lenght();//根据距离判断左转还是右转if(dis_left dis_right)motor_go_right();elsemotor_go_left();delay_ms(500); //给个时间反应一下motor_stop(); //电机停一下sg90_turn_middle(); //舵机回到中间的位置}delay_ms(100); //给个时间反应一下 }int main(void) {HAL_Init(); / 初始化HAL库 /stm32_clock_init(RCC_PLL_MUL9); / 设置时钟, 72Mhz /uart1_init(115200);motor_init();follow_init();hcsr04_init();sg90_init();track_init();printf(hello word!\r\n);sg90_turn_middle();while(1) { } }新建一个voice文件加载文件 voice.c代码如下 voice.h文件 主函数代码如下 #include sys.h #include delay.h #include uart1.h #include motor.h #include follow.h #include hcsr04.h #include sg90.h #include track.h #include voice.hdouble dis_left 0, dis_middle 0, dis_right 0;//循迹模式 void track_mode(void) {if(track_left_flag() TRUE track_right_flag() TRUE)motor_go_forward(); //前进else if(track_left_flag() FALSE track_right_flag() TRUE) //左边压线motor_go_left(); //左转else if(track_left_flag() TRUE track_right_flag() FALSE) //右边压线motor_go_right(); //右转else if(track_left_flag() FALSE track_right_flag() FALSE) // 全部为黑色motor_stop(); //停止 } //跟随模式 void follow_mode(void) {if(follow_left_flag() TRUE follow_right_flag() TRUE)motor_go_forward();else if(follow_left_flag() FALSE follow_right_flag() TRUE)//右边有目标motor_go_right();else if(follow_left_flag() TRUE follow_right_flag() FALSE)//左边有目标motor_go_left();else if(follow_left_flag() FALSE follow_right_flag() FALSE)motor_stop(); } //避障模式 void avoid_mode(void) {dis_middle hcsr04_get_lenght();//接收超声波所测的距离if(dis_middle 35)//判断距离是否大于35是向前走motor_go_forward();else if(dis_middle 15)//否则判断距离是否小于15是后退motor_go_backward();else //否则就是距离15并且35{motor_stop(); //先停下来//向左看并测量左侧距离sg90_turn_left();delay_ms(500); //给个时间进行测量dis_left hcsr04_get_lenght(); //存储下左侧的长度//居中sg90_turn_middle(); //超声波传感器回到中间的位置delay_ms(500);//向右看并测量右侧距离sg90_turn_right();delay_ms(500);dis_right hcsr04_get_lenght();//根据距离判断左转还是右转if(dis_left dis_right)motor_go_right();elsemotor_go_left();delay_ms(500); //给个时间反应一下motor_stop(); //电机停一下sg90_turn_middle(); //舵机回到中间的位置}delay_ms(100); //给个时间反应一下 }int main(void) {HAL_Init(); / 初始化HAL库 /stm32_clock_init(RCC_PLL_MUL9); / 设置时钟, 72Mhz */uart1_init(115200);motor_init();follow_init();hcsr04_init();sg90_init();track_init();voice_init();printf(hello word!\r\n);sg90_turn_middle();while(1) { if(TRACK_PIN GPIO_PIN_RESET FOLLOW_PIN GPIO_PIN_SET AVOID_PIN GPIO_PIN_SET)track_mode();//循迹模式else if(TRACK_PIN GPIO_PIN_SET FOLLOW_PIN GPIO_PIN_RESET AVOID_PIN GPIO_PIN_SET)follow_mode();//跟随模式else if(TRACK_PIN GPIO_PIN_SET FOLLOW_PIN GPIO_PIN_SET AVOID_PIN GPIO_PIN_RESET)avoid_mode();//避障模式} }编译无错
- 上一篇: 建立门户网站的费用广阳区建设局网站
- 下一篇: 建立商城网站建筑人才网有哪些
相关文章
-
建立门户网站的费用广阳区建设局网站
建立门户网站的费用广阳区建设局网站
- 技术栈
- 2026年03月21日
-
建立旅游网站的目的电脑做系统教学网站
建立旅游网站的目的电脑做系统教学网站
- 技术栈
- 2026年03月21日
-
建立购物网站的目的手机商城网站建设
建立购物网站的目的手机商城网站建设
- 技术栈
- 2026年03月21日
-
建立商城网站建筑人才网有哪些
建立商城网站建筑人才网有哪些
- 技术栈
- 2026年03月21日
-
建立什么样的网站好响应式设计的网站
建立什么样的网站好响应式设计的网站
- 技术栈
- 2026年03月21日
-
建立石墨碳素网站怎么做如何借用别人静态网站做模板
建立石墨碳素网站怎么做如何借用别人静态网站做模板
- 技术栈
- 2026年03月21日
