赞
踩
需要实现的项目内容
材料 | 数量 |
电机 | 2 |
万向轮 | 1 |
轮胎 | 2 |
循迹模块 | 2 |
超声波、舵机 | 1 |
STM32F103学习板或者最小系统 | 1 |
L298N | 1 |
12V可充电锂电池 | 1 |
蓝牙模块HC-06 | 1 |
如上图所示: 输出A和输出B接到电机。12V供电接到锂电池正极,5V接到单片机正极(注意单片机上的5V丝印层字样),GND单片机和锂电池共用。拔掉通道A使能和通道B使能,各接到单片机PC6和PC7口(PWM控制电机速度,用的是TIM3,开启复用模式,详细看PWM输出实验详细示例),IN1和IN2为一组( IN1是PA0; //左电机正转, IN2 = PA1; //左电机反转),接到单片机P2对应OutA(输出A); IN3和IN4为一组(IN3 是PA2; //右电机正转 ,IN4 是PC3; //右电机反转),对应OutB(输出B)。注意自己的L298N的IN1IN2IN3IN4驱动电子的方向。ENA和ENB是用来控制小车速度的,给高电平有效。
正反转逻辑(0为低电平,1为高电平)
IN1 | IN2 | IN3 | IN4 | 电机 |
1 | 0 | 0 | 1 | 向前 |
0 | 1 | 1 | 0 | 向后 |
0 | 0 | 0 | 1 | 左转 |
1 | 0 | 0 | 0 | 向后 |
1 | 1 | 1 | 1 | 停止 |
0 | 0 | 0 | 0 | 停止 |
PWM,STM32的I/O口PC6和PC7,TIM_SetCompare1(TIM3,PWM1)中PWM1控制小车转速即占空比。
PWM.C
- #include "To.h"
-
- void PWM_Init(void)
- {
-
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
- TIM_OCInitTypeDef TIM_OCInitStruct;
- GPIO_InitTypeDef GPIO_InitStruct;
-
- /***************时钟使能*******************/
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
-
- /***************TIM使能*******************/
- TIM_TimeBaseInitStruct.TIM_Period= 100-1;//重装载值
- TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1;//预分频数
- TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
- TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
- /***************PWM使能*******************/
- TIM_OCStructInit(&TIM_OCInitStruct);//给结构体成员赋初始值
- TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM1模式
- TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//设置极性
- TIM_OCInitStruct.TIM_Pulse = 50;//占空比
- TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;//使能/失能
- TIM_OC2Init(TIM3,&TIM_OCInitStruct);
- TIM_OC1Init(TIM3,&TIM_OCInitStruct);
- TIM_Cmd(TIM3,ENABLE);
- }

TO.h 总头文件
- #ifndef _TO_H
- #define _TO_H
-
- #include "stm32f10x.h"
-
- //管脚初始化
- void GPIOx_cofing(void);
-
-
- //delay
- void delay_init(void);
- void delay_ms(u16 nms);
- void delay_us(u32 nus);
- void delay_s(int s);
-
- //PWM
- void PWM_Init(void);
-
-
- //控制电机
- void qj(int PWM1,int PWM2);
- void zz(int PWM1,int PWM2);
- void yz(int PWM1,int PWM2);
- void ht(int PWM1,int PWM2);
- void tz(int PWM1,int PWM2);
-
- //循迹
- void XJ(void);
-
-
- //蓝牙通信
- void usart_Initconfig(void);
- void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data);
- uint8_t USART_ReceiveByte(USART_TypeDef* USARTx);
-
- extern uint16_t temp;
-
-
- //遥控
- void YKXC(void);
-
- #endif

motor.c
- #include "To.h"
- //车轮方向控制
- void qj(int PWM1,int PWM2)//前进
- {
- TIM_SetCompare1(TIM3,PWM1);
- GPIO_SetBits(GPIOA,GPIO_Pin_0);
- GPIO_ResetBits(GPIOA,GPIO_Pin_1);
-
- TIM_SetCompare2(TIM3,PWM2);
- GPIO_SetBits(GPIOA,GPIO_Pin_2);
- GPIO_ResetBits(GPIOA,GPIO_Pin_3);
- }
-
- void zz(int PWM1,int PWM2)//左转
- {
- TIM_SetCompare1(TIM3,PWM1);
- GPIO_SetBits(GPIOA,GPIO_Pin_0);
- GPIO_ResetBits(GPIOA,GPIO_Pin_1);
-
- TIM_SetCompare2(TIM3,PWM2);
- GPIO_SetBits(GPIOA,GPIO_Pin_2);
- GPIO_ResetBits(GPIOA,GPIO_Pin_3);
- }
-
- void yz(int PWM1,int PWM2)//右转
- {
- TIM_SetCompare1(TIM3,PWM1);
- GPIO_SetBits(GPIOA,GPIO_Pin_0);
- GPIO_ResetBits(GPIOA,GPIO_Pin_1);
-
- TIM_SetCompare2(TIM3,PWM2);
- GPIO_SetBits(GPIOA,GPIO_Pin_2);
- GPIO_ResetBits(GPIOA,GPIO_Pin_3);
- }
-
- void ht(int PWM1,int PWM2)//后退
- {
- TIM_SetCompare1(TIM3,PWM1);
- GPIO_ResetBits(GPIOA,GPIO_Pin_0);
- GPIO_SetBits(GPIOA,GPIO_Pin_1);
-
- TIM_SetCompare2(TIM3,PWM2);
- GPIO_ResetBits(GPIOA,GPIO_Pin_2);
- GPIO_SetBits(GPIOA,GPIO_Pin_3);
- }
-
- void tz(int PWM1,int PWM2)//停止
- {
- TIM_SetCompare1(TIM3,PWM1);
- GPIO_ResetBits(GPIOA,GPIO_Pin_0);
- GPIO_ResetBits(GPIOA,GPIO_Pin_1);
-
- TIM_SetCompare2(TIM3,PWM2);
- GPIO_ResetBits(GPIOA,GPIO_Pin_2);
- GPIO_ResetBits(GPIOA,GPIO_Pin_3);
- }

