目录
1. 电机模块开发
2. 让小车动起来
3. 串口控制小车方向
4. 如何进行小车PWM调速
5. PWM方式实现小车转向
L9110s概述
接通VCC,GND 模块电源指示灯亮, 以下资料来源官方,具体根据实际调试
IA1输入高电平,IA1输入低电平,【OA1 OB1】电机正转;
IA1输入低电平,IA1输入高电平,【OA1 OB1】电机反转;
IA2输入高电平,IA2输入低电平,【OA2 OB2】电机正转;
IA2输入低电平,IA2输入高电平,【OA2 OB2】电机反转;
接线参考:
B-1A -- PA0
B-1B -- PB1
A-1A -- PA1
A-1B -- PB10
代码实现:
motor.c
#include "motor.h"
void goForward(void)
{
// 左轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
// 右轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
void goBack(void)
{
// 左轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
// 右轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
}
void goLeft(void)
{
// 左轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
// 右轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
void goRight(void)
{
// 左轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
// 右轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
void stop(void)
{
// 左轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
// 右轮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
motor.h
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "main.h"
void goForward(void);
void goBack(void);
void goLeft(void);
void goRight(void);
void stop(void);
#endif
main.c
#include "motor.h"
//main函数的while循环部分:
while (1)
{
goForward();
HAL_Delay(1000);
goBack();
HAL_Delay(1000);
goLeft();
HAL_Delay(1000);
goRight();
HAL_Delay(1000);
stop();
HAL_Delay(1000);
}
代码实现:
usart.c
#include "usart.h"
#include "string.h"
#include "stdio.h"
#include "motor.h"
//串口接收缓存(1字节)
uint8_t buf=0;
//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200
// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];
// 接收状态
// bit15, 接收完成标志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字节数目
uint16_t UART1_RX_STA=0;
#define SIZE 12
char buffer[SIZE];
// 接收完成回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 判断中断是由哪个串口触发的
if(huart->Instance == USART1)
{
// 判断接收是否完成(UART1_RX_STA bit15 位是否为1)
if((UART1_RX_STA & 0x8000) == 0)
{
// 如果已经收到了 0x0d (回车),
if(UART1_RX_STA & 0x4000)
{
// 则接着判断是否收到 0x0a (换行)
if(buf == 0x0a)
{
// 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1
UART1_RX_STA |= 0x8000;
// 灯控指令
if(!strcmp(UART1_RX_Buffer, "M1"))
goForward();
else if(!strcmp(UART1_RX_Buffer, "M2"))
goBack();
else if(!strcmp(UART1_RX_Buffer, "M3"))
goLeft();
else if(!strcmp(UART1_RX_Buffer, "M4"))
goRight();
else
stop();
memset(UART1_RX_Buffer, 0, UART1_REC_LEN);
UART1_RX_STA = 0;
}
else
// 否则认为接收错误,重新开始
UART1_RX_STA = 0;
}
else // 如果没有收到了 0x0d (回车)
{
//则先判断收到的这个字符是否是 0x0d (回车)
if(buf == 0x0d)
{
// 是的话则将 bit14 位置为1
UART1_RX_STA |= 0x4000;
}
else
{
// 否则将接收到的数据保存在缓存数组里
UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
UART1_RX_STA++;
// 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
if(UART1_RX_STA > UART1_REC_LEN - 1)
UART1_RX_STA = 0;
}
}
}
// 重新开启中断
HAL_UART_Receive_IT(&huart1, &buf, 1);
}
}
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
原理:
全速前进是LeftCon1A = 0; LeftCon1B = 1;
完全停止是LeftCon1A = 0;LeftCon1B = 0;
那么单位时间内,比如20ms, 有15ms是全速前进,5ms是完全停止, 速度就会比5ms全速前进,15ms完全停止获得的功率多,相应的速度更快!
开发:借用PWM的舵机控制代码
将控制车轮的4个 GPIO 口配置修改如下,否则小车动不起来。
原因:L9110每个控制口需要一高一低才可以动起来,如果PWM有效电平为高电平,则另一个 GPIO口则需要输出低电平才可以驱动轮子。
代码实现:
main.c
// main函数里
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
while (1)
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 8);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 8);
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 10);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 10);
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 15);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 15);
HAL_Delay(1000);
}
右转原理:
左轮速度大于右轮
左转原理:
右轮速度大于左轮
左右轮各自调速代码实现:
// main函数里
while (1)
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,8);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,15);
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,15);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,8);
HAL_Delay(1000);
}