32代码 四驱简易电动小车 蓝牙控制、语音控制、巡线、寻光、避障(内含语音模块天问ASR-PRO开发板的串口配置程序)

作者声明:
作者笔名为:北风
作者QQ号为:2547903457
作者个人简介1:现为大二的一名普通学生,祝自己努力加油!!!!
作者个人简介2:因作者初学,能力有限,部分代码并不精简,可根据自身能力进行更改;
作品简介1:
本车为四驱小车,现在具有的功能:蓝牙、语音、寻光、巡线、避障。通过上行蓝牙或语音模块来控制下行车辆行驶(前进、后退、左转、右转、原地左转、原地右转)以及三个功能(寻光、巡线、避障)。

作品简介2:
本车用到一个stm32f103rct6作为主控板、两块tb6612集成的电机驱动板D24A、
四个带编码器的电机(但没用到编码器)、一个电源模块(12V转3.3/5/12V)、一个四路红外巡线模块、
一个舵机模块SG90、一个超声波测距避障模块HC-SR04、三个光敏电阻传感器模块、一个天问语音模块、
两块电池(一块12V)、两块板子(电机在中间)、几个雪糕棒(用来向外扩展四路巡线模块)、杜邦线若干

作者提示1:
本车程序代码的绝大部分注释均为作者本人所写。

db50973856b748eb91cfdc38322a12d4.jpeg

70bac0cfca454e81a5a3b4d8a5b1d9f5.png

主函数main.c 

#include "stm32f10x.h"
#include "system.h"
#include "Delay.h"
#include "moto.h"
#include "pwm.h"
#include "Car.h"
#include "Serial.h"
#include "Timer1.h"
#include "Ultrasound.h"
#include "Track.h"
#include "usart3.h"
#include "Light.h"
#include "Timer2.h"
uint16_t Data1;
extern u16 flag_send;
extern u8 com_data;
/*******************************************************************************************
作者声明:
作者笔名为:北风
作者QQ号为:2547903457
作者个人简介1:现为大二的一名普通学生,祝自己努力加油!!!!
作者个人简介2:因作者初学,能力有限,部分代码并不精简,可根据自身能力进行更改;
作品简介1:
本车为四驱小车,现在具有的功能:蓝牙、语音、寻光、巡线、避障。通过上行蓝牙或语音模块来控制
下行车辆行驶(前进、后退、左转、右转、原地左转、原地右转)以及三个功能(寻光、巡线、避障)。

作品简介2:
本车用到一个stm32f103rct6作为主控板、两块tb6612集成的电机驱动板D24A、
四个带编码器的电机(但没用到编码器)、一个电源模块(12V转3.3/5/12V)、一个四路红外巡线模块、
一个舵机模块SG90、一个超声波测距避障模块HC-SR04、三个光敏电阻传感器模块、一个天问语音模块、
两块电池(一块12V)、两块板子(电机在中间)、几个雪糕棒(用来向外扩展四路巡线模块)、杜邦线若干

作者提示1:
本车程序代码的绝大部分注释均为作者本人所写。
********************************************************************************************/

int main()                                 //语音控制(三个功能1.寻光功能 xunguang(); 2.巡线功能 xunxian(); 3.避障功能 bizhang();)
{                                          //int main()的上花括号
   SystemInit();                           //配置系统时钟为72M   
   delay_init();                           //延时函数初始化
   moto_Init();                            //初始化gpioB pin_0/1/8/9/12/13/14/15
   TIM4PWM_Init();                         //初始化设置舵机转向 右边为0度 0°对应500    90°对应1500   180°对应2500 
   Car_Init();                             //初始化车辆行驶方向
   Light_Init();                           //初始化寻光模块
   Track_Init();                           //初始化巡线模块
   Ultrasound_Init();                      //初始化避障模块
   USART3_Init();                          //初始化语音模块(语音模块用到串口3)
   Serial_Init();                          //初始化蓝牙模块(蓝牙模块用到串口1)
   PWM_Int(0,0);                           //初始化电机模块(此车为四驱,定时器五的四个通道都用了)
   while(1)                                //循环上花括号(设计的是通过蓝牙或语音来切换功能)
	{                                      //(三个功能1.寻光功能 xunguang(); 2.巡线功能 xunxian(); 3.避障功能 bizhang();)
		
		if(Data1 == 0x37)xunguang();       //蓝牙模式下的寻光模式
		if(Data1 == 0x38)xunxian();        //蓝牙模式下的巡线模式
		if(Data1 == 0x39)bizhang();        //蓝牙模式下的避障模式
		if(com_data == 0x37)xunguang();    //语音模式下的寻光模式
		if(com_data == 0x38)xunxian();     //语音模式下的巡线模式
		if(com_data == 0x39)bizhang();     //语音模式下的避障模式
		
	}                                      //循环下花括号
		
}		                                   //int main()的下花括号