GPIOX.c I/O口初始化代码
- #include "To.h"
-
- void GPIOx_cofing(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
-
- //小车车轮接口
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- //LED
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- //小车循迹接口
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1|GPIO_Pin_10| GPIO_Pin_11;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStruct);
-
-
- //pwm输出/串口
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_9; //GPIO_Pin_9 //TX
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_InitStruct);
-
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; //GPIO_Pin_10
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA,&GPIO_InitStruct);
-
- }

循迹模块有模拟量和数字量的,初学者建议选择数字量,但循迹不丝滑,它的循迹原理就是接收到信号来转向。
- #include "To.h"
-
- void XJ(void)
- {
- if( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0&& GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
- {
- qj(23,23);
- }
-
-
- else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
- {
- zz(13,25);
-
- }
-
- else if( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==1)
- {
- yz(25,13);
- }
-
-
- else if( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==1)
- {
- tz(0,0);
- }
- }

请看VCR
HC-05蓝牙模块--------手机与STM32通信(代码编写)(上位机配置)保姆级教程
我这里用RCC_APB2Periph_USART1,波特率9600,PA9是TX,PA9接到蓝牙模块的RX,PA10是RX,PA10接到蓝牙模块的TX,单片机和蓝牙模块的这两个口反接。
- #include "To.h"
-
- uint16_t temp;
- void usart_Initconfig(void)
- {
- USART_InitTypeDef USART_InitStruct;
- NVIC_InitTypeDef NVIC_InitStruct;
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1,ENABLE);
-
-
- USART_InitStruct.USART_BaudRate = 9600;//波特率
- USART_InitStruct.USART_WordLength = USART_WordLength_8b;//数据位
- USART_InitStruct.USART_StopBits = USART_StopBits_1;//停止位长度
- USART_InitStruct.USART_Parity = USART_Parity_No;//校验位;无
- USART_InitStruct.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//发送/接收
- USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流控
- USART_Init(USART1,&USART_InitStruct);
- USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能usart1的中断
- USART_Cmd(USART1, ENABLE);
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =0 ;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;
- NVIC_Init(&NVIC_InitStruct);
- }
-
- void USART1_IRQHandler()
- {
- //判断是否接收到数据
- if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
- {
- temp=USART_ReceiveByte(USART1);
- //USART_SendByte(USART1,temp);
- USART_ClearITPendingBit(USART1,USART_IT_RXNE);
- }
- }
-
-
-
- void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data)
- {
- assert_param(IS_USART_ALL_PERIPH(USARTx));
- assert_param(IS_USART_DATA(Data));
-
- USARTx->DR = (Data & (uint16_t)0x01FF);
- while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==0);
- }
-
-
-
- uint8_t USART_ReceiveByte(USART_TypeDef* USARTx)
- {
- while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)==0);//为0表示没有收到数据;为1表示收到数据
-
- return (uint8_t)USART_ReceiveData(USART1);
- }

- #include "To.h"
-
- void YKXC(void)
- {
- if(temp == 'w') //控制w十六进制为“0x77”,temp == 0x77 也可以
- {
- qj(25,26);
- }
-
- else if(temp == 'a')
- {
- zz(22,30);
- }
- else if(temp == 'd')
- {
- yz(30,22);
- }
- else if(temp == 's')
- {
- ht(25,25);
- }
- else if(temp == 't')
- {
- tz(0,0);
- }
- else if(temp == 'x')
- {
- XJ();
- }
- }

信号线(黄色)、正极(红色)、负极(棕色)
信号线连接到P3^4,用定时器0,0.1ms中断一次,0.1*6(中断次数)=1ms(指向右边);0.1*15(中断次数)=1.5ms(舵机指向中间);0.1*20(中断次数)=2ms(舵机指向左边)
180度舵机控制参数 | |||
角度 | 脉冲周期 | 脉冲高电平时间 | 占空比 |
0 | 20ms | 0.5ms | 2.50% |
45 | 20ms | 1ms | 5.00% |
90 | 20ms | 1.5ms | 7.50% |
145 | 20ms | 2ms | 10.00% |
180 | 20ms | 2.5ms | 12.50% |
超声波和舵机是接在一起的,一般网上买都有连接材料,超声波可以随便连接I/O口,我这里接的是EchoPin = P3^6;//超声波模块Echo 接收端;TrigPin = P3^5;//超声波模块Trig 控制端。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。