1.main.c
/* 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 "adc.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "lcd.h"
#include "stdio.h"
#include "string.h"
#include "i2c_hal.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
char text[30];
uint8_t key_state = 0; // 记录按键状态
uint8_t key_count = 0; // 消抖计数
uint16_t key_time = 0;
double IC_FREQUENCE = 0;
double IC_DUTY = 0;
uint32_t IC_HIGH_TIME = 0;
uint16_t FINISH = 1;//0结束
double adc1;
double adc2;
/* 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 */
/*DMA+USART接收*/
uint8_t uart_rx_flag = 0 ;
uint8_t rx_buf[100];
//HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
if(huart -> Instance == USART1){
uart_rx_flag = 1 ;
HAL_UARTEx_ReceiveToIdle_DMA(&huart1 , rx_buf , 100);
}
};
/*ADC*/
double get_adc(ADC_HandleTypeDef *pin){
HAL_ADC_Start(pin);
adc1 = HAL_ADC_GetValue(pin);
return adc1*3.3/4096;
};
/*ADC*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if(htim->Instance == TIM8){
//sprintf(text," TIM8 OK!");
//LCD_DisplayStringLine(Line1,(unsigned char*)text);
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){ // 按键按下
if(key_count < 5) key_count++; // 消抖计数
} else { // 按键松开
if(key_count >= 5 && key_state == 1){ // 确保之前是按下的状态
sprintf(text," PA0 Released");
LCD_DisplayStringLine(Line3,(unsigned char*)text);
}
key_count = 0; // 复位计数
key_state = 0; // 复位按键状态
}
if(key_count >= 5 && key_state == 0){ // 按键按下且未处理
key_state = 1; // 标记按键已按下
sprintf(text," PA0 PRESSED");
LCD_DisplayStringLine(Line2,(unsigned char*)text);
key_time =key_time+1;
}
if(key_time >= 2 ){
sprintf(text,"PA0 DOUBLE PRESSED");
LCD_DisplayStringLine(Line4,(unsigned char*)text);
key_time=0;
}
}
}
/*输入捕获频率*/
uint32_t IC_WHOLE_TIME = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
static uint8_t state = 0;
if(htim->Instance == TIM3){
switch(state){
case 0: /*1.捕获第一个上升沿*/
IC_HIGH_TIME = 0;
IC_WHOLE_TIME = 0;
__HAL_TIM_SET_COUNTER(&htim3,0);/*清空定时器*/
__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);
/*翻转检测下降*/
state = 1;
break;
case 1: /*2.捕获第一个下降沿*/
IC_HIGH_TIME = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);
state = 2;
break;
case 2:/*3.捕获第二个上升沿*/
IC_WHOLE_TIME = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
FINISH = 0;
state = 0;
break;
}
}
}
uint16_t PWM_ARR(double Frequency){
uint16_t PWM_ARR=(double)1000000 / Frequency -1 +0.5 ;
return PWM_ARR;
}
uint16_t PWM_CCR( uint16_t PWM_ARR,double ZKB){
uint16_t PWM_CCR = 0;
PWM_CCR = (double)(PWM_ARR+1)*ZKB/100 +0.5;
return PWM_CCR;
}
/* 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_DMA_Init();
MX_TIM8_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_USART1_UART_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
/*LED初始化*/
LED_DISP(0x00);
LED_DISP(0x6A); //0110 1010
/*LED初始化*/
/*LCD初始化*/
LCD_Init();
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
LCD_Clear(Black);
sprintf(text," LCD OK!%d%%",6);
LCD_DisplayStringLine(Line0,(unsigned char*)text);
/*LCD初始化*/
/*TIM初始化*/
HAL_TIM_Base_Start_IT(&htim8);//要初始化定时器中断,_IT不能少
/*TIM初始化*/
/*按键初始化(TIM8检测)*/
//实现了按下一次、按下两次、松手检测的三个功能
//注意,千万不能在定时器里面使用HAL_Delay();
/*按键初始化(TIM8检测)*/
/*输入捕获频率*/
HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
/*输入捕获频率*/
/*DMA接收中断*/
HAL_UARTEx_ReceiveToIdle_DMA(&huart1 , rx_buf , 100);
/*DMA接收中断*/
/*I2C + E2PROM*/
unsigned int a = 12345;
unsigned char data_high = (a >> 8) & 0xFF; // 取高8位
unsigned char data_low = a & 0xFF; // 取低8位
eeprom_write(1,data_high);
HAL_Delay(10);
eeprom_write(2,data_low);
HAL_Delay(10);
unsigned int eep_temp = (eeprom_read(1)<<8)+eeprom_read(2);
sprintf(text,"eeprom:%d ",eep_temp);
LCD_DisplayStringLine(Line1, (unsigned char *)text);
HAL_Delay(500);
/*I2C + E2PROM*/
/*PWM输出*/
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
uint16_t ARR = 0;
uint16_t CCR = 0;
ARR = PWM_ARR(1000);
__HAL_TIM_SET_AUTORELOAD(&htim1,ARR);
HAL_TIM_GenerateEvent(&htim1,TIM_EVENTSOURCE_UPDATE);
CCR =PWM_CCR(ARR,40);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,CCR);
/*PWM输出*/
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(FINISH == 0){
/*输入捕获*/
IC_FREQUENCE=(double)1000000 / (IC_WHOLE_TIME+1);
IC_DUTY = (double)IC_HIGH_TIME / (double)IC_WHOLE_TIME ;
sprintf(text,"IC_FRE:%.2f ",IC_FREQUENCE);
LCD_DisplayStringLine(Line5,(unsigned char*)text);
sprintf(text,"IC_DUTY:%.4f ",IC_DUTY);
LCD_DisplayStringLine(Line6,(unsigned char*)text);
/*输入捕获*/
/*ADC*/
sprintf(text,"V1:%.2f ",get_adc(&hadc1));
LCD_DisplayStringLine(Line7, (unsigned char *)text);
sprintf(text,"V2:%.2f ",get_adc(&hadc2));
LCD_DisplayStringLine(Line8, (unsigned char *)text);
/*ADC*/
/*USART发送*/
//uint8_t buf[100];
//int a=0;
//sprintf((char *)buf,"UART TEST=%d \r\n",a);
//HAL_UART_Transmit_DMA(&huart1,buf,strlen((char *)buf));
/*USART发送*/
FINISH = 1;
}
if(uart_rx_flag == 1 ){
uint8_t buf[100];
uart_rx_flag = 0;
sprintf((char *)buf,"UART TEST=%s \r\n",rx_buf);
HAL_UART_Transmit_DMA(&huart1,buf,strlen((char *)buf));
}
}
/* 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_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 10;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_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_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = 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 */
2.led.c
#include "led.h"
void LED_DISP(unsigned char dsLED){
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
3.i2c.c
/*EEPROM读取*/
unsigned char eeprom_read(unsigned char addr){
unsigned char dat;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
dat = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return dat;
}
/*EEPROM读取*/
/*EEPROM写入*/
void eeprom_write(unsigned char addr , unsigned char dat){
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
/*EEPROM写入*/