/*****************************************************************************************************
下方函数功能 :通过蓝牙或语音控制车辆的前进、后退、左转、右转、原地左转、原地右转。
作者提示1:通过调用USART_ClearITPendingBit函数,可以将接收中断挂起位清零,以便下一次接收中断能够正常触发。
作者提示2:USART_ClearFlag(USART3,USART_FLAG_RXNE);同理一样的作用。
******************************************************************************************************/

 void USART1_IRQHandler(void)                               //蓝牙模块(蓝牙模块用到串口1)串口1中断服务程序
{
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)    //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		Data1=USART_ReceiveData(USART1);
		if(Data1 == 0x30)Car_Stop();                        //停车函数可鼠标右键跳转查看
		if(Data1 == 0x31)Go_Ahead();                        //前进函数可鼠标右键跳转查看
		if(Data1 == 0x32)Go_Back();                         //后退函数可鼠标右键跳转查看
		if(Data1 == 0x33)Turn_Left();                       //左转函数可鼠标右键跳转查看
		if(Data1 == 0x34)Turn_Right();                      //右转函数可鼠标右键跳转查看
		if(Data1 == 0x35)Self_Left();                       //原地左转函数可鼠标右键跳转查看
		if(Data1 == 0x36)Self_Right();                      //原地右转函数可鼠标右键跳转查看
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);     
	}                                                       
}


 void USART3_IRQHandler(void)                               //语音模块(语音模块用到串口3)串口3中断服务程序
 {
	
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)   //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		USART_ClearFlag(USART3,USART_FLAG_RXNE);
		com_data = USART3->DR;	
		if(com_data == 0x30)Car_Stop();
		if(com_data == 0x31)Go_Ahead();
	    if(com_data == 0x32)Go_Back();
		if(com_data == 0x33)Turn_Left();
		if(com_data == 0x34)Turn_Right();
		if(com_data == 0x35)Self_Left();
		if(com_data == 0x36)Self_Right();
	 } 

 }


/*******************************************************************************************
下方为各功能模块的独立代码:1.寻光功能 xunguang(); 2.巡线功能 xunxian(); 3.避障功能 bizhang();
在测试使用各功能模块时请解除对应模块的注释。
********************************************************************************************/


/*******************************************************************************************
功能模块:1.寻光功能 xunguang();    
********************************************************************************************/
		
//int TargetVelocity=500;
//int main(void)
// {	
//   SystemInit();   //配置系统时钟为72M   
//   delay_init();   //延时函数初始化
//   moto_Init();    //初始化gpioB pin_0/1/8/9/12/13/14/15
//   Car_Init();	
//   Light_Init();
//   PWM_Int(0,0);
//    while(1)
//   {
//	    xunguang();
//   }
// }

/*******************************************************************************************
功能模块:2.巡线功能 xunxian();  
********************************************************************************************/

//int TargetVelocity=500; 
//int main(void)
//{	
//   SystemInit();   //配置系统时钟为72M   
//   delay_init();   //延时函数初始化
//   moto_Init();    //初始化gpioB pin_0/1/8/9/12/13/14/15
//   Car_Init();	
//   Track_Init();
//   PWM_Int(0,0);
//	
//   while(1)
//   {  
//	    xunxian(); 
//   }
//} 	

/*******************************************************************************************
功能模块:3.避障功能 bizhang();  
********************************************************************************************/

//int TargetVelocity=500; //自动避障功能
//int main(void)
// {	
//   SystemInit();   //配置系统时钟为72M   
//   delay_init();   //延时函数初始化
//   moto_Init();    //初始化gpioB pin_0/1/8/9/12/13/14/15
//   TIM4PWM_Init();
//   Car_Init();	
//   Ultrasound_Init();
//   PWM_Int(0,0);  
//  while(1)                            
//	{
//      bizhang();
//	}
//} 

/*******************************************************************************************
直线巡线时绕开障碍物后继续巡线:绕开障碍物的函数(本代码实现从左侧绕过障碍物并回到直行线上)
(需按照实际情况更改) 
********************************************************************************************/

