1. 电机模块开发
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
2. 让小车动起来
代码实现:
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); }
3. 串口控制小车方向
- 串口分文件编程进行代码整合——通过现象来改代码
- 接入蓝牙模块,通过蓝牙控制小车
- 添加点动控制,如果APP支持按下一直发数据,松开就停止发数据(蓝牙调试助手的自定义按键不 能实现),就能实现前进按键按下后小车一直往前走的功能
代码实现:
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; }
4. 如何进行小车PWM调速
原理:
全速前进是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); }
5. PWM方式实现小车转向
右转原理:
左轮速度大于右轮
左转原理:
右轮速度大于左轮
左右轮各自调速代码实现:
// 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); }