STM32 HAL库实战(智能小车项目详解)第四部分
STM32-HAL库(下4-智能小车项目)
269 智能小车项目概述
(1)小车项目综合了stm32各个知识点,具有代表性;
270 智能小车车身基础安装
(1)小车组装后下载代码验证确保硬件无误;
271 车身基础安装完整版
272 电机驱动模块L9110S
(1)参考文档链接:https://www.lxlinux.net/e/stm32/l9110s-tutorial.html
(2)电机驱动模块:是一种用于控制和驱动电机的设备,它能够将控制信号转化为适合电机操作的电流和电压。
(2)L9110S模块有二路可以驱动2个直流电机,A-1A 输入高电平,A-1B 输入低电平,MotorA 电机正转;A-1A 输入低电平,A-1B 输入高电平,MotorA 电机反转;
B-1A 输入高电平,B-1B 输入低电平,MotorB 电机正转;B-1A 输入低电平,B-1B 输入高电平,MotorB 电机反转。
273 让小车动起来
(1)编写电机初始化函数motor_init(),电机向前函数motor_go_forward(),电机向后函数motor_go_backward(),电机向左函数motor_go_left(),电机向右函数motor_go_right(),电机停止函数motor_stop()。
-(63. 智能小车项目/1. 让小车动起来-main.c,motor.c,motor.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
printf("hello world!\r\n");
while(1)
{
motor_go_forward();
delay_ms(1000);
motor_go_backward();
delay_ms(1000);
motor_go_left();
delay_ms(1000);
motor_go_right();
delay_ms(1000);
motor_stop();
delay_ms(1000);
}
}
/*
------------------------------------------------------------------------
motor.c:
-------------------------------------------------------------------------
*/
#include "motor.h"
//电机初始化函数motor_init()
void motor_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;
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();
}
//电机向前函数motor_go_forward()
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);
}
//电机向后函数motor_go_backward()
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);
}
//电机向左函数motor_go_left()
void motor_go_left(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_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);
}
//电机向右函数motor_go_right()
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);
}
//电机停止函数motor_stop()
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);
}
/*
------------------------------------------------------------------------
motor.h:
-------------------------------------------------------------------------
*/
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "sys.h"
void motor_init(void);
void motor_go_forward(void);
void motor_go_backward(void);
void motor_go_left(void);
void motor_go_right(void);
void motor_stop(void);
#endif
274 串口控制小车
(1)参考"63. 智能小车项目/1. 让小车动起来"代码,添加蓝牙模块,uart1文件中添加串口2,蓝牙模块中断服务函数USART2_IRQHandler()中增加蓝牙接收的数据控制小车转向;
-(63. 智能小车项目/2. 串口控制小车-main.c,bluetooth.c,bluetooth.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "bluetooth.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
bt_init(9600);
printf("hello world!\r\n");
while(1)
{
// motor_go_forward();
// delay_ms(1000);
// motor_go_backward();
// delay_ms(1000);
// motor_go_left();
// delay_ms(1000);
// motor_go_right();
// delay_ms(1000);
// motor_stop();
// delay_ms(1000);
}
}
/*
------------------------------------------------------------------------
bluetooth.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "bluetooth.h"
#include "string.h"
#include "stdarg.h"
#include "motor.h"
UART_HandleTypeDef uart2_handle; /* UART2句柄 */
uint8_t uart2_rx_buf[UART2_RX_BUF_SIZE]; /* UART2接收缓冲区 */
uint16_t uart2_rx_len = 0; /* UART2接收字符长度 */
/**
* @brief 串口1初始化函数
* @param baudrate: 波特率, 根据自己需要设置波特率值
* @retval 无
*/
void bt_init(uint32_t baudrate)
{
/*UART2 初始化设置*/
uart2_handle.Instance = USART2; /* USART2 */
uart2_handle.Init.BaudRate = baudrate; /* 波特率 */
uart2_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
uart2_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
uart2_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
uart2_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
uart2_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&uart2_handle); /* HAL_UART_Init()会使能UART2 */
}
/**
* @brief UART2接收缓冲区清除
* @param 无
* @retval 无
*/
void uart2_rx_clear(void)
{
memset(uart2_rx_buf, 0, sizeof(uart2_rx_buf)); /* 清空接收缓冲区 */
uart2_rx_len = 0; /* 接收计数器清零 */
}
/**
* @brief 串口1中断服务函数
* @note 在此使用接收中断及空闲中断,实现不定长数据收发
* @param 无
* @retval 无
*/
void USART2_IRQHandler(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_RXNE) != RESET){ /* 获取接收RXNE标志位是否被置位 */
if(uart2_rx_len >= sizeof(uart2_rx_buf)) /* 如果接收的字符数大于接收缓冲区大小, */
uart2_rx_len = 0; /* 则将接收计数器清零 */
HAL_UART_Receive(&uart2_handle, &receive_data, 1, 1000); /* 接收一个字符 */
uart2_rx_buf[uart2_rx_len++] = receive_data; /* 将接收到的字符保存在接收缓冲区 */
}
if (__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_IDLE) != RESET) /* 获取接收空闲中断标志位是否被置位 */
{
printf("bt recv: %s\r\n", uart2_rx_buf); /* 将接收到的数据打印出来 */
if(strcmp((char *)uart2_rx_buf,"M1") == 0)
motor_go_forward();
else if(strcmp((char *)uart2_rx_buf,"M2") == 0)
motor_go_backward();
else if(strcmp((char *)uart2_rx_buf,"M3") == 0)
motor_go_left();
else if(strcmp((char *)uart2_rx_buf,"M4") == 0)
motor_go_right();
else
motor_stop();
uart2_rx_clear();
__HAL_UART_CLEAR_IDLEFLAG(&uart2_handle); /* 清除UART总线空闲中断 */
}
}
//void bt_send(char *send_buf,uint8_t size)
//{
// //HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
// HAL_UART_Transmit(&uart2_handle,(uint8_t *)send_buf,size,100);
//}
void bt_send(char * format, ...)
{
uint8_t send_buf[128] ={0};
va_list arg;
va_start(arg, format);
vsprintf((char *)send_buf, format, arg);
va_end(arg);
HAL_UART_Transmit(&uart2_handle,send_buf,sizeof(send_buf),100);
}
/*
------------------------------------------------------------------------
bluetooth.h:
-------------------------------------------------------------------------
*/
#ifndef __BLUETOOTH__H__
#define __BLUETOOTH__H__
#include "stdio.h"
#include "sys.h"
/* UART收发缓冲大小 */
#define UART2_RX_BUF_SIZE 128
#define UART2_TX_BUF_SIZE 64
void bt_init(uint32_t baudrate); /* 串口初始化函数 */
//void bt_send(char *send_buf,uint8_t size);
void bt_send(char * format, ...);
#endif
275 蓝牙控制小车
(1)直接采用"63. 智能小车项目/2. 串口控制小车"代码,将串口2接蓝牙模块,通过手机蓝牙助手即可控制小车。-待测试
276 点动控制小车
(1)参考"63. 智能小车项目/2. 串口控制小车"代码,蓝牙模块中断服务函数USART2_IRQHandler()中增加延时函数delay_ms(10),main函数中while循环中为电机停止函数motor_stop()。
-(63. 智能小车项目/3. 点动控制小车-main.c,bluetooth.c,bluetooth.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "bluetooth.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
bt_init(9600);
printf("hello world!\r\n");
while(1)
{
motor_stop();
}
}
/*
------------------------------------------------------------------------
bluetooth.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "bluetooth.h"
#include "string.h"
#include "stdarg.h"
#include "motor.h"
#include "delay.h"
UART_HandleTypeDef uart2_handle; /* UART2句柄 */
uint8_t uart2_rx_buf[UART2_RX_BUF_SIZE]; /* UART2接收缓冲区 */
uint16_t uart2_rx_len = 0; /* UART2接收字符长度 */
/**
* @brief 串口1初始化函数
* @param baudrate: 波特率, 根据自己需要设置波特率值
* @retval 无
*/
void bt_init(uint32_t baudrate)
{
/*UART2 初始化设置*/
uart2_handle.Instance = USART2; /* USART2 */
uart2_handle.Init.BaudRate = baudrate; /* 波特率 */
uart2_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
uart2_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
uart2_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
uart2_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
uart2_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&uart2_handle); /* HAL_UART_Init()会使能UART2 */
}
/**
* @brief UART2接收缓冲区清除
* @param 无
* @retval 无
*/
void uart2_rx_clear(void)
{
memset(uart2_rx_buf, 0, sizeof(uart2_rx_buf)); /* 清空接收缓冲区 */
uart2_rx_len = 0; /* 接收计数器清零 */
}
/**
* @brief 串口1中断服务函数
* @note 在此使用接收中断及空闲中断,实现不定长数据收发
* @param 无
* @retval 无
*/
void USART2_IRQHandler(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_RXNE) != RESET){ /* 获取接收RXNE标志位是否被置位 */
if(uart2_rx_len >= sizeof(uart2_rx_buf)) /* 如果接收的字符数大于接收缓冲区大小, */
uart2_rx_len = 0; /* 则将接收计数器清零 */
HAL_UART_Receive(&uart2_handle, &receive_data, 1, 1000); /* 接收一个字符 */
uart2_rx_buf[uart2_rx_len++] = receive_data; /* 将接收到的字符保存在接收缓冲区 */
}
if (__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_IDLE) != RESET) /* 获取接收空闲中断标志位是否被置位 */
{
printf("bt recv: %s\r\n", uart2_rx_buf); /* 将接收到的数据打印出来 */
if(strcmp((char *)uart2_rx_buf,"M1") == 0)
motor_go_forward();
else if(strcmp((char *)uart2_rx_buf,"M2") == 0)
motor_go_backward();
else if(strcmp((char *)uart2_rx_buf,"M3") == 0)
motor_go_left();
else if(strcmp((char *)uart2_rx_buf,"M4") == 0)
motor_go_right();
else
motor_stop();
delay_ms(10);
uart2_rx_clear();
__HAL_UART_CLEAR_IDLEFLAG(&uart2_handle); /* 清除UART总线空闲中断 */
}
}
//void bt_send(char *send_buf,uint8_t size)
//{
// //HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
// HAL_UART_Transmit(&uart2_handle,(uint8_t *)send_buf,size,100);
//}
void bt_send(char * format, ...)
{
uint8_t send_buf[128] ={0};
va_list arg;
va_start(arg, format);
vsprintf((char *)send_buf, format, arg);
va_end(arg);
HAL_UART_Transmit(&uart2_handle,send_buf,sizeof(send_buf),100);
}
/*
------------------------------------------------------------------------
bluetooth.h:
-------------------------------------------------------------------------
*/
#ifndef __BLUETOOTH__H__
#define __BLUETOOTH__H__
#include "stdio.h"
#include "sys.h"
/* UART收发缓冲大小 */
#define UART2_RX_BUF_SIZE 128
#define UART2_TX_BUF_SIZE 64
void bt_init(uint32_t baudrate); /* 串口初始化函数 */
//void bt_send(char *send_buf,uint8_t size);
void bt_send(char * format, ...);
#endif
277 pwm调速小车
(1)参考"63. 智能小车项目/1. 让小车动起来"代码,添加呼吸灯中pwm模块,pwm模块中采用定时器TIM2中的通道1,通道2分别控制左轮,右轮电压占空比值,从而达到pwm调速的目的。
pwm模块中添加了左轮值设定pwm_left_motor_set(),右轮值设定pwm_right_motor_set()。
-(63. 智能小车项目/4. pwm调速小车-main.c,pwm.c,pwm.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "pwm.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
pwm_init(20-1,72-1);
printf("hello world!\r\n");
while(1)
{
pwm_left_motor_set(8);
pwm_right_motor_set(15);
delay_ms(1000);
pwm_left_motor_set(15);
pwm_right_motor_set(8);
delay_ms(1000);
}
}
/*
------------------------------------------------------------------------
pwm.c:
-------------------------------------------------------------------------
*/
#include "pwm.h"
TIM_HandleTypeDef pwm_handler = {0};
//pwm初始化
void pwm_init(uint16_t arr,uint16_t psc)
{
TIM_OC_InitTypeDef pwm_config = {0};
pwm_handler.Instance = TIM2 ;
pwm_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
pwm_handler.Init.Period = arr;
pwm_handler.Init.Prescaler = psc;
//HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
HAL_TIM_PWM_Init(&pwm_handler);
// HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
// const TIM_OC_InitTypeDef *sConfig,
// uint32_t Channel)
pwm_config.OCMode = TIM_OCMODE_PWM1;//模式1
pwm_config.Pulse = 0; //设定比较值CCR,开始设定一次,后面__HAL_TIM_SET_COMPARE()函数中会修改
pwm_config.OCPolarity = TIM_OCNPOLARITY_HIGH;//有效电平为高电平
HAL_TIM_PWM_ConfigChannel(&pwm_handler,&pwm_config,TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&pwm_handler,&pwm_config,TIM_CHANNEL_2);
//HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
HAL_TIM_PWM_Start(&pwm_handler,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&pwm_handler,TIM_CHANNEL_2);
}
//msp初始化
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM4)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
__HAL_RCC_TIM2_CLK_ENABLE();//使能TIM2时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
gpio_initstruct.Mode = GPIO_MODE_AF_PP; // 推挽输出
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
}
}
//修改CCR寄存器值
void pwm_left_motor_set(uint16_t val)
{
//__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
__HAL_TIM_SET_COMPARE(&pwm_handler,TIM_CHANNEL_1,val);
}
void pwm_right_motor_set(uint16_t val)
{
//__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
__HAL_TIM_SET_COMPARE(&pwm_handler,TIM_CHANNEL_2,val);
}
/*
------------------------------------------------------------------------
pwm.h:
-------------------------------------------------------------------------
*/
#ifndef __PWM_H__
#define __PWM_H__
#include "sys.h"
void pwm_init(uint16_t arr,uint16_t psc);
void pwm_left_motor_set(uint16_t val);
void pwm_right_motor_set(uint16_t val);
#endif
278 循迹模块介绍
(1)参考文档链接:https://www.lxlinux.net/e/stm32/tcrt5000-tutorial.html
(2)循迹模块TCRT5000不断发射红外信号,当红外信号:
1.有反射回来,DO 输出低电平,开关指示灯(绿灯)亮。
2.没反射回来,DO 输出高电平,开关指示灯(绿灯)灭。
279 循迹小车
(1)参考"63. 智能小车项目/1. 让小车动起来"代码,添加"智能台灯项目"中的红外传感器模块作为循迹模块,循迹模块中修改初始化函数track_init()中gpio口,
新增获取左模块值标志track_left_flag(),新增获取右模块值标志track_right_flag();main函数中根据左右模块值的不同来控制小车前左右停。
-(63. 智能小车项目/5. 循迹小车-main.c,track.c,track.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "track.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
track_init();
printf("hello world!\r\n");
while(1)
{
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();
}
}
/*
------------------------------------------------------------------------
track.c:
-------------------------------------------------------------------------
*/
#include "track.h"
#include "sys.h"
//初始化exti函数
void track_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOA时钟
gpio_initstruct.Pin = GPIO_PIN_13 | GPIO_PIN_14;
gpio_initstruct.Mode = GPIO_MODE_INPUT;
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
}
uint8_t track_left_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
uint8_t track_right_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
/*
------------------------------------------------------------------------
track.h:
-------------------------------------------------------------------------
*/
#ifndef __TRACK_H__
#define __TRACK_H__
#include "stdint.h"
#define TRUE 1
#define FALSE 0
void track_init(void);
uint8_t track_left_flag(void);
uint8_t track_right_flag(void);
#endif
280 循迹+pwm调速小车
(1)参考"63. 智能小车项目/4. pwm调速小车",添加循迹模块代码,main函数里面根据左右模块值的不同来控制小车前左右停(前后左右用pwm中左右轮设定值pwm_left_motor_set(),pwm_right_motor_set())。
-(63. 智能小车项目/6. 循迹+pwm调速小车-main.c,track.c,pwm.c,track.h,pwm.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "pwm.h"
#include "track.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
pwm_init(200-1,720-1);
printf("hello world!\r\n");
while(1)
{
if(track_left_flag() == TRUE && track_right_flag() == TRUE)
{
pwm_left_motor_set(95);
pwm_right_motor_set(95);
}
else if(track_left_flag() == FALSE && track_right_flag() == TRUE)
{
pwm_left_motor_set(0);
pwm_right_motor_set(95);
}
else if(track_left_flag() == TRUE && track_right_flag() == FALSE)
{
pwm_left_motor_set(95);
pwm_right_motor_set(0);
}
else if(track_left_flag() == FALSE && track_right_flag() == FALSE)
pwm_left_motor_set(0);
pwm_right_motor_set(0);
}
}
/*
------------------------------------------------------------------------
track.c:
-------------------------------------------------------------------------
*/
#include "track.h"
#include "sys.h"
//初始化exti函数
void track_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOA时钟
gpio_initstruct.Pin = GPIO_PIN_13 | GPIO_PIN_14;
gpio_initstruct.Mode = GPIO_MODE_INPUT;
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
}
uint8_t track_left_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
uint8_t track_right_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
/*
------------------------------------------------------------------------
pwm.c:
-------------------------------------------------------------------------
*/
#include "pwm.h"
TIM_HandleTypeDef pwm_handler = {0};
//pwm初始化
void pwm_init(uint16_t arr,uint16_t psc)
{
TIM_OC_InitTypeDef pwm_config = {0};
pwm_handler.Instance = TIM2 ;
pwm_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
pwm_handler.Init.Period = arr;
pwm_handler.Init.Prescaler = psc;
//HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
HAL_TIM_PWM_Init(&pwm_handler);
// HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
// const TIM_OC_InitTypeDef *sConfig,
// uint32_t Channel)
pwm_config.OCMode = TIM_OCMODE_PWM1;//模式1
pwm_config.Pulse = 0; //设定比较值CCR,开始设定一次,后面__HAL_TIM_SET_COMPARE()函数中会修改
pwm_config.OCPolarity = TIM_OCNPOLARITY_HIGH;//有效电平为高电平
HAL_TIM_PWM_ConfigChannel(&pwm_handler,&pwm_config,TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&pwm_handler,&pwm_config,TIM_CHANNEL_2);
//HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
HAL_TIM_PWM_Start(&pwm_handler,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&pwm_handler,TIM_CHANNEL_2);
}
//msp初始化
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM4)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
__HAL_RCC_TIM2_CLK_ENABLE();//使能TIM2时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
gpio_initstruct.Mode = GPIO_MODE_AF_PP; // 推挽输出
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
}
}
//修改CCR寄存器值
void pwm_left_motor_set(uint16_t val)
{
//__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
__HAL_TIM_SET_COMPARE(&pwm_handler,TIM_CHANNEL_1,val);
}
void pwm_right_motor_set(uint16_t val)
{
//__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
__HAL_TIM_SET_COMPARE(&pwm_handler,TIM_CHANNEL_2,val);
}
/*
------------------------------------------------------------------------
track.h:
-------------------------------------------------------------------------
*/
#ifndef __TRACK_H__
#define __TRACK_H__
#include "stdint.h"
#define TRUE 1
#define FALSE 0
void track_init(void);
uint8_t track_left_flag(void);
uint8_t track_right_flag(void);
#endif
/*
------------------------------------------------------------------------
pwm.h:
-------------------------------------------------------------------------
*/
#ifndef __PWM_H__
#define __PWM_H__
#include "sys.h"
void pwm_init(uint16_t arr,uint16_t psc);
void pwm_left_motor_set(uint16_t val);
void pwm_right_motor_set(uint16_t val);
#endif
281 跟随小车
(1)参考"63. 智能小车项目/1. 让小车动起来",添加"63. 智能小车项目/5. 循迹小车"中的循迹模块,修改函数名;主函数逻辑改为左边检测到物体,左转即右轮转动,右边检测到物体,右转即左轮转动,
左右两边检测到物体,向前走即左右轮一块转。-(63. 智能小车项目/7. 跟随小车-main.c,follow.c,motor.c,follow.h,motor.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "follow.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
follow_init();
printf("hello world!\r\n");
while(1)
{
if(follow_left_flag() == TRUE && follow_right_flag() == TRUE)
motor_go_forward();
else if(follow_left_flag() == FALSE && follow_right_flag() == TRUE)
motor_go_left();
else if(follow_left_flag() == TRUE && follow_right_flag() == FALSE)
motor_go_right();
else if (follow_left_flag() == FALSE && follow_right_flag() == FALSE)
motor_stop();
}
}
/*
------------------------------------------------------------------------
follow.c:
-------------------------------------------------------------------------
*/
#include "follow.h"
#include "sys.h"
//初始化exti函数
void follow_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOA时钟
gpio_initstruct.Pin = GPIO_PIN_13 | GPIO_PIN_14;
gpio_initstruct.Mode = GPIO_MODE_INPUT;
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
}
uint8_t follow_left_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
uint8_t follow_right_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
/*
------------------------------------------------------------------------
motor.c:
-------------------------------------------------------------------------
*/
#include "motor.h"
//电机初始化函数motor_init()
void motor_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;
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();
}
//电机向前函数motor_go_forward()
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);
}
//电机向后函数motor_go_backward()
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);
}
//电机向左函数motor_go_left()
void motor_go_left(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_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);
}
//电机向右函数motor_go_right()
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);
}
//电机停止函数motor_stop()
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);
}
/*
------------------------------------------------------------------------
follow.h:
-------------------------------------------------------------------------
*/
#ifndef __FOLLOW_H__
#define __FOLLOW_H__
#include "stdint.h"
#define TRUE 1
#define FALSE 0
void follow_init(void);
uint8_t follow_left_flag(void);
uint8_t follow_right_flag(void);
#endif
/*
------------------------------------------------------------------------
motor.h:
-------------------------------------------------------------------------
*/
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "sys.h"
void motor_init(void);
void motor_go_forward(void);
void motor_go_backward(void);
void motor_go_left(void);
void motor_go_right(void);
void motor_stop(void);
#endif
282 避障小车
(1)参考"63. 智能小车项目/1. 让小车动起来",添加舵机模块,超声波模块,舵机模块中添加向左转函数sg90_turn_left(),向中转函数sg90_turn_middle(),向右转函数sg90_turn_right();
主函数中根据距离障碍物距离决定向那个方向行驶;-(63. 智能小车项目/8. 避障小车-main.c,motor.c,sg90.c,hcsr04.c,motor.h,sg90.h,hcsr04.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "sg90.h"
#include "hcsr04.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
hcsr04_init();
sg90_init();
printf("hello world!\r\n");
double dis_left = 0,dis_middle = 0,dis_right = 0;
sg90_turn_middle();
while(1)
{
dis_middle = hcsr04_get_length();
if(dis_middle > 35)
motor_go_forward();
else if(dis_middle <15)
motor_go_backward();
else
{
motor_stop();
sg90_turn_left();
delay_ms(500);
dis_left = hcsr04_get_length();
sg90_turn_middle();
delay_ms(500);
sg90_turn_right();
delay_ms(500);
dis_right = hcsr04_get_length();
if(dis_left < dis_right)
motor_go_right();
else
motor_go_left();
delay_ms(200);
motor_stop();
sg90_turn_middle();
}
delay_ms(100);
}
}
/*
------------------------------------------------------------------------
motor.c:
-------------------------------------------------------------------------
*/
#include "motor.h"
//电机初始化函数motor_init()
void motor_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;
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();
}
//电机向前函数motor_go_forward()
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);
}
//电机向后函数motor_go_backward()
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);
}
//电机向左函数motor_go_left()
void motor_go_left(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_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);
}
//电机向右函数motor_go_right()
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);
}
//电机停止函数motor_stop()
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);
}
/*
------------------------------------------------------------------------
sg90.c:
-------------------------------------------------------------------------
*/
#include "sg90.h"
TIM_HandleTypeDef tim3_handler = {0};
//pwm初始化
void tim3_init(void)
{
TIM_OC_InitTypeDef pwm_config = {0};
tim3_handler.Instance = TIM3 ;
tim3_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
tim3_handler.Init.Period = 200 - 1;
tim3_handler.Init.Prescaler = 7200-1;
//HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
HAL_TIM_PWM_Init(&tim3_handler);
// HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
// const TIM_OC_InitTypeDef *sConfig,
// uint32_t Channel)
pwm_config.OCMode = TIM_OCMODE_PWM1;
pwm_config.Pulse = 100;
pwm_config.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&tim3_handler,&pwm_config,TIM_CHANNEL_1);
//HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
HAL_TIM_PWM_Start(&tim3_handler,TIM_CHANNEL_1);
}
//msp初始化
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOB时钟
__HAL_RCC_TIM3_CLK_ENABLE();//使能TIM3时钟
//调用GPIO初始化函数
//HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
gpio_initstruct.Pin = GPIO_PIN_6;
gpio_initstruct.Mode = GPIO_MODE_AF_PP; // 复合推挽输出
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
}
}
//修改CCR寄存器值
void tim3_compare_set(uint16_t val)
{
//__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
__HAL_TIM_SET_COMPARE(&tim3_handler,TIM_CHANNEL_1,val);
}
//sg90初始化
void sg90_init(void)
{
tim3_init();
}
//舵机角度设定
void sg90_angle_set(uint16_t angle)
{
uint16_t CCRx = (1.0/9.0)*angle + 5.0;
tim3_compare_set(CCRx);
}
//向左转函数sg90_turn_left()
void sg90_turn_left(void)
{
sg90_angle_set(180);
}
//向中转函数sg90_turn_middle()
void sg90_turn_middle(void)
{
sg90_angle_set(90);
}
//向右转函数sg90_turn_right
void sg90_turn_right(void)
{
sg90_angle_set(0);
}
/*
------------------------------------------------------------------------
hcsr04.c:
-------------------------------------------------------------------------
*/
#include "hcsr04.h"
#include "delay.h"
TIM_HandleTypeDef tim2_handler ={0};
//定时器初始化函数
void tim2_init(void)
{
tim2_handler.Instance =TIM2;
tim2_handler.Init.Prescaler = 72 - 1;
tim2_handler.Init.Period = 65536 - 1;
tim2_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
tim2_handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&tim2_handler);
HAL_TIM_Base_Start_IT(&tim2_handler);
}
//msp函数
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
__HAL_RCC_TIM2_CLK_ENABLE();
}
}
//定时器开启
void tim2_start(void)
{
HAL_TIM_Base_Start(&tim2_handler);
}
//定时器关闭
void tim2_stop(void)
{
HAL_TIM_Base_Stop(&tim2_handler);
}
//获取定时器的计数器值
uint16_t tim2_get_cnt(void)
{
return __HAL_TIM_GetCounter(&tim2_handler);
}
//设定定时器的计数器值
void tim2_set_cnt(uint16_t val)
{
__HAL_TIM_SetCounter(&tim2_handler,val);
}
//hcsr04所用GPIO初始化
void hcsr04_gpio_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
TRIG_GPIO_CLK_ENABLE();
ECHO_GPIO_CLK_ENABLE();
//初始化Trig引脚
gpio_initstruct.Pin = TRIG_PIN;
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
gpio_initstruct.Pull = GPIO_NOPULL;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(TRIG_PORT,&gpio_initstruct);
//初始化Echo引脚
gpio_initstruct.Pin = ECHO_PIN;
gpio_initstruct.Mode = GPIO_MODE_INPUT; //输入
HAL_GPIO_Init(ECHO_PORT,&gpio_initstruct);
}
//hcsr04初始化
void hcsr04_init(void)
{
tim2_init();
hcsr04_gpio_init();
}
//hcsr04获取距离
float hcsr04_get_length(void)
{
uint16_t total_time = 0;
float distance = 0;
//1.Trig,给Trig端口至少10us的高电平
TRIG_HIGH();
delay_us(15);
TRIG_LOW();
//2.Echo引脚,由低电平跳转到高电平,表示开始发送波
while(ECHO_STATUS() == GPIO_PIN_RESET);
tim2_start();
tim2_set_cnt(0);
//3.Echo,由高电平跳转回低电平,表示波回来了
//Echo引脚维持高电平的时间,波发出去的那一下,开始启动定时器,波回来的那一下,我们开始停止定时器,
while(ECHO_STATUS() == GPIO_PIN_SET);
tim2_stop();
//4.计算出中间经过多少时间
total_time = tim2_get_cnt();
//5.距离 = 速度(343m/s) * 时间 / 2
distance = total_time*0.01715;
return distance;
}
/*
------------------------------------------------------------------------
motor.h:
-------------------------------------------------------------------------
*/
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "sys.h"
void motor_init(void);
void motor_go_forward(void);
void motor_go_backward(void);
void motor_go_left(void);
void motor_go_right(void);
void motor_stop(void);
#endif
/*
------------------------------------------------------------------------
sg90.h:
-------------------------------------------------------------------------
*/
#ifndef __SG90_H__
#define __SG90_H__
#include "sys.h"
void sg90_init(void);
void sg90_turn_left(void);
void sg90_turn_middle(void);
void sg90_turn_right(void);
#endif
/*
------------------------------------------------------------------------
hcsr04.h:
-------------------------------------------------------------------------
*/
#ifndef __HCSR04_H__
#define __HCSR04_H__
#include "sys.h"
#define TRIG_PORT GPIOB
#define TRIG_PIN GPIO_PIN_6
#define TRIG_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE();
#define TRIG_HIGH() HAL_GPIO_WritePin(TRIG_PORT,TRIG_PIN,GPIO_PIN_SET)
#define TRIG_LOW() HAL_GPIO_WritePin(TRIG_PORT,TRIG_PIN,GPIO_PIN_RESET)
#define ECHO_PORT GPIOB
#define ECHO_PIN GPIO_PIN_7
#define ECHO_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE();
#define ECHO_STATUS() HAL_GPIO_ReadPin(ECHO_PORT,ECHO_PIN)
void hcsr04_init(void);
float hcsr04_get_length(void);
#endif
283 测速模块介绍
(1)参考文档链接:https://www.lxlinux.net/e/stm32/speed-sensor-tutorial.html
(2)原理:有遮挡,输出高电平;无遮挡,输出低电平;20格的码盘转一圈就会经历20个下降沿中断,一个下降沿中断就是走了 3.14×6.5/20 = 1.0205cm,约等于一个中断走1cm。
测距离 = 3.14×直径/码盘格子×中断次数;测速度 = 定时器每秒输出 3.14×直径/码盘格子×中断次数;
284 测速小车
(1)参考"63. 智能小车项目/2. 串口控制小车",新增测速模块代码,包含了中断模块,及定时器模块这两部分的代码。
-(63. 智能小车项目/9. 测速小车-main.c,motor.c,speed.c,motor.h,speed.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "bluetooth.h"
#include "speed.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
bt_init(9600);
speed_init();
printf("hello world!\r\n");
while(1)
{
}
}
/*
------------------------------------------------------------------------
motor.c:
-------------------------------------------------------------------------
*/
#include "motor.h"
//电机初始化函数motor_init()
void motor_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;
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();
}
//电机向前函数motor_go_forward()
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);
}
//电机向后函数motor_go_backward()
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);
}
//电机向左函数motor_go_left()
void motor_go_left(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_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);
}
//电机向右函数motor_go_right()
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);
}
//电机停止函数motor_stop()
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);
}
/*
------------------------------------------------------------------------
speed.c:
-------------------------------------------------------------------------
*/
#include "speed.h"
#include "stdio.h"
uint16_t speed_cnt = 0;
TIM_HandleTypeDef timer_handler ={0};
void speed_gpio_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_12; //按键对应引脚
gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,0);// 设置EXTI0中断线的优先级
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);// 使能中断
}
//定时器初始化函数
void speed_timer_init(uint16_t arr,uint16_t psc)
{
timer_handler.Instance =TIM2;
timer_handler.Init.Prescaler = psc;
timer_handler.Init.Period = arr;
timer_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
timer_handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&timer_handler);
HAL_TIM_Base_Start_IT(&timer_handler);
}
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)
{
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_handler);
}
//更新中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
printf("speed:%d\r\n",speed_cnt);
speed_cnt = 0;
}
}
/*
------------------------------------------------------------------------
motor.h:
-------------------------------------------------------------------------
*/
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "sys.h"
void motor_init(void);
void motor_go_forward(void);
void motor_go_backward(void);
void motor_go_left(void);
void motor_go_right(void);
void motor_stop(void);
#endif
/*
------------------------------------------------------------------------
speed.h:
-------------------------------------------------------------------------
*/
#ifndef __SPEED_H__
#define __SPEED_H__
#include "sys.h"
void speed_init(void);
#endif
285 测速小车OLED显示并上传蓝牙
(1)参考"63. 智能小车项目/9. 测速小车",添加蓝牙模块,oled模块代码,在测速模块里面的定时器回调函数中进行oled显示oled_show_string(),发送给蓝牙数据bt_send(),蓝牙模块中修改sizeof为strlen;
-(63. 智能小车项目/10. 测速小车OLED显示并上传蓝牙-main.c,motor.c,speed.c,bluetooth.c,motor.h,speed.h,bluetooth.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "bluetooth.h"
#include "speed.h"
#include "oled.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
bt_init(9600);
speed_init();
oled_init();
printf("hello world!\r\n");
motor_go_forward();
while(1)
{
}
}
/*
------------------------------------------------------------------------
motor.c:
-------------------------------------------------------------------------
*/
#include "motor.h"
//电机初始化函数motor_init()
void motor_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;
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();
}
//电机向前函数motor_go_forward()
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);
}
//电机向后函数motor_go_backward()
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);
}
//电机向左函数motor_go_left()
void motor_go_left(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_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);
}
//电机向右函数motor_go_right()
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);
}
//电机停止函数motor_stop()
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);
}
/*
------------------------------------------------------------------------
speed.c:
-------------------------------------------------------------------------
*/
#include "speed.h"
#include "stdio.h"
#include "bluetooth.h"
#include "oled.h"
#include "string.h"
uint16_t speed_cnt = 0;
char speed_str[24] = {0};
TIM_HandleTypeDef timer_handler ={0};
void speed_gpio_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_12; //按键对应引脚
gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,0);// 设置EXTI0中断线的优先级
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);// 使能中断
}
//定时器初始化函数
void speed_timer_init(uint16_t arr,uint16_t psc)
{
timer_handler.Instance =TIM2;
timer_handler.Init.Prescaler = psc;
timer_handler.Init.Period = arr;
timer_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
timer_handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&timer_handler);
HAL_TIM_Base_Start_IT(&timer_handler);
}
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)
{
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_handler);
}
//更新中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
printf("speed:%d\r\n",speed_cnt);
memset(speed_str,0,sizeof(speed_str));
sprintf(speed_str,"speed:%2dcm/s",speed_cnt);
bt_send(speed_str);
bt_send("\r\n");
oled_show_string(10,2,speed_str,16);
speed_cnt = 0;
}
}
/*
------------------------------------------------------------------------
bluetooth.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "bluetooth.h"
#include "string.h"
#include "stdarg.h"
#include "motor.h"
UART_HandleTypeDef uart2_handle; /* UART2句柄 */
uint8_t uart2_rx_buf[UART2_RX_BUF_SIZE]; /* UART2接收缓冲区 */
uint16_t uart2_rx_len = 0; /* UART2接收字符长度 */
/**
* @brief 串口1初始化函数
* @param baudrate: 波特率, 根据自己需要设置波特率值
* @retval 无
*/
void bt_init(uint32_t baudrate)
{
/*UART2 初始化设置*/
uart2_handle.Instance = USART2; /* USART2 */
uart2_handle.Init.BaudRate = baudrate; /* 波特率 */
uart2_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
uart2_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
uart2_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
uart2_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
uart2_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&uart2_handle); /* HAL_UART_Init()会使能UART2 */
}
/**
* @brief UART2接收缓冲区清除
* @param 无
* @retval 无
*/
void uart2_rx_clear(void)
{
memset(uart2_rx_buf, 0, sizeof(uart2_rx_buf)); /* 清空接收缓冲区 */
uart2_rx_len = 0; /* 接收计数器清零 */
}
/**
* @brief 串口1中断服务函数
* @note 在此使用接收中断及空闲中断,实现不定长数据收发
* @param 无
* @retval 无
*/
void USART2_IRQHandler(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_RXNE) != RESET){ /* 获取接收RXNE标志位是否被置位 */
if(uart2_rx_len >= sizeof(uart2_rx_buf)) /* 如果接收的字符数大于接收缓冲区大小, */
uart2_rx_len = 0; /* 则将接收计数器清零 */
HAL_UART_Receive(&uart2_handle, &receive_data, 1, 1000); /* 接收一个字符 */
uart2_rx_buf[uart2_rx_len++] = receive_data; /* 将接收到的字符保存在接收缓冲区 */
}
if (__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_IDLE) != RESET) /* 获取接收空闲中断标志位是否被置位 */
{
printf("bt recv: %s\r\n", uart2_rx_buf); /* 将接收到的数据打印出来 */
if(strcmp((char *)uart2_rx_buf,"M1") == 0)
motor_go_forward();
else if(strcmp((char *)uart2_rx_buf,"M2") == 0)
motor_go_backward();
else if(strcmp((char *)uart2_rx_buf,"M3") == 0)
motor_go_left();
else if(strcmp((char *)uart2_rx_buf,"M4") == 0)
motor_go_right();
else
motor_stop();
uart2_rx_clear();
__HAL_UART_CLEAR_IDLEFLAG(&uart2_handle); /* 清除UART总线空闲中断 */
}
}
//void bt_send(char *send_buf,uint8_t size)
//{
// //HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
// HAL_UART_Transmit(&uart2_handle,(uint8_t *)send_buf,size,100);
//}
void bt_send(char * format, ...)
{
uint8_t send_buf[128] ={0};
va_list arg;
va_start(arg, format);
vsprintf((char *)send_buf, format, arg);
va_end(arg);
HAL_UART_Transmit(&uart2_handle,send_buf,strlen((char *)send_buf),100);
}
/*
------------------------------------------------------------------------
motor.h:
-------------------------------------------------------------------------
*/
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "sys.h"
void motor_init(void);
void motor_go_forward(void);
void motor_go_backward(void);
void motor_go_left(void);
void motor_go_right(void);
void motor_stop(void);
#endif
/*
------------------------------------------------------------------------
speed.h:
-------------------------------------------------------------------------
*/
#ifndef __SPEED_H__
#define __SPEED_H__
#include "sys.h"
void speed_init(void);
#endif
/*
------------------------------------------------------------------------
bluetooth.h:
-------------------------------------------------------------------------
*/
#ifndef __BLUETOOTH__H__
#define __BLUETOOTH__H__
#include "stdio.h"
#include "sys.h"
/* UART收发缓冲大小 */
#define UART2_RX_BUF_SIZE 128
#define UART2_TX_BUF_SIZE 64
void bt_init(uint32_t baudrate); /* 串口初始化函数 */
//void bt_send(char *send_buf,uint8_t size);
void bt_send(char * format, ...);
#endif
286 wifi控制小车并发送速度
(1)参考"63. 智能小车项目/10. 测速小车OLED显示并上传蓝牙",添加wifi模块esp8266,定时器回调函数中发送数据给主机esp8266_send_data(),主函数中接收来自主机信号esp8266_receive_data()用来控制小车行驶;
-(63. 智能小车项目/11. wifi控制小车并发送速度-main.c,motor.c,speed.c,esp8266.c,motor.h,speed.h,esp8266.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "speed.h"
#include "oled.h"
#include "esp8266.h"
#include "string.h"
#include "string.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
speed_init();
oled_init();
esp8266_init(115200);
printf("hello world!\r\n");
motor_go_forward();
char recv_data[ESP8266_RX_BUF_SIZE];
while(1)
{
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();
else
motor_stop();
delay_ms(10);
}
}
/*
------------------------------------------------------------------------
motor.c:
-------------------------------------------------------------------------
*/
#include "motor.h"
//电机初始化函数motor_init()
void motor_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;
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();
}
//电机向前函数motor_go_forward()
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);
}
//电机向后函数motor_go_backward()
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);
}
//电机向左函数motor_go_left()
void motor_go_left(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_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);
}
//电机向右函数motor_go_right()
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);
}
//电机停止函数motor_stop()
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);
}
/*
------------------------------------------------------------------------
speed.c:
-------------------------------------------------------------------------
*/
#include "speed.h"
#include "stdio.h"
#include "oled.h"
#include "string.h"
#include "esp8266.h"
uint16_t speed_cnt = 0;
char speed_str[24] = {0};
TIM_HandleTypeDef timer_handler ={0};
void speed_gpio_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_12; //按键对应引脚
gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,0);// 设置EXTI0中断线的优先级
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);// 使能中断
}
//定时器初始化函数
void speed_timer_init(uint16_t arr,uint16_t psc)
{
timer_handler.Instance =TIM2;
timer_handler.Init.Prescaler = psc;
timer_handler.Init.Period = arr;
timer_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
timer_handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&timer_handler);
HAL_TIM_Base_Start_IT(&timer_handler);
}
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)
{
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_handler);
}
//更新中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
printf("speed:%d\r\n",speed_cnt);
memset(speed_str,0,sizeof(speed_str));
sprintf(speed_str,"speed:%2dcm/s",speed_cnt);
oled_show_string(10,2,speed_str,16);
esp8266_send_data(speed_str);
speed_cnt = 0;
}
}
/*
------------------------------------------------------------------------
esp8266.c:
-------------------------------------------------------------------------
*/
#include "esp8266.h"
#include "stdio.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"
uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE];
uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE];
uint16_t esp8266_cnt = 0, esp8266_cntPre = 0;
UART_HandleTypeDef esp8266_handle = {0};
void esp8266_uart_init(uint32_t baudrate)
{
esp8266_handle.Instance = USART1;
esp8266_handle.Init.BaudRate = baudrate;
esp8266_handle.Init.WordLength = UART_WORDLENGTH_8B;
esp8266_handle.Init.StopBits = UART_STOPBITS_1;
esp8266_handle.Init.Parity = UART_PARITY_NONE;
esp8266_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
esp8266_handle.Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(&esp8266_handle);
}
void USART2_IRQHandler(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&esp8266_handle, UART_FLAG_RXNE) != RESET)
{
if(esp8266_cnt >= sizeof(esp8266_rx_buf))
esp8266_cnt = 0;
HAL_UART_Receive(&esp8266_handle, &receive_data, 1, 1000);
esp8266_rx_buf[esp8266_cnt++] = receive_data;
//esp8266_cnt++;
//HAL_UART_Transmit(&esp8266_handle, &receive_data, 1, 1000);
}
}
uint8_t esp8266_wait_receive(void)
{
if(esp8266_cnt == 0)
return ESP8266_ERROR;
if(esp8266_cnt == esp8266_cntPre)
{
esp8266_cnt = 0;
return ESP8266_EOK;
}
esp8266_cntPre = esp8266_cnt;
return ESP8266_ERROR;
}
void esp8266_rx_clear(void)
{
memset(esp8266_rx_buf, 0, sizeof(esp8266_rx_buf));
esp8266_cnt = 0;
}
uint16_t esp8266_receive_data(char *recv_data)
{
if(esp8266_wait_receive() == ESP8266_EOK)
{
printf("esp8266 recv: %s\r\n", esp8266_rx_buf);
memcpy(recv_data,esp8266_rx_buf,strlen((char *)esp8266_rx_buf));
esp8266_rx_clear();
return strlen((char *)esp8266_rx_buf);
}
return 0;
}
void esp8266_send_data(char *fmt, ...)
{
va_list ap;
uint16_t len;
va_start(ap,fmt);
vsprintf((char *)esp8266_tx_buf,fmt,ap);
va_end(ap);
len = strlen((const char *)esp8266_tx_buf);
HAL_UART_Transmit(&esp8266_handle,esp8266_tx_buf,len,100);
}
uint8_t esp8266_send_command(char *cmd,char *res)
{
uint8_t time_out = 250;
esp8266_rx_clear();
HAL_UART_Transmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100);
while(time_out--)
{
if(esp8266_wait_receive() == ESP8266_EOK)
{
if(strstr((const char*)esp8266_rx_buf,res) != NULL)
{
return ESP8266_EOK;
}
}
delay_ms(10);
}
return ESP8266_ERROR;
}
//esp8266的at指令测试
uint8_t esp8266_at_test(void)
{
return (esp8266_send_command("AT\r\n","OK"));
}
uint8_t esp8266_set_mode(uint8_t mode)
{
switch(mode)
{
case ESP8266_STA_MODE:
return esp8266_send_command("AT+CWMODE=1\r\n","OK");
case ESP8266_AP_MODE:
return esp8266_send_command("AT+CWMODE=2\r\n","OK");
case ESP8266_STA_AP_MODE:
return esp8266_send_command("AT+CWMODE=3\r\n","OK");
default:
return ESP8266_EINVAL;
}
}
uint8_t esp8266_join_ap(char *ssid,char *pwd)
{
char cmd[64];
sprintf(cmd,"AT+CWJAP=\"%s\",\"%s\r\n\"",ssid,pwd);
return esp8266_send_command(cmd,"WIFI GOT IP");
}
uint8_t esp8266_connection_mode(uint8_t mode)
{
char cmd[64];
sprintf(cmd,"AT+CIPMUX=%d\r\n",mode);
return esp8266_send_command(cmd,"OK");
}
uint8_t esp8266_connect_tcp_server(char *server_ip,char *server_port)
{
char cmd[64];
sprintf(cmd,"AT+CIPSTART=\"TCP\",\"%s\",%s\r\n",server_ip,server_port);
return esp8266_send_command(cmd,"CONNECT");
}
uint8_t esp8266_enter_unvarnished(void)
{
uint8_t ret;
ret = esp8266_send_command("AT+CIPMODE=1\r\n","OK");
ret += esp8266_send_command("AT+CIPSEND\r\n",">");
if(ret == ESP8266_EOK)
return ESP8266_EOK;
else
return ESP8266_ERROR;
}
void esp8266_init(uint32_t baudrate)
{
printf("esp8266初始化开始...\r\n");
esp8266_uart_init(baudrate);
//esp8266的其他初始化
printf("1.测试esp8266是否存在...\r\n");
while(esp8266_at_test())
delay_ms(500);
printf("2.设置工作模式为STA...\r\n");
while(esp8266_set_mode(ESP8266_STA_MODE))
delay_ms(500);
printf("3.设置单路链接模式...\r\n");
while(esp8266_connection_mode(ESP8266_SINGLE_CONNECTION))
delay_ms(500);
printf("4.连接wifi,SSID: %s, PWD: %s\r\n",WIFI_SSID,WIFI_PWD);
while(esp8266_join_ap(WIFI_SSID,WIFI_PWD))
delay_ms(1500);
printf("5.连接TCP服务器,server_ip: %s, server_port: %s\r\n",TCP_SERVER_IP,TCP_SERVER_PORT);
while(esp8266_connect_tcp_server(TCP_SERVER_IP,TCP_SERVER_PORT))
delay_ms(500);
printf("6.进入透传模式...\r\n");
while(esp8266_enter_unvarnished())
delay_ms(500);
printf("ESP8266已连接上TCP服务器并进入透传模式\r\n");
printf("ESP8266初始化完成!\r\n");
}
/*
------------------------------------------------------------------------
motor.h:
-------------------------------------------------------------------------
*/
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "sys.h"
void motor_init(void);
void motor_go_forward(void);
void motor_go_backward(void);
void motor_go_left(void);
void motor_go_right(void);
void motor_stop(void);
#endif
/*
------------------------------------------------------------------------
speed.h:
-------------------------------------------------------------------------
*/
#ifndef __SPEED_H__
#define __SPEED_H__
#include "sys.h"
void speed_init(void);
#endif
/*
------------------------------------------------------------------------
esp8266.h:
-------------------------------------------------------------------------
*/
#ifndef __ESP8266_H__
#define __ESP8266_H__
#include "sys.h"
#define ESP8266_RX_BUF_SIZE 128
#define ESP8266_TX_BUF_SIZE 64
#define ESP8266_EOK 0
#define ESP8266_ERROR 1
#define ESP8266_ETIMEOUT 2
#define ESP8266_EINVAL 3
#define ESP8266_STA_MODE 1
#define ESP8266_AP_MODE 2
#define ESP8266_STA_AP_MODE 3
#define WIFI_SSID "wifi账号"
#define WIFI_PWD "wifi密码"
#define ESP8266_SINGLE_CONNECTION 0
#define ESP8266_MULTI_CONNECTION 1
#define TCP_SERVER_IP "主机ip地址"
#define TCP_SERVER_PORT "主机端口号"
void esp8266_init(uint32_t baudrate);
void esp8266_send_data(char *fmt, ...);
uint16_t esp8266_receive_data(char *recv_data);
#endif
287 4G控制小车
(1)参考"63. 智能小车项目/9. 测速小车",4G模块跟蓝牙模块一样采用内网穿透原理,仅需4G模块配置后采用蓝牙模块一样代码进行控制小车行驶;-待测试
288 语音控制模块介绍
(1)SU-03T模组规格书了解。语音识别模块,会烧录程序使用即可。
289 SU-03T配置详解
(1)在智能公元网址:http://www.smartpi.cn/#/ 中配置,配置小车跟随,循迹,避障3种模式。-待测试
290 SU-03T镜像烧录
(1)烧录工具软件:UniOneUpdateTool;烧录内容:智能公元中下载的固件包里的bin文件;用usb转ttl链接语音模块,下载时语音模块需要拨动开关下电后上电;-待测试
291 语音控制小车
(1)参考"63. 智能小车项目/1. 让小车动起来",添加跟随模块(follow文件),循迹模块(track文件),避障模块(sg90,hcsr04文件)代码;新增voice模块进行声言模块初始化GPIO口voice_init();
主函数中封装好循迹模式track_mode(),跟随模式follow_mode(),避障模式avoid_mode(),while循环中通过3个GPIO口的电平来判定是那种模式。
-(63. 智能小车项目/12. 语音控制小车-main.c,motor.c,follow.c,track.c,hcsr04.c,sg90.c,voice.c,motor.h,follow.h,track.h,hcsr04.h,sg90.h,voice.h)–待测试
/*
------------------------------------------------------------------------
main.c:
-------------------------------------------------------------------------
*/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "motor.h"
#include "track.h"
#include "follow.h"
#include "sg90.h"
#include "hcsr04.h"
#include "voice.h"
double dis_left = 0,dis_middle = 0,dis_right = 0;
//循迹模式track_mode()
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();
}
//跟随模式follow_mode()
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_left();
else if(follow_left_flag() == TRUE && follow_right_flag() == FALSE)
motor_go_right();
else if (follow_left_flag() == FALSE && follow_right_flag() == FALSE)
motor_stop();
}
//避障模式avoid_mode()
void avoid_mode(void)
{
dis_middle = hcsr04_get_length();
if(dis_middle > 35)
motor_go_forward();
else if(dis_middle <15)
motor_go_backward();
else
{
motor_stop();
sg90_turn_left();
delay_ms(500);
dis_left = hcsr04_get_length();
sg90_turn_middle();
delay_ms(500);
sg90_turn_right();
delay_ms(500);
dis_right = hcsr04_get_length();
if(dis_left < dis_right)
motor_go_right();
else
motor_go_left();
delay_ms(200);
motor_stop();
sg90_turn_middle();
}
delay_ms(100);
}
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
motor_init();
track_init();
follow_init();
hcsr04_init();
voice_init();
sg90_init();
printf("hello world!\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();
if(TRACK_PIN == GPIO_PIN_SET && FOLLOW_PIN == GPIO_PIN_RESET && AVOID_PIN == GPIO_PIN_SET)
follow_mode();
if(TRACK_PIN == GPIO_PIN_SET && FOLLOW_PIN == GPIO_PIN_SET && AVOID_PIN == GPIO_PIN_RESET)
avoid_mode();
}
}
/*
------------------------------------------------------------------------
motor.c:
-------------------------------------------------------------------------
*/
#include "motor.h"
//电机初始化函数motor_init()
void motor_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10;
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();
}
//电机向前函数motor_go_forward()
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);
}
//电机向后函数motor_go_backward()
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);
}
//电机向左函数motor_go_left()
void motor_go_left(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_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);
}
//电机向右函数motor_go_right()
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);
}
//电机停止函数motor_stop()
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);
}
/*
------------------------------------------------------------------------
follow.c:
-------------------------------------------------------------------------
*/
#include "follow.h"
#include "sys.h"
//初始化exti函数
void follow_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOA时钟
gpio_initstruct.Pin = GPIO_PIN_5 | GPIO_PIN_6;
gpio_initstruct.Mode = GPIO_MODE_INPUT;
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
}
uint8_t follow_left_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
uint8_t follow_right_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
/*
------------------------------------------------------------------------
track.c:
-------------------------------------------------------------------------
*/
#include "track.h"
#include "sys.h"
//初始化exti函数
void track_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOA时钟
gpio_initstruct.Pin = GPIO_PIN_13 | GPIO_PIN_14;
gpio_initstruct.Mode = GPIO_MODE_INPUT;
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
}
uint8_t track_left_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
uint8_t track_right_flag(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_RESET)
return TRUE;
else
return FALSE;
}
/*
------------------------------------------------------------------------
hcsr04.c:
-------------------------------------------------------------------------
*/
#include "hcsr04.h"
#include "delay.h"
TIM_HandleTypeDef tim2_handler ={0};
//定时器初始化函数
void tim2_init(void)
{
tim2_handler.Instance =TIM2;
tim2_handler.Init.Prescaler = 72 - 1;
tim2_handler.Init.Period = 65536 - 1;
tim2_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
tim2_handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&tim2_handler);
HAL_TIM_Base_Start_IT(&tim2_handler);
}
//msp函数
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
__HAL_RCC_TIM2_CLK_ENABLE();
}
}
//定时器开启
void tim2_start(void)
{
HAL_TIM_Base_Start(&tim2_handler);
}
//定时器关闭
void tim2_stop(void)
{
HAL_TIM_Base_Stop(&tim2_handler);
}
//获取定时器的计数器值
uint16_t tim2_get_cnt(void)
{
return __HAL_TIM_GetCounter(&tim2_handler);
}
//设定定时器的计数器值
void tim2_set_cnt(uint16_t val)
{
__HAL_TIM_SetCounter(&tim2_handler,val);
}
//hcsr04所用GPIO初始化
void hcsr04_gpio_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
TRIG_GPIO_CLK_ENABLE();
ECHO_GPIO_CLK_ENABLE();
//初始化Trig引脚
gpio_initstruct.Pin = TRIG_PIN;
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
gpio_initstruct.Pull = GPIO_NOPULL;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(TRIG_PORT,&gpio_initstruct);
//初始化Echo引脚
gpio_initstruct.Pin = ECHO_PIN;
gpio_initstruct.Mode = GPIO_MODE_INPUT; //输入
HAL_GPIO_Init(ECHO_PORT,&gpio_initstruct);
}
//hcsr04初始化
void hcsr04_init(void)
{
tim2_init();
hcsr04_gpio_init();
}
//hcsr04获取距离
float hcsr04_get_length(void)
{
uint16_t total_time = 0;
float distance = 0;
//1.Trig,给Trig端口至少10us的高电平
TRIG_HIGH();
delay_us(15);
TRIG_LOW();
//2.Echo引脚,由低电平跳转到高电平,表示开始发送波
while(ECHO_STATUS() == GPIO_PIN_RESET);
tim2_start();
tim2_set_cnt(0);
//3.Echo,由高电平跳转回低电平,表示波回来了
//Echo引脚维持高电平的时间,波发出去的那一下,开始启动定时器,波回来的那一下,我们开始停止定时器,
while(ECHO_STATUS() == GPIO_PIN_SET);
tim2_stop();
//4.计算出中间经过多少时间
total_time = tim2_get_cnt();
//5.距离 = 速度(343m/s) * 时间 / 2
distance = total_time*0.01715;
return distance;
}
/*
------------------------------------------------------------------------
sg90.c:
-------------------------------------------------------------------------
*/
#include "sg90.h"
TIM_HandleTypeDef tim3_handler = {0};
//pwm初始化
void tim3_init(void)
{
TIM_OC_InitTypeDef pwm_config = {0};
tim3_handler.Instance = TIM3 ;
tim3_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
tim3_handler.Init.Period = 200 - 1;
tim3_handler.Init.Prescaler = 7200-1;
//HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
HAL_TIM_PWM_Init(&tim3_handler);
// HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
// const TIM_OC_InitTypeDef *sConfig,
// uint32_t Channel)
pwm_config.OCMode = TIM_OCMODE_PWM1;
pwm_config.Pulse = 100;
pwm_config.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&tim3_handler,&pwm_config,TIM_CHANNEL_1);
//HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
HAL_TIM_PWM_Start(&tim3_handler,TIM_CHANNEL_1);
}
//msp初始化
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOB时钟
__HAL_RCC_TIM3_CLK_ENABLE();//使能TIM3时钟
//调用GPIO初始化函数
//HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
gpio_initstruct.Pin = GPIO_PIN_6;
gpio_initstruct.Mode = GPIO_MODE_AF_PP; // 复合推挽输出
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
}
}
//修改CCR寄存器值
void tim3_compare_set(uint16_t val)
{
//__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
__HAL_TIM_SET_COMPARE(&tim3_handler,TIM_CHANNEL_1,val);
}
//sg90初始化
void sg90_init(void)
{
tim3_init();
}
//舵机角度设定
void sg90_angle_set(uint16_t angle)
{
uint16_t CCRx = (1.0/9.0)*angle + 5.0;
tim3_compare_set(CCRx);
}
//向左转函数sg90_turn_left()
void sg90_turn_left(void)
{
sg90_angle_set(180);
}
//向中转函数sg90_turn_middle()
void sg90_turn_middle(void)
{
sg90_angle_set(90);
}
//向右转函数sg90_turn_right
void sg90_turn_right(void)
{
sg90_angle_set(0);
}
/*
------------------------------------------------------------------------
voice.c:
-------------------------------------------------------------------------
*/
#include "voice.h"
//voice模块进行声言模块初始化GPIO口voice_init()
void voice_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2;
gpio_initstruct.Mode = GPIO_MODE_INPUT;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
}
/*
------------------------------------------------------------------------
motor.h:
-------------------------------------------------------------------------
*/
#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "sys.h"
void motor_init(void);
void motor_go_forward(void);
void motor_go_backward(void);
void motor_go_left(void);
void motor_go_right(void);
void motor_stop(void);
#endif
/*
------------------------------------------------------------------------
follow.h:
-------------------------------------------------------------------------
*/
#ifndef __FOLLOW_H__
#define __FOLLOW_H__
#include "stdint.h"
#define TRUE 1
#define FALSE 0
void follow_init(void);
uint8_t follow_left_flag(void);
uint8_t follow_right_flag(void);
#endif
/*
------------------------------------------------------------------------
track.h:
-------------------------------------------------------------------------
*/
#ifndef __TRACK_H__
#define __TRACK_H__
#include "stdint.h"
#define TRUE 1
#define FALSE 0
void track_init(void);
uint8_t track_left_flag(void);
uint8_t track_right_flag(void);
#endif
/*
------------------------------------------------------------------------
hcsr04.h:
-------------------------------------------------------------------------
*/
#ifndef __HCSR04_H__
#define __HCSR04_H__
#include "sys.h"
#define TRIG_PORT GPIOB
#define TRIG_PIN GPIO_PIN_6
#define TRIG_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE();
#define TRIG_HIGH() HAL_GPIO_WritePin(TRIG_PORT,TRIG_PIN,GPIO_PIN_SET)
#define TRIG_LOW() HAL_GPIO_WritePin(TRIG_PORT,TRIG_PIN,GPIO_PIN_RESET)
#define ECHO_PORT GPIOB
#define ECHO_PIN GPIO_PIN_7
#define ECHO_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE();
#define ECHO_STATUS() HAL_GPIO_ReadPin(ECHO_PORT,ECHO_PIN)
void hcsr04_init(void);
float hcsr04_get_length(void);
#endif
/*
------------------------------------------------------------------------
sg90.h:
-------------------------------------------------------------------------
*/
#ifndef __SG90_H__
#define __SG90_H__
#include "sys.h"
void sg90_init(void);
void sg90_turn_left(void);
void sg90_turn_middle(void);
void sg90_turn_right(void);
#endif
/*
------------------------------------------------------------------------
voice.h:
-------------------------------------------------------------------------
*/
#ifndef __VOICE_H__
#define __VOICE_H__
#include "sys.h"
#define TRACK_PIN HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)
#define AVOID_PIN HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)
#define FOLLOW_PIN HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
void voice_init(void);
#endif
作者:Aspiring Q