//		Car_Stop();
//		delay_ms(240);
//		Self_Left();
//		delay_ms(834);
//		Go_Ahead();
//		delay_ms(520);
//		Self_Right();
//		delay_ms(750);
//		Go_Ahead();
//		delay_ms(800);
//		Self_Right();
//		delay_ms(740);
//		Go_Ahead();
//		delay_ms(790);
//		Self_Left();
//		delay_ms(380);
//      Car_Stop();
//		delay_ms(500);

/*******************************************************************************************
后续功能可按照自己所需功能自行添加 
********************************************************************************************/

usart3.c串口3全套配置

#include "stm32f10x.h"
#include "usart3.h"
u16 flag_send=0;
u8 com_data;
u16 USART3_RX_STA=0;
/**************************************************************************
函数功能:语音配置,用到串口3,
作者提示:下方所有函数代码,b站江协科技up主都讲过
***************************************************************************/
void USART3_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStrue;
	USART_InitTypeDef USART3_InitStrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
	GPIO_InitStrue.GPIO_Mode = GPIO_Mode_AF_PP;//推挽输出(发射)
	GPIO_InitStrue.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStrue.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStrue);
	
	GPIO_InitStrue.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入(接收)
	GPIO_InitStrue.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStrue.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStrue);
	
	
	USART3_InitStrue.USART_BaudRate = 115200;
	USART3_InitStrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART3_InitStrue.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	USART3_InitStrue.USART_Parity = USART_Parity_No;//奇偶校验位
	USART3_InitStrue.USART_StopBits = USART_StopBits_1;//停止位
	USART3_InitStrue.USART_WordLength = USART_WordLength_8b;//数据位
	USART_Init(USART3, &USART3_InitStrue);
	
	USART_Cmd(USART3, ENABLE);
	
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//打开接收中断,当接收到数据时开启中断
	NVIC_InitStrue.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStrue.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStrue);
}


//extern u8 check_flag;

void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
    /* 发送一个字节数据到 USART */
	USART_SendData(pUSARTx,ch);

    /* 等待发送数据寄存器为空 */
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}


void Usart_SendString(USART_TypeDef* pUSARTx, char *str)
{
    unsigned int k=0; 
    do
    {
        Usart_SendByte(pUSARTx, *(str + k));
        k++;
    }while(*(str + k) != '\0');
 
    /* 等待发送完成 */
    while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
	{}
}


usart3.h串口3全套配置

#ifndef _usart3_H
#define _usart3_H


#include "system.h"


#define USART3_MAX_RECV_LEN		600					//最大接收缓存字节数
#define USART3_MAX_SEND_LEN		600					//最大发送缓存字节数
//#define USART3_RX_EN 			1					//0,不接收;1,接收.

extern u8  USART3_RX_BUF[USART3_MAX_RECV_LEN]; 		//接收缓冲,最大USART3_MAX_RECV_LEN字节
extern u8  USART3_TX_BUF[USART3_MAX_SEND_LEN]; 		//发送缓冲,最大USART3_MAX_SEND_LEN字节
extern u16 USART3_RX_STA;   						//接收数据状态

void USART3_Init(void);				//串口3初始化 

void Usart_SendString(USART_TypeDef* pUSARTx, char *str);
#endif

usart3中提及的

system.c的配置

#include "system.h"    //请跳转至.h文件查看注释,此模块.c文件中不需要任何代码




 system.h

#ifndef _system_H
#define _system_H


#include "stm32f10x.h"


//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入


#endif

祝你学习进步! 

<think>好的,我需要帮用户修改代码,让小车电机从反转改为正转。用户提供了他们当前的代码和一些引用资料,我需要仔细看看这些内容。 首先,用户提到他们想通过修改DIR_A1、DIR_A2、DIR_B1和DIR_B2的逻辑来实现正转。根据引用[1],右电机的DIR_A1是13脚控制反转,DIR_A2是7脚控制正转。左电机的DIR_B1是9控制反转,DIR_B2是8控制正转。原来的代码中,loop函数里反转的时候,右电机是DIR_A1设为LOW,DIR_A2为HIGH,左电机是DIR_B1设为LOW,DIR_B2为HIGH。所以如果要正转的话,应该反过来设置这些引脚的状态。 原来的正转部分在loop函数开始的时候,右电机是DIR_A1 HIGH,DIR_A2 LOW,左电机是DIR_B1 HIGH,DIR_B2 LOW。这时候电机正转。而反转的时候,右电机DIR_A1 LOW,DIR_A2 HIGH,左电机DIR_B1 LOW,DIR_B2 HIGH。用户现在想将反转改为正转,可能需要检查这些引脚的高低电平设置是否正确。 如果用户之前的反转逻辑正确,那么要改为正转,应该把DIR_A1和DIR_A2的值调换,同样对于DIR_B1和DIR_B2也是如此。比如,在反转时,右电机的DIR_A1是LOW,DIR_A2是HIGH,那么正转应该是DIR_A1 HIGH,DIR_A2 LOW。同样左电机DIR_B1在反转时是LOW,DIR_B2是HIGH,正转应该是DIR_B1 HIGH,DIR_B2 LOW。这样就能改变电机的转向。 不过需要确认电机的实际接线和驱动方式是否正确。比如,有些电机驱动模块可能需要设置不同的引脚组合来控制方向。根据引用[2],模块使用D1-D4作为控制端口,其中DA和DB是方向控制,可能对应不同的高低电平组合。而引用[3]中的例子则是通过不同的相引脚通电来控制方向,比如A相和B相的高低电平组合。 用户当前的代码中使用的是digitalWrite来控制DIR引脚,然后通过PWM调节速度。所以正确的方向控制应该取决于DIR引脚的高低组合。例如,在引用[1]的例子中,右电机正转时DIR_A1是HIGH,DIR_A2是LOW,而反转时相反。所以用户需要确保在希望正转的时候,设置正确的引脚状态。 可能的解决方案是检查每个电机的正转和反转所需的DIR引脚状态,并调整相应的代码部分。例如,如果用户希望反转改为正转,那么可能需要将原本设置的反转部分的DIR引脚状态改为正转的状态。或者,如果用户整个循环中想要小车一直正转,而不是交替正反转,那么可能需要修改loop函数中的代码,去掉反转的部分,保持正转的状态。 另外,用户提到了PID库,但代码中没有显示PID相关的实现,可能需要确保在修改方向控制时不影响PID的控制逻辑,如果有的话。不过当前的问题主要是方向控制,所以重点放在DIR引脚的状态设置上。 总结一下,用户需要将原本的反转部分的引脚状态改为正转的设置。例如,在反转时,右电机的DIR_A1设为LOW,DIR_A2设为HIGH,改为正转的话,应设置为DIR_A1 HIGH和DIR_A2 LOW,同样适用于左电机的DIR_B1和DIR_B2。</think>要修改电机转向逻辑,需调整DIR引脚的电平组合。根据引用[1]的引脚定义: 右电机正转逻辑: - `DIR_A1 = HIGH`(禁用反转) - `DIR_A2 = LOW`(启用正转) 左电机正转逻辑: - `DIR_B1 = HIGH`(禁用反转) - `DIR_B2 = LOW`(启用正转) ### 修改步骤: 1. **原反转代码段**: ```cpp //右电机反转 digitalWrite(DIR_A1,LOW); digitalWrite(DIR_A2,HIGH); //左电机反转 digitalWrite(DIR_B1,LOW); digitalWrite(DIR_B2,HIGH); ``` 2. **改为正转**: ```cpp //右电机正转 digitalWrite(DIR_A1,HIGH); // 关闭反转通道 digitalWrite(DIR_A2,LOW); // 开启正转通道 //左电机正转 digitalWrite(DIR_B1,HIGH); // 关闭反转通道 digitalWrite(DIR_B2,LOW); // 开启正转通道 ``` ### 完整示例(修改后loop函数): ```cpp void loop() { //右电机正转 digitalWrite(DIR_A1,HIGH); digitalWrite(DIR_A2,LOW); analogWrite(PWM_A,25); //左电机正转 digitalWrite(DIR_B1,HIGH); digitalWrite(DIR_B2,LOW); analogWrite(PWM_B,25); delay(1000); //保持正转(原反转部分改为正转) digitalWrite(DIR_A1,HIGH); // 修改点 digitalWrite(DIR_A2,LOW); // 修改点 digitalWrite(DIR_B1,HIGH); // 修改点 digitalWrite(DIR_B2,LOW); // 修改点 analogWrite(PWM_A,25); analogWrite(PWM_B,25); delay(1000); } ``` ### 原理说明: TB6612电机驱动芯片通过`DIR_x`引脚组合控制转向[^2]。当正转通道使能(LOW)且反转通道关闭(HIGH)时,电机正转。修改后代码始终保持正转通道激活状态,实现持续正转。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值