/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 "icache.h"
#include "spi.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_ili9341_4line.h"
__ASM (".global __use_no_semihosting");
#include "adc.h" // 确保包含 ADC 的头文件
/* 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);
static void SystemPower_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 延时函数声明
void delay_us(uint32_t us);
void delay_ms(uint32_t ms);
void soft_pwm_led(GPIO_TypeDef* GPIOx, uint16_t pin, int duty);
typedef enum {
STATE_LED1_ON,
STATE_LED3_ON
} SystemState;
SystemState currentState = STATE_LED1_ON;
// 声明外部函数
extern void GuiShowString(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, char *str);
// 获取内部温度(单位:摄氏度)
float GetTemperature(void)
{
uint32_t adc_value;
float voltage;
float temperature;
// 启动ADC转换
HAL_ADC_Start(&hadc4);
// 等待转换完成
if (HAL_ADC_PollForConversion(&hadc4, 1000) == HAL_OK)
{
adc_value = HAL_ADC_GetValue(&hadc4);
}
else
{
return -999; // 错误标志
}
// 停止ADC(低功耗考虑,也可用连续模式避免频繁启停)
HAL_ADC_Stop(&hadc4);
// 计算参考电压下的电压值(假设VREF = 3.3V)
// ADC分辨率为12位(0~4095),VDDA=3.3V
voltage = ((float)adc_value) * (3.3f / 4095.0f); // 单位:V
/*
* 温度传感器公式(来自STM32参考手册):
* Temp(°C) = ((VSENSE - V25) / Avg_Slope) + 25
* 其中:
* V25 = 传感器在25°C时的输出电压(典型值约1.43V)
* Avg_Slope = 平均斜率(典型值约4.3mV/℃ = 0.0043V/℃)
*/
temperature = ((voltage - 1.43f) / 0.0043f) + 25.0f;
return temperature;
}
/* 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();
/* Configure the System Power */
SystemPower_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ICACHE_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
// 启用内部温度传感器(关键!)
__HAL_RCC_PWR_CLK_ENABLE(); // PWR 时钟使能
HAL_PWR_EnableBkUpAccess(); // 允许访问备份域
HAL_ADCEx_EnableInternalChannel(&hadc4); // 启动 ADC4 内部通道
uint8_t key1_last = 1;
uint8_t key3_last = 1;
uint8_t pending_action = 0; // 待执行动作:1=等待Key1释放, 2=等待Key3释放
ILI9341_Init(); //芯片初始化
ILI9341_Clear(RED ); //清除屏幕东西 显示原色
LCD_Picture(); //显示图片
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
uint8_t key1_curr = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9);
uint8_t key3_curr = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5);
uint8_t ir_blocked = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, ir_blocked ? GPIO_PIN_SET : GPIO_PIN_RESET);
// 按键消抖 & 触发待处理动使
if (key1_last == 1 && key1_curr == 0)
{
delay_ms(10);
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) == 0)
{
pending_action = 1; // 标记:需要处琿 Key1 按下
}
}
if (key3_last == 1 && key3_curr == 0)
{
delay_ms(10);
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5) == 0)
{
pending_action = 2; // 标记:需要处琿 Key3 按下
}
}
key1_last = key1_curr;
key3_last = key3_curr;
// === 新增:每500ms刷新一次温度显示 ===
static uint32_t last_temp_time = 0;
if (HAL_GetTick() - last_temp_time >= 500) // 每500ms更新一次
{
float temp = GetTemperature();
char temp_str[32];
if (temp > -100 && temp < 150) // 判断是否合理
{
sprintf(temp_str, "Temp: %.2f C", temp);
}
else
{
sprintf(temp_str, "Temp: ERR");
}
// 在屏幕指定位置显示温度(比如坐标(10,10),白色字体,黑色背景)
GuiShowString(10, 10, WHITE, BLACK, temp_str);
last_temp_time = HAL_GetTick();
}
delay_ms(10); // 主循环延时
// 状濁机处理
if (currentState == STATE_LED1_ON)
{
soft_pwm_led(GPIOC, GPIO_PIN_4, 100);
soft_pwm_led(GPIOC, GPIO_PIN_13, 0);
if (pending_action == 2) // Key3 按下
{
if (!ir_blocked) // 只有无障碍才执行
{
pending_action = 0; // 清除待处琿
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); // 启动马达
for (int level = 100; level >= 0; level--)
{
soft_pwm_led(GPIOC, GPIO_PIN_4, level);
soft_pwm_led(GPIOC, GPIO_PIN_13, 100 - level);
delay_ms(10);
}
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
currentState = STATE_LED3_ON;
}
}
}
else if (currentState == STATE_LED3_ON)
{
soft_pwm_led(GPIOC, GPIO_PIN_4, 0);
soft_pwm_led(GPIOC, GPIO_PIN_13, 100);
if (pending_action == 1) // Key1 按下
{
if (!ir_blocked)
{
pending_action = 0;
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
for (int level = 100; level >= 0; level--)
{
soft_pwm_led(GPIOC, GPIO_PIN_13, level);
soft_pwm_led(GPIOC, GPIO_PIN_4, 100 - level);
delay_ms(10);
}
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
currentState = STATE_LED1_ON;
}
}
}
delay_ms(10); // 主循环延旿
/* 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
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4;
RCC_OscInitStruct.PLL.PLLM = 3;
RCC_OscInitStruct.PLL.PLLN = 10;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 1;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
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_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_PCLK3;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief Power Configuration
* @retval None
*/
static void SystemPower_Config(void)
{
/*
* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral
*/
HAL_PWREx_DisableUCPDDeadBattery();
/* USER CODE BEGIN PWR */
/* USER CODE END PWR */
}
/* USER CODE BEGIN 4 */
/**
* @brief
*/
void delay_us(uint32_t us)
{
volatile uint32_t n = us * 11;
while (n > 0) { n--; }
}
/**
* @brief
*/
void delay_ms(uint32_t ms)
{
for (uint32_t i = 0; i < ms; i++)
{
delay_us(1000);
}
}
void soft_pwm_led(GPIO_TypeDef* GPIOx, uint16_t pin, int duty)
{
if (duty <= 0)
{
HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_RESET);
return;
}
if (duty >= 100)
{
HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_SET);
return;
}
const uint32_t period_us = 10000;
uint32_t on_time = (duty * period_us) / 100;
uint32_t off_time = period_us - on_time;
HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_SET);
delay_us(on_time);
HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_RESET);
delay_us(off_time);
}
/* 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 */
/**
******************************************************************************
* @file bsp_ili9341_4line.h
* @brief 2.8寸屏ILI9341驱动文件,采用4线SPI
*
******************************************************************************
*/
#ifndef __BSP_ILI9341_4LINE_H__
#define __BSP_ILI9341_4LINE_H__
//
#include "main.h"
#define LCD_DCX_Pin GPIO_PIN_4
#define LCD_DCX_GPIO_Port GPIOA
#define LCD_RST_Pin GPIO_PIN_8
#define LCD_RST_GPIO_Port GPIOA
//
typedef struct
{
uint16_t width; //ili9341 宽度
uint16_t height; //ili9341 高度
uint16_t id; //ili9341 ID
uint8_t wramcmd; //开始写gram指令
uint8_t setxcmd; //设置x坐标指令
uint8_t setycmd; //设置y坐标指令
}_ILI9341_dev;
//扫描方向定义
#define L2R_U2D 0 //从左到右,从上到下
#define L2R_D2U 1 //从左到右,从下到上
#define R2L_U2D 2 //从右到左,从上到下
#define R2L_D2U 3 //从右到左,从下到上
#define U2D_L2R 4 //从上到下,从左到右
#define U2D_R2L 5 //从上到下,从右到左
#define D2U_L2R 6 //从下到上,从左到右
#define D2U_R2L 7 //从下到上,从右到左
//屏幕显示方式
typedef enum
{
SCAN_Vertical= 0U, //竖屏
SCAN_Horizontal //横屏
} Screen_ShowDIR;
//画笔颜色
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
//GUI颜色
#define DARKBLUE 0X01CF //深蓝色
#define LIGHTBLUE 0X7D7C //浅蓝色
#define GRAYBLUE 0X5458 //灰蓝色
//以上三色为PANEL的颜色
#define LIGHTGREEN 0X841F //浅绿色
//#define LIGHTGRAY 0XEF5B //浅灰色(PANNEL)
#define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色
//
#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色)
//
/* 定义ATK-MD0280模块LCD尺寸 */
#define LCD_WIDTH 240
#define LCD_HEIGHT 320
void ILI9341_Init(void); //初始化
void ILI9341_Clear(uint16_t Color); //清屏
void ILI9341_SetCursor(uint16_t Xpos, uint16_t Ypos); //设置光标
void ILI9341_SetArea(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); //设置显示区域
//
void ILI9341_WR_REG(uint8_t);
void ILI9341_WR_DATA(uint8_t);
void ILI9341_WriteReg(uint8_t ili9341_Reg, uint8_t ili9341_RegValue);
//
void ILI9341_WriteRAM_Prepare(void);
void ILI9341_WriteRAM(uint16_t RGB_Code);
void ILI9341_Display_Dir(Screen_ShowDIR ShowDIR); //设置屏幕显示方向
//
void LCD_DrawRect(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, uint16_t _usColor); //绘制水平放置的矩形
void LCD_DrawCircle(uint16_t _usX, uint16_t _usY, uint16_t _usRadius, uint16_t _usColor); //绘制一个圆,笔宽为1个像素
void GuiShowString(uint16_t x0, uint16_t y0, uint16_t fc, uint16_t bc, char *s);
void LCD_Picture(void);
void Gui_DrawFont_GBK16(uint16_t x0, uint16_t y0, uint16_t fc, uint16_t bc, uint8_t *s);
//void LCD_Picture2(void);
static void set_page_address(uint16_t sp, uint16_t ep);
static void set_column_address(uint16_t sc, uint16_t ec);
void LCD_Picture_pic(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t *pic);
#endif /* __BSP_ILI9341_4LINE_H__ */
有很多错误检查一下