while (1)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
2.检测按键:HAL_GPIO_WritePin
按下按键为亮,松开为灭
cpp复制代码
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
//读取按键状态
HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//如果读取到按键为低电平,说明按下按键
if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)==GPIO_PIN_RESET){
//如果按下,将led点亮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
}
else{//反之按下没有反应
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
void backword(){
//电机后进:则将左右的IN+设置为低电平,左右的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_RESET);//left 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_RESET);//right 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN_Pin,GPIO_PIN_SET);//left 的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_SET);//right 的IN-设置为高电平
}
void forword(){
//电机前进:则将左右的IN+设置为高电平,左右的IN-设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);//left 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);//right 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN_Pin,GPIO_PIN_RESET);//left 的IN-设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);//right 的IN-设置为低电平
}
//按键检测
int key_detection(){
if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==GPIO_PIN_RESET){
return 1;
}
return 0;
}
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
//使能电机
HAL_GPIO_WritePin(GPIOB, MOTOR_L_S_Pin|MOTOR_R_S_Pin,GPIO_PIN_SET);
//定义按键
HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
A:while(1){
forword();
if(key_detection()==1){
HAL_Delay(100);//消抖
if(key_detection()==1){
goto B;
}
}
}
B:while(1){
forword();
if(key_detection()==1){
HAL_Delay(100);//消抖
if(key_detection()==1){
goto A;
}
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 16;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/**
1)如果左边越界,则用户指示灯闪烁减慢【HAL_Delay(1000)】,红外模块上的led熄灭
2)如果右边越界,则用户指示灯闪烁一般速度【HAL_Delay(500)】,红外模块上的led熄灭
3)如果正常行驶,用户指示灯熄灭【HAL_GPIO_WritePin(SET)-->输入高电平,熄灭】,红外模块上的led都熄灭
4)如果左右都越界(整个车头越界),则用户指示灯闪烁加快【HAL_Delay(50)】
*/
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//越界判断
int cross(){
//【注意点】
//判断整个车头是否越界应该放在第一个进行判断,因为如果先将单个判断放在第一个则后面无法进行判断
if(HAL_GPIO_ReadPin(GPIOB,IR_TRACK_L_Pin) && HAL_GPIO_ReadPin(GPIOB,IR_TRACK_R_Pin)==0){//表示两边都越界【整个车头】
return 1;
}else if(HAL_GPIO_ReadPin(GPIOB,IR_TRACK_L_Pin)==0){//表示左边越界
return 2;
}else if(HAL_GPIO_ReadPin(GPIOB,IR_TRACK_R_Pin)==0){//表示右边越界
return 3;
}else{
return 4;
}
}
//led闪烁速度转换
void led_speed(unsigned int time){
HAL_GPIO_TogglePin(user_led_GPIO_Port,user_led_Pin);
HAL_Delay(time);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
switch(cross()){
//整个车头越界
case 1:
led_speed(50);
break;
//左边越界
case 2:
led_speed(1000);
break;
//右边越界
case 3:
led_speed(500);
break;
//正常行驶时,用户指示灯熄灭
case 4:
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 16;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
5.左边越界后小车右转
1.设置电机模块
2.代码编写
cpp复制代码
//前进
void forward(){
//使能左右电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port,MOTOR_R_S_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port,MOTOR_L_S_Pin,GPIO_PIN_SET);
//IN+:设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);
//IN-:设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);
}
//右转
void go_right(){
//失能右电机(right)
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port,MOTOR_R_S_Pin,GPIO_PIN_RESET);
//使能左电机(left)
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port,MOTOR_L_S_Pin,GPIO_PIN_SET);
//IN+:设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);
//IN-:设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);
}
//左转
void go_left(){
//使能右电机(right)
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port,MOTOR_R_S_Pin,GPIO_PIN_SET);
//失能左电机(left)
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port,MOTOR_L_S_Pin,GPIO_PIN_RESET);
//IN+:设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);
//IN-:设置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_GPIO_ReadPin(IR_TRACK_L_GPIO_Port,IR_TRACK_L_Pin)==0){
//表示左边此时越界,则应该往右走
go_right();
}else if(HAL_GPIO_ReadPin(IR_TRACK_R_GPIO_Port,IR_TRACK_R_Pin)==0){
//表示右边此时越界,则应该往左走
go_left();
}
else{//说明此时为不越界
forward();
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
6.完整代码
当整个车头越界时,会后退,然后再重新规划路线
cpp复制代码
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void backword(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
//电机后进:则将左右的IN+设置为低电平,左右的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_RESET);//left 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_RESET);//right 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_SET);//left 的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_SET);//right 的IN-设置为高电平
}
void forword(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
//电机后进:则将左右的IN+设置为低电平,左右的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);//left 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);//right 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);//left 的IN-设置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);//right 的IN-设置为低电平
}
//左转前进:左边的轮子不动,右边的轮子动
//左边轮子不使能,右边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void left_forward(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_RESET);//不使能左轮子
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);//right 的IN+设置为高置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);//right 的IN-设置为低电平
}
//左转后退:左边的轮子不动,右边的轮子动
//左边轮子不使能,右边的轮子使能,并且将IN+设置为低电平,IN-设置为高电平
void left_back(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_RESET);//不使能左轮子
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_RESET);//right 的IN+设置为高置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_SET);//right 的IN-设置为高电平
}
//右转前进:右边的轮子不动,左边的轮子动
//右边轮子不使能,左边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void right_forward(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);//left 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);//left 的IN-设置为低电平
}
//右转后退:右边的轮子不动,左边的轮子动
//右边轮子不使能,左边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void right_back(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_RESET);//left 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_SET);//left 的IN-设置为高电平
}
//停止
void stop(){
//使能电机
HAL_GPIO_WritePin(GPIOB, MOTOR_L_S_Pin,GPIO_PIN_RESET);//不使能左轮子
HAL_GPIO_WritePin(GPIOB, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//这里还有问题:待解决~~~~~~~~~~~~【但是前后退模块是正确的】
if(HAL_GPIO_ReadPin(IR_TRACK_L_GPIO_Port,IR_TRACK_L_Pin) && HAL_GPIO_ReadPin(IR_TRACK_R_GPIO_Port,IR_TRACK_R_Pin)==0){
//说明此时整个车头越界
//先让其后退
backword();
//在让其延时一会(后退一会)
HAL_Delay(500);
//在让其左/右转,在循环多次之后,肯定会找到一个合适的路线继续行驶
right_forward();
}else if(HAL_GPIO_ReadPin(IR_TRACK_L_GPIO_Port,IR_TRACK_L_Pin)==0){
//说明此时左边越界,应该往右边走
right_forward();
}else if(HAL_GPIO_ReadPin(IR_TRACK_R_GPIO_Port,IR_TRACK_R_Pin)==0){
//说明此时右边越界,应该往左边走
left_forward();
}else{
//都没有越界,则往前走
forword();
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
while (1)
{
if(HAL_GPIO_ReadPin(IR_OA_L_GPIO_Port,IR_OA_L_Pin)==0){//此时表示遇到障碍物,led1亮
//此时我们点亮用户led
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_RESET);
}else{//此时表示遇到障碍物,led1不亮
//此时我们不点亮用户led
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
2.右边有障碍物用户led亮起
原理同上面一致
1.代码编写
cpp复制代码
while (1)
{
if(HAL_GPIO_ReadPin(IR_OA_R_GPIO_Port,IR_OA_R_Pin==0){//此时表示遇到障碍物,led1亮
//此时我们点亮用户led
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_RESET);
}else{//此时表示遇到障碍物,led1不亮
//此时我们不点亮用户led
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
3..前方有障碍物用户led亮起
前面两个同时越界--->led闪烁
左边有障碍物--->led会亮,设置用户led也亮
右边有障碍物----->led会亮,设置用户led也亮
都无障碍物-->两个led都灭
cpp复制代码
while (1)
{
if(HAL_GPIO_ReadPin(IR_OA_L_GPIO_Port,IR_OA_L_Pin) && HAL_GPIO_ReadPin(IR_OA_R_GPIO_Port,IR_OA_R_Pin)==0){
//表示前面两个都遇到障碍物
led_speed();
}
else if(HAL_GPIO_ReadPin(IR_OA_L_GPIO_Port,IR_OA_L_Pin)==0){//此时表示遇到障碍物,led1亮
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_RESET);
}else if(HAL_GPIO_ReadPin(IR_OA_R_GPIO_Port,IR_OA_R_Pin)==0){
//遇到障碍物用户led亮起来
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_RESET);
}else{//此时表示没有遇到障碍物,led1不亮
//此时我们不点亮用户led
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
4.前方有障碍物代码
cpp复制代码
void backword(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
//电机后进:则将左右的IN+设置为低电平,左右的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_RESET);//left 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_RESET);//right 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_SET);//left 的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_SET);//right 的IN-设置为高电平
}
void forword(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
//电机后进:则将左右的IN+设置为低电平,左右的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);//left 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);//right 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);//left 的IN-设置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);//right 的IN-设置为低电平
}
//左转前进:左边的轮子不动,右边的轮子动
//左边轮子不使能,右边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void left_forward(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_RESET);//不使能左轮子
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);//right 的IN+设置为高置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);//right 的IN-设置为低电平
}
//左转后退:左边的轮子不动,右边的轮子动
//左边轮子不使能,右边的轮子使能,并且将IN+设置为低电平,IN-设置为高电平
void left_back(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_RESET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_RESET);//right 的IN+设置为高置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_SET);//right 的IN-设置为高电平
}
//右转前进:右边的轮子不动,左边的轮子动
//右边轮子不使能,左边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void right_forward(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);//left 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);//left 的IN-设置为低电平
}
//右转后退:右边的轮子不动,左边的轮子动
//右边轮子不使能,左边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void right_back(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_RESET);//left 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_SET);//left 的IN-设置为高电平
}
//停止
void stop(){
//使能电机
HAL_GPIO_WritePin(GPIOB, MOTOR_L_S_Pin,GPIO_PIN_RESET);//不使能左轮子
HAL_GPIO_WritePin(GPIOB, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if((HAL_GPIO_ReadPin(IR_OA_L_GPIO_Port,IR_OA_L_Pin)==0)&& (HAL_GPIO_ReadPin(IR_OA_R_GPIO_Port,IR_OA_R_Pin)==0)){
backword();
HAL_Delay(500);
right_forward();
}
else if(HAL_GPIO_ReadPin(IR_OA_L_GPIO_Port,IR_OA_L_Pin)==0){
//此时表示左边遇到障碍物,则led1亮起
//我们应该想右转
right_forward();
}else if(HAL_GPIO_ReadPin(IR_OA_R_GPIO_Port,IR_OA_R_Pin)==0){
//此时表示右边遇到障碍物,则led1亮起
//我们应该想左转
left_forward();
}else{
//没有遇到障碍物向前
forword();
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
#include "stdio.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
//上升沿
uint32_t isUpcat=1;//表示默认为上升沿
uint32_t valueUp=0;
uint32_t valueDown=0;
//脉冲宽度
uint32_t kuandu=0;
uint16_t buffer[128]={0};
uint16_t buffer_ID=0;
//接收标志位:判断此时buffer中的数据是否已经填满
uint16_t rvcFlag=0;
char ceshi[]="start";
char yaokong;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void backword(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
//电机后进:则将左右的IN+设置为低电平,左右的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_RESET);//left 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_RESET);//right 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_SET);//left 的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_SET);//right 的IN-设置为高电平
}
void forword(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
//电机后进:则将左右的IN+设置为低电平,左右的IN-设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);//left 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);//right 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);//left 的IN-设置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);//right 的IN-设置为低电平
}
//左转前进:左边的轮子不动,右边的轮子动
//左边轮子不使能,右边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void left_forward(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_RESET);//不使能左轮子
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_SET);//right 的IN+设置为高置为高电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_RESET);//right 的IN-设置为低电平
}
//左转后退:左边的轮子不动,右边的轮子动
//左边轮子不使能,右边的轮子使能,并且将IN+设置为低电平,IN-设置为高电平
void left_back(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_SET);//使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_RESET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_R_IN__GPIO_Port,MOTOR_R_IN__Pin,GPIO_PIN_RESET);//right 的IN+设置为高置为低电平
HAL_GPIO_WritePin(MOTOR_R_IN_B6_GPIO_Port,MOTOR_R_IN_B6_Pin,GPIO_PIN_SET);//right 的IN-设置为高电平
}
//右转前进:右边的轮子不动,左边的轮子动
//右边轮子不使能,左边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void right_forward(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_SET);//left 的IN+设置为高电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_RESET);//left 的IN-设置为低电平
}
//右转后退:右边的轮子不动,左边的轮子动
//右边轮子不使能,左边的轮子使能,并且将IN+设置为高电平,IN-设置为低电平
void right_back(){
//使能电机
HAL_GPIO_WritePin(MOTOR_R_S_GPIO_Port, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
HAL_GPIO_WritePin(MOTOR_L_S_GPIO_Port, MOTOR_L_S_Pin,GPIO_PIN_SET);//使能左轮子
HAL_GPIO_WritePin(MOTOR_L_IN__GPIO_Port,MOTOR_L_IN__Pin,GPIO_PIN_RESET);//left 的IN+设置为低电平
HAL_GPIO_WritePin(MOTOR_L_IN_B12_GPIO_Port,MOTOR_L_IN_B12_Pin,GPIO_PIN_SET);//left 的IN-设置为高电平
}
//停止
void stop(){
//使能电机
HAL_GPIO_WritePin(GPIOB, MOTOR_L_S_Pin,GPIO_PIN_RESET);//不使能左轮子
HAL_GPIO_WritePin(GPIOB, MOTOR_R_S_Pin,GPIO_PIN_RESET);//不使能右轮子
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
//发生测试串口代码
HAL_UART_Transmit(&huart1,(uint8_t*)ceshi,strlen(ceshi),HAL_MAX_DELAY);
//使能输入捕获中断【定时器中的】
HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);
//使能定时器中断
HAL_TIM_Base_Start_IT(&htim1);
char printfbuffer[128]={0};
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(rvcFlag){//接收到红外标志信号,表示数据接收完成
for(int i=0;i<33;i++){
//将从红外中获取的数据打印给printfbuffer
sprintf(printfbuffer," %u",buffer[i]);
//显示测试代码
//HAL_MAX_DELAY:最大超时时间
HAL_UART_Transmit(&huart1,(uint8_t*)printfbuffer,strlen(printfbuffer),HAL_MAX_DELAY);
//换行
if(i%8==0){
HAL_UART_Transmit(&huart1,"\n",2,HAL_MAX_DELAY);
}
}
//将标志位清零,等待下一次传输的数据
rvcFlag=0;
//将获取到的遥控数值转换为逻辑1或者逻辑0
for(int i=0;i<8;i++){
if(buffer[16+i]>=1400 && buffer[16+i]<1700){
yaokong |=0x01;//将其设置为逻辑1
}else if(buffer[16+i]>=400 && buffer[16+i]<=600){
yaokong |=0x00;//将其设置为逻辑0
}else {
//错误处理
}
yaokong<<=1;
}
switch(yaokong){
case 0x18://对应按键2
forword();
yaokong=0;
break;
case 0x4a://对应按键8
backword();
yaokong=0;
break;
case 0x10://对应按键4
left_forward();
yaokong=0;
break;
case 0x5a://对应按键6
right_forward();
yaokong=0;
break;
case 0x42://对应按键7
left_back();
yaokong=0;
break;
case 0x52://对应按键9
right_back();
yaokong=0;
break;
case 0x38://对应按键8
stop();
yaokong=0;
break;
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 16;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
//定时器的中断处理回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
//判断是否为上升沿捕获
if(isUpcat){
//将捕获的定时器的值赋值给valueUp
valueUp=HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);
//将上升沿置为0
isUpcat=0;//是否为上升沿的标志位
//触发捕获事件的信号边沿
__HAL_TIM_SET_CAPTUREPOLARITY(&htim1,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);
}else{//捕获下降沿
//将捕获的定时器的值赋值给valueDown
valueDown=HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);
//将上升沿置为1
isUpcat=1;//是否为上升沿的标志位
//触发捕获事件的信号边沿
__HAL_TIM_SET_CAPTUREPOLARITY(&htim1,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);
//计算差值
kuandu=valueDown-valueUp;//取到了脉冲宽度
//判断输入进来的数据是否是我们想要的【判断同步码头】
if(kuandu>=4400 && kuandu <=4600){//接收码头的范围
buffer_ID=0;//这个值用来判断我遍历到数组中的哪一个位置
buffer[buffer_ID++]=kuandu;//将我们获得的数据填入
}else if(buffer_ID>0){//表示此时我们还没有填充完整
//接着往下填充
buffer[buffer_ID++]=kuandu;
if(buffer_ID>32){//表示接收完毕
rvcFlag=1;//红外接收标志位,表示数据接收完成
//将指针设置回开头
buffer_ID=0;
}
}
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
while (1)
{
//判断一次数据传输接收是否完成
if(ready){
juli=jisuan(kuandu);//计算出距离
//将距离打印出来
sprintf(printfJuli," %u",juli);
//通过串口打印
HAL_UART_Transmit(&huart1,(uint8_t*)printfJuli,strlen(printfJuli),HAL_MAX_DELAY);
//记得将ready复位,才可以进行下一次数据采样
ready=0;
}
//因为我们需要先制造一次上升沿的触发信号才可以进行数据接收,所以这里一定要写这个
//先将电平拉低,在拉高制造一个上升沿
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_SET);
//设置用户指示灯
//当物体靠近设定值,则灯亮起
if(juli<=200){
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_RESET);
}else{
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
7.完整代码
cpp复制代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t isUpcat=1;//默认输入高电平
uint16_t valueUp=0;
uint16_t valueDown=0;
//输出回响信号
uint32_t kuandu=0;
//数据接收完毕状态位
uint16_t ready=0;
//距离计算结果
uint32_t juli=0;
//将存放获得的数据
char printfJuli[124]={0};
uint32_t jisuan(uint16_t kuandu);
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
//串口测试
HAL_UART_Transmit(&huart1,"go!",3,HAL_MAX_DELAY);
//开启定时器输入捕获
HAL_TIM_IC_Start_IT(&htim17,TIM_CHANNEL_1);
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM17_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
//先将电平拉低,在拉高制造一个上升沿
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_SET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//判断一次数据传输接收是否完成
if(ready){
juli=jisuan(kuandu);//计算出距离
//将距离打印出来
sprintf(printfJuli," %u",juli);
//通过串口打印
HAL_UART_Transmit(&huart1,(uint8_t*)printfJuli,strlen(printfJuli),HAL_MAX_DELAY);
//记得将ready复位,才可以进行下一次数据采样
ready=0;
}
//因为我们需要先制造一次上升沿的触发信号才可以进行数据接收,所以这里一定要写这个
//先将电平拉低,在拉高制造一个上升沿
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_SET);
//设置用户指示灯
//当物体靠近设定值,则灯亮起
if(juli<=200){
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_RESET);
}else{
HAL_GPIO_WritePin(user_led_GPIO_Port,user_led_Pin,GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 16;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
//定时器输入捕获(回调函数)-->传输一次数据后得到的数值
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
if(isUpcat){
//获取上升沿的值
valueUp=HAL_TIM_ReadCapturedValue(&htim17,TIM_CHANNEL_1);
//将输入捕获模式改为下降沿触发
__HAL_TIM_SET_CAPTUREPOLARITY(&htim17,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
isUpcat=0;
}else{
//获取下降沿的值
valueDown=HAL_TIM_ReadCapturedValue(&htim17,TIM_CHANNEL_1);
//将输入捕获模式改为上升沿触发
__HAL_TIM_SET_CAPTUREPOLARITY(&htim17,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
isUpcat=1;
//计算宽度(输出回响信号)
kuandu=valueDown-valueUp;
//表示数据接收完成
ready=1;
}
}
uint32_t jisuan(uint16_t kuandu){
//此处我们/1000,是将长度单位改为毫米
//计算公式=高电平时间*340m/s(光速)/2
return kuandu*340/2/1000;
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
//画直线
//***************************************
// * @param x1 起始点横坐标
// * @param y1 起始点纵坐标
// * @param x2 终止点横坐标
// * @param y2 终止点纵坐标
//****************************************
void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
static uint8_t temp = 0;
if (x1 == x2)
{
if (y1 > y2)
{
temp = y1;
y1 = y2;
y2 = temp;
}
for (uint8_t y = y1; y <= y2; y++)
{
OLED_SetPixel(x1, y);
}
}
else if (y1 == y2)
{
if (x1 > x2)
{
temp = x1;
x1 = x2;
x2 = temp;
}
for (uint8_t x = x1; x <= x2; x++)
{
OLED_SetPixel(x, y1);
}
}
else
{
// Bresenham直线算法
int16_t dx = x2 - x1;
int16_t dy = y2 - y1;
int16_t ux = ((dx > 0) << 1) - 1;
int16_t uy = ((dy > 0) << 1) - 1;
int16_t x = x1, y = y1, eps = 0;
dx = abs(dx);
dy = abs(dy);
if (dx > dy)
{
for (x = x1; x != x2; x += ux)
{
OLED_SetPixel(x, y);
eps += dy;
if ((eps << 1) >= dx)
{
y += uy;
eps -= dx;
}
}
}
else
{
for (y = y1; y != y2; y += uy)
{
OLED_SetPixel(x, y);
eps += dx;
if ((eps << 1) >= dy)
{
x += ux;
eps -= dy;
}
}
}
}
}
//绘制矩形
//********************
// * @param x 起始点横坐标
// * @param y 起始点纵坐标
// * @param w 矩形宽度
// * @param h 矩形高度
//*********************
void OLED_DrawRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
{
OLED_DrawLine(x, y, x + w, y);
OLED_DrawLine(x, y + h, x + w, y + h);
OLED_DrawLine(x, y, x, y + h);
OLED_DrawLine(x + w, y, x + w, y + h);
}
//绘制圆形
//********************
// * @param x 圆心横坐标
// * @param y 圆心纵坐标
// * @param r 圆半径
//********************
void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r)
{
int16_t a = 0, b = r, di = 3 - (r << 1);
while (a <= b)
{
OLED_SetPixel(x - b, y - a);
OLED_SetPixel(x + b, y - a);
OLED_SetPixel(x - a, y + b);
OLED_SetPixel(x - b, y - a);
OLED_SetPixel(x - a, y - b);
OLED_SetPixel(x + b, y + a);
OLED_SetPixel(x + a, y - b);
OLED_SetPixel(x + a, y + b);
OLED_SetPixel(x - b, y + a);
a++;
if (di < 0)
{
di += 4 * a + 6;
}
else
{
di += 10 + 4 * (a - b);
b--;
}
OLED_SetPixel(x + a, y + b);
}
}
//绘制填充三角形
//************************
// * @param x1 第一个点横坐标
// * @param y1 第一个点纵坐标
// * @param x2 第二个点横坐标
// * @param y2 第二个点纵坐标
// * @param x3 第三个点横坐标
// * @param y3 第三个点纵坐标
//*************************
void OLED_DrawFilledTriangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t x3, uint8_t y3)
{
uint8_t a = 0, b = 0, y = 0, last = 0;
if (y1 > y2)
{
a = y2;
b = y1;
}
else
{
a = y1;
b = y2;
}
y = a;
for (; y <= b; y++)
{
if (y <= y3)
{
OLED_DrawLine(x1 + (y - y1) * (x2 - x1) / (y2 - y1), y, x1 + (y - y1) * (x3 - x1) / (y3 - y1), y);
}
else
{
last = y - 1;
break;
}
}
for (; y <= b; y++)
{
OLED_DrawLine(x2 + (y - y2) * (x3 - x2) / (y3 - y2), y, x1 + (y - last) * (x3 - x1) / (y3 - last), y);
}
}
//绘制一个填充圆
// * @param x 圆心横坐标
// * @param y 圆心纵坐标
// * @param r 圆半径
void OLED_DrawFilledCircle(uint8_t x, uint8_t y, uint8_t r)
{
int16_t a = 0, b = r, di = 3 - (r << 1);
while (a <= b)
{
for (int16_t i = x - b; i <= x + b; i++)
{
OLED_SetPixel(i, y + a);
OLED_SetPixel(i, y - a);
}
for (int16_t i = x - a; i <= x + a; i++)
{
OLED_SetPixel(i, y + b);
OLED_SetPixel(i, y - b);
}
a++;
if (di < 0)
{
di += 4 * a + 6;
}
else
{
di += 10 + 4 * (a - b);
b--;
}
}
}
//*****************************
// * @brief 绘制一个椭圆
// * @param x 椭圆中心横坐标
// * @param y 椭圆中心纵坐标
// * @param a 椭圆长轴
// * @param b 椭圆短轴
//******************************
void OLED_DrawEllipse(uint8_t x, uint8_t y, uint8_t a, uint8_t b)
{
int xpos = 0, ypos = b;
int a2 = a * a, b2 = b * b;
int d = b2 + a2 * (0.25 - b);
while (a2 * ypos > b2 * xpos)
{
OLED_SetPixel(x + xpos, y + ypos);
OLED_SetPixel(x - xpos, y + ypos);
OLED_SetPixel(x + xpos, y - ypos);
OLED_SetPixel(x - xpos, y - ypos);
if (d < 0)
{
d = d + b2 * ((xpos << 1) + 3);
xpos += 1;
}
else
{
d = d + b2 * ((xpos << 1) + 3) + a2 * (-(ypos << 1) + 2);
xpos += 1, ypos -= 1;
}
}
d = b2 * (xpos + 0.5) * (xpos + 0.5) + a2 * (ypos - 1) * (ypos - 1) - a2 * b2;
while (ypos > 0)
{
OLED_SetPixel(x + xpos, y + ypos);
OLED_SetPixel(x - xpos, y + ypos);
OLED_SetPixel(x + xpos, y - ypos);
OLED_SetPixel(x - xpos, y - ypos);
if (d < 0)
{
d = d + b2 * ((xpos << 1) + 2) + a2 * (-(ypos << 1) + 3);
xpos += 1, ypos -= 1;
}
else
{
d = d + a2 * (-(ypos << 1) + 3);
ypos -= 1;
}
}
}
8.完整代码
1.oled.c
cpp复制代码
#include "oled.h"
#include "string.h"
//这个是我们OLED的地址【开发方给的】
#define OLED_ADDRESS 0x78
//存储一页数据
uint16_t GRAM[8][128]={0};
//在显示屏上显示数据
void OLED_SendCmd(uint8_t cmd){
uint8_t SendBuffer[2];
SendBuffer[0]=0x00;//告诉他,我们要开始发送数据了【固定的】
SendBuffer[1]=cmd;
//IIC发送信息
//OLED_ADDRESS:发送者的地址
HAL_I2C_Master_Transmit(&hi2c1,OLED_ADDRESS,SendBuffer,strlen(SendBuffer),HAL_MAX_DELAY);
}
//OLED初始化
void OLED_Init()
{
OLED_SendCmd(0xAE); /*关闭显示 display off*/
OLED_SendCmd(0x20);
OLED_SendCmd(0x10);
OLED_SendCmd(0xB0);
OLED_SendCmd(0xC8);
OLED_SendCmd(0x00);
OLED_SendCmd(0x10);
OLED_SendCmd(0x40);
OLED_SendCmd(0x81);
OLED_SendCmd(0xDF);
OLED_SendCmd(0xA1);
OLED_SendCmd(0xA6);
OLED_SendCmd(0xA8);
OLED_SendCmd(0x3F);
OLED_SendCmd(0xA4);
OLED_SendCmd(0xD3);
OLED_SendCmd(0x00);
OLED_SendCmd(0xD5);
OLED_SendCmd(0xF0);
OLED_SendCmd(0xD9);
OLED_SendCmd(0x22);
OLED_SendCmd(0xDA);
OLED_SendCmd(0x12);
OLED_SendCmd(0xDB);
OLED_SendCmd(0x20);
OLED_SendCmd(0x8D);
OLED_SendCmd(0x14);
OLED_SendCmd(0xAF); /*开启显示 display ON*/
}
//测试函数
void OLED_test(){
//我们发送的显示的位置为:第一列的第一行
OLED_SendCmd(0xB0);//页地址(一共分为8块,1块8行)
OLED_SendCmd(0x00);//列地址(分为2份表示)
OLED_SendCmd(0x10);
//要发送的数据
//0x40:表示我们要开始发送数据【发送标志位】
//0xaa:发送的数据
uint8_t sendBuffer[]={0x40,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa};
//IIC发送信息
HAL_I2C_Master_Transmit(&hi2c1,OLED_ADDRESS,sendBuffer,strlen(sendBuffer),HAL_MAX_DELAY);
}
//因为我们在显示数据前应该先清屏
//要不然会出现问题
void Clear_OLED(){
for(uint8_t i=0;i<8;i++){
for(uint8_t j=0;j<128;j++){
GRAM[i][j]=0;
}
}
}
//将显存中的数据,显示到OLED上
void OLED_ShowFrams(){
//第一个是发送的指令【表示我们要发送的是数据】
uint8_t SendSGRM[129];//存储发送的数据
SendSGRM[0]=0x40;//告诉是发送给屏幕的数据(指令)
for(uint8_t i=0;i<8;i++){
for(uint8_t j=0;j<128;j++){
//j+1:因为第一个存放了指令,后面才是存放数据
SendSGRM[j+1]=GRAM[i][j];
}
//设置页地址
OLED_SendCmd(0xb0+i);
//设置列地址(由于列地址会自己换列,所以不需要自己手动换)
OLED_SendCmd(0x00);//表示第一行
OLED_SendCmd(0x10);//表示第一列
//将数据发送给IIC
HAL_I2C_Master_Transmit(&hi2c1,OLED_ADDRESS,SendSGRM,strlen(SendSGRM),HAL_MAX_DELAY);
}
}
//显示一个像素
void OLED_Setpixel(uint16_t x,uint16_t y){//x:列 y:表示行【页】
//判断是否越界
if(x>=128 || y>=64){
return;
}
//y/8:表示第几页
//y%8:表示在该页的第几行
//0x01 << (y%8):将该行置为1,其他置为0
GRAM[y/8][x] |= 0x01 << (y%8);
}
//画直线
//***************************************
// * @param x1 起始点横坐标
// * @param y1 起始点纵坐标
// * @param x2 终止点横坐标
// * @param y2 终止点纵坐标
//****************************************
void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
static uint8_t temp = 0;
if (x1 == x2)
{
if (y1 > y2)
{
temp = y1;
y1 = y2;
y2 = temp;
}
for (uint8_t y = y1; y <= y2; y++)
{
OLED_SetPixel(x1, y);
}
}
else if (y1 == y2)
{
if (x1 > x2)
{
temp = x1;
x1 = x2;
x2 = temp;
}
for (uint8_t x = x1; x <= x2; x++)
{
OLED_SetPixel(x, y1);
}
}
else
{
// Bresenham直线算法
int16_t dx = x2 - x1;
int16_t dy = y2 - y1;
int16_t ux = ((dx > 0) << 1) - 1;
int16_t uy = ((dy > 0) << 1) - 1;
int16_t x = x1, y = y1, eps = 0;
dx = abs(dx);
dy = abs(dy);
if (dx > dy)
{
for (x = x1; x != x2; x += ux)
{
OLED_SetPixel(x, y);
eps += dy;
if ((eps << 1) >= dx)
{
y += uy;
eps -= dx;
}
}
}
else
{
for (y = y1; y != y2; y += uy)
{
OLED_SetPixel(x, y);
eps += dx;
if ((eps << 1) >= dy)
{
x += ux;
eps -= dy;
}
}
}
}
}
//绘制矩形
//********************
// * @param x 起始点横坐标
// * @param y 起始点纵坐标
// * @param w 矩形宽度
// * @param h 矩形高度
//*********************
void OLED_DrawRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
{
OLED_DrawLine(x, y, x + w, y);
OLED_DrawLine(x, y + h, x + w, y + h);
OLED_DrawLine(x, y, x, y + h);
OLED_DrawLine(x + w, y, x + w, y + h);
}
//绘制圆形
//********************
// * @param x 圆心横坐标
// * @param y 圆心纵坐标
// * @param r 圆半径
//********************
void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r)
{
int16_t a = 0, b = r, di = 3 - (r << 1);
while (a <= b)
{
OLED_SetPixel(x - b, y - a);
OLED_SetPixel(x + b, y - a);
OLED_SetPixel(x - a, y + b);
OLED_SetPixel(x - b, y - a);
OLED_SetPixel(x - a, y - b);
OLED_SetPixel(x + b, y + a);
OLED_SetPixel(x + a, y - b);
OLED_SetPixel(x + a, y + b);
OLED_SetPixel(x - b, y + a);
a++;
if (di < 0)
{
di += 4 * a + 6;
}
else
{
di += 10 + 4 * (a - b);
b--;
}
OLED_SetPixel(x + a, y + b);
}
}
//绘制填充三角形
//************************
// * @param x1 第一个点横坐标
// * @param y1 第一个点纵坐标
// * @param x2 第二个点横坐标
// * @param y2 第二个点纵坐标
// * @param x3 第三个点横坐标
// * @param y3 第三个点纵坐标
//*************************
void OLED_DrawFilledTriangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t x3, uint8_t y3)
{
uint8_t a = 0, b = 0, y = 0, last = 0;
if (y1 > y2)
{
a = y2;
b = y1;
}
else
{
a = y1;
b = y2;
}
y = a;
for (; y <= b; y++)
{
if (y <= y3)
{
OLED_DrawLine(x1 + (y - y1) * (x2 - x1) / (y2 - y1), y, x1 + (y - y1) * (x3 - x1) / (y3 - y1), y);
}
else
{
last = y - 1;
break;
}
}
for (; y <= b; y++)
{
OLED_DrawLine(x2 + (y - y2) * (x3 - x2) / (y3 - y2), y, x1 + (y - last) * (x3 - x1) / (y3 - last), y);
}
}
//绘制一个填充圆
// * @param x 圆心横坐标
// * @param y 圆心纵坐标
// * @param r 圆半径
void OLED_DrawFilledCircle(uint8_t x, uint8_t y, uint8_t r)
{
int16_t a = 0, b = r, di = 3 - (r << 1);
while (a <= b)
{
for (int16_t i = x - b; i <= x + b; i++)
{
OLED_SetPixel(i, y + a);
OLED_SetPixel(i, y - a);
}
for (int16_t i = x - a; i <= x + a; i++)
{
OLED_SetPixel(i, y + b);
OLED_SetPixel(i, y - b);
}
a++;
if (di < 0)
{
di += 4 * a + 6;
}
else
{
di += 10 + 4 * (a - b);
b--;
}
}
}
//*****************************
// * @brief 绘制一个椭圆
// * @param x 椭圆中心横坐标
// * @param y 椭圆中心纵坐标
// * @param a 椭圆长轴
// * @param b 椭圆短轴
//******************************
void OLED_DrawEllipse(uint8_t x, uint8_t y, uint8_t a, uint8_t b)
{
int xpos = 0, ypos = b;
int a2 = a * a, b2 = b * b;
int d = b2 + a2 * (0.25 - b);
while (a2 * ypos > b2 * xpos)
{
OLED_SetPixel(x + xpos, y + ypos);
OLED_SetPixel(x - xpos, y + ypos);
OLED_SetPixel(x + xpos, y - ypos);
OLED_SetPixel(x - xpos, y - ypos);
if (d < 0)
{
d = d + b2 * ((xpos << 1) + 3);
xpos += 1;
}
else
{
d = d + b2 * ((xpos << 1) + 3) + a2 * (-(ypos << 1) + 2);
xpos += 1, ypos -= 1;
}
}
d = b2 * (xpos + 0.5) * (xpos + 0.5) + a2 * (ypos - 1) * (ypos - 1) - a2 * b2;
while (ypos > 0)
{
OLED_SetPixel(x + xpos, y + ypos);
OLED_SetPixel(x - xpos, y + ypos);
OLED_SetPixel(x + xpos, y - ypos);
OLED_SetPixel(x - xpos, y - ypos);
if (d < 0)
{
d = d + b2 * ((xpos << 1) + 2) + a2 * (-(ypos << 1) + 3);
xpos += 1, ypos -= 1;
}
else
{
d = d + a2 * (-(ypos << 1) + 3);
ypos -= 1;
}
}
}
2.main.c
cpp复制代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
//OLED初始化
HAL_Delay(20);
OLED_Init();
// Clear_OLED();
// OLED_ShowFrams();
OLED_test();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
for(uint8_t i=0;i<8;i++){
Clear_OLED();
OLED_Setpixel(64,32);
OLED_ShowFrams();
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 8;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */