蓝桥杯嵌入式第十一届省赛——代码详解

本文档记录了一位参赛者在蓝桥杯电子赛嵌入式组的项目,涉及LED控制、按键扫描、LCD显示、ADC采样、PWM调制、UART通信和定时器配置等技术。作者详细展示了基础和复杂功能的代码片段,以及如何使用STM32进行硬件交互和实时处理。
摘要由CSDN通过智能技术生成

本人刚不久参加了蓝桥杯电子赛嵌入式组,想要记录一下之前的学习成果,如有不正确的地方,欢迎大家交流与评论

目录

试题题目

试题完整代码

代码之底层函数

        void LED_Set(u8 ucled)

        void KEY_Scan(void)

       void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

代码之基本功能函数

        void LCD_Proc(void)      

        void Key_Proc(void)

        void LED_Proc(void)

代码之复杂功能函数

        void PWM_Proc(void)

        void RX_Proc(void)

        void SysTick_Handler(void)


试题题目

试题完整代码

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lcd.h"
#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 */
#define DATA 0
#define PARA 1
u8 LCD_JM=DATA;
u8 LCD_Buffer[20];
double VR37=0;
double VP1=0.3;
u16 pa7_frq=1000;


u8 Key_Scan(void)
{
	u8 keynum=0;
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0)
		keynum=1;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
		keynum=2;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0)
		keynum=3;
	else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
		keynum=4;
	return keynum;
}
void LED_Set(u8 ucled)
{
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,ucled << 8,GPIO_PIN_RESET);
	
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
double Get_ADC(void)
{
	u16 value=0;
	HAL_ADC_Start(&hadc2);
	value=HAL_ADC_GetValue(&hadc2);
	return (value*3.3)/4096;
}
void LCD_Proc(void)
{
	VR37 = Get_ADC();
	if(LCD_JM==DATA)
	{
		sprintf((char*)LCD_Buffer,"        DATA  ");
		LCD_DisplayStringLine(Line3, (unsigned char*)LCD_Buffer);
		
		sprintf((char*)LCD_Buffer,"     VR37:%.2lfV  ",VR37);
		LCD_DisplayStringLine(Line4, (unsigned char*)LCD_Buffer);
		
		sprintf((char*)LCD_Buffer,"     PA7:%dHz ",pa7_frq);
		LCD_DisplayStringLine(Line5, (unsigned char*)LCD_Buffer);
	
	}
	else if(LCD_JM==PARA)
	{
		sprintf((char*)LCD_Buffer,"        PARA  ");
		LCD_DisplayStringLine(Line3, (unsigned char*)LCD_Buffer);
		
		sprintf((char*)LCD_Buffer,"      VP1:%.1lfV  ",VP1);
		LCD_DisplayStringLine(Line4, (unsigned char*)LCD_Buffer);
		
		
	}
}
u8 key_value,key_down,key_up,key_old;
uint32_t uwTick_key_point=0;
void Key_Proc(void)
{
	key_value = Key_Scan();
	key_down = key_value & (key_old ^key_value);
	key_up =~ key_value & (key_old ^key_value);
	key_old = key_value;
	
	if(key_down==1)
	{
		LCD_JM=(LCD_JM+1)%2;
		LCD_Clear(Black);
	}
	else if(key_down==2)
	{
		if(LCD_JM==PARA)
		{
			VP1+=0.3f;
			if(VP1 >3.4f)
				VP1 = 0.0f;
		}
	}
	else if(key_down==3)
	{
		if(LCD_JM==DATA)
		{
			pa7_frq+=1000;
			if(pa7_frq>10000)
				pa7_frq=1000;
			//两个必须一起用
			TIM3->ARR = 1000000/pa7_frq;
			TIM3->CCR2 = (1000000/pa7_frq)*0.1;
		}
	}
	else if(key_down==4)
	{
		
	}
}
u8 rev_buf[2];
u8 res_buf[6];
u8 rx_index=0;
u16 duty=0;
int fputc(int ch,FILE*f)
{
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,50);
	return ch;
}

void RX_Proc(void)
{
	if(rx_index==1)
	{
		if(res_buf[0]>='1' && res_buf[0]<='9')
		{
			duty=res_buf[0]-'0';
			TIM3->CCR2 = (1000000/pa7_frq)*(duty*10)/100.0;
		}
		else{
			printf("Error");
		}
		rx_index=0;
		memset(res_buf,0,sizeof(res_buf));
	}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	res_buf[rx_index++]=rev_buf[0];
	RX_Proc();
		HAL_UART_Receive_IT(&huart1,rev_buf,1);

}
u8 ucled=0;
uint32_t uwTick_LED3_Point=0;
void LED_Proc(void)
{
	if(LCD_JM==DATA)
	{
		ucled|=0x01;
	}
	else
	{
		ucled&=~0x01;
	}
	if(LCD_JM==PARA)
	{
		ucled|=0x02;
	}
	else
	{
		ucled&=~0x02;
	}
	if(VR37>VP1)  //LED3闪烁
	{
		if(uwTick - uwTick_LED3_Point>100)
		{
			uwTick_LED3_Point = uwTick;
			ucled^=0x04;
		}
	}
	else
	{
		ucled&=~0x04;
	}
	LED_Set(ucled);
}


/* 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_ADC2_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	LCD_Init();
	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
	HAL_UART_Receive_IT(&huart1,rev_buf,1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	 LCD_Clear(Black);
	 LCD_SetTextColor(White);
	 LCD_SetBackColor(Black);
	 
	// sprintf();
	LED_Set(0X05);
  while (1)
  {
		LCD_Proc();
		Key_Proc();
		LED_Proc();
		
    /* 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};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {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_DIV3;
  RCC_OscInitStruct.PLL.PLLN = 20;
  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();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_ADC12;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != 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 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

代码之底层函数

        void LED_Set(u8 ucled)      
void LED_Set(u8 ucled)
{
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,ucled << 8,GPIO_PIN_RESET);
	
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
        void KEY_Scan(void)
u8 Key_Scan(void)
{
	u8 keynum=0;
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0)
		keynum=1;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
		keynum=2;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0)
		keynum=3;
	else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
		keynum=4;
	return keynum;
}
          void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	res_buf[rx_index++]=rev_buf[0];
	RX_Proc();
		HAL_UART_Receive_IT(&huart1,rev_buf,1);

}
        double Get_ADC(void)
double Get_ADC(void)
{
	u16 value=0;
	HAL_ADC_Start(&hadc2);
	value=HAL_ADC_GetValue(&hadc2);
	return (value*3.3)/4096;
}
int fputc(int ch,FILE*f)

int fputc(int ch,FILE*f)
{
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,50);
	return ch;
}

 

代码之基本功能函数

        void LCD_Proc(void)      

        

void LCD_Proc(void)
{
	VR37 = Get_ADC();
	if(LCD_JM==DATA)
	{
		sprintf((char*)LCD_Buffer,"        DATA  ");
		LCD_DisplayStringLine(Line3, (unsigned char*)LCD_Buffer);
		
		sprintf((char*)LCD_Buffer,"     VR37:%.2lfV  ",VR37);
		LCD_DisplayStringLine(Line4, (unsigned char*)LCD_Buffer);
		
		sprintf((char*)LCD_Buffer,"     PA7:%dHz ",pa7_frq);
		LCD_DisplayStringLine(Line5, (unsigned char*)LCD_Buffer);
	
	}
	else if(LCD_JM==PARA)
	{
		sprintf((char*)LCD_Buffer,"        PARA  ");
		LCD_DisplayStringLine(Line3, (unsigned char*)LCD_Buffer);
		
		sprintf((char*)LCD_Buffer,"      VP1:%.1lfV  ",VP1);
		LCD_DisplayStringLine(Line4, (unsigned char*)LCD_Buffer);
		
		
	}
}
        void Key_Proc(void)
u8 key_value,key_down,key_up,key_old;
uint32_t uwTick_key_point=0;
void Key_Proc(void)
{
	key_value = Key_Scan();
	key_down = key_value & (key_old ^key_value);
	key_up =~ key_value & (key_old ^key_value);
	key_old = key_value;
	
	if(key_down==1)
	{
		LCD_JM=(LCD_JM+1)%2;
		LCD_Clear(Black);
	}
	else if(key_down==2)
	{
		if(LCD_JM==PARA)
		{
			VP1+=0.3f;
			if(VP1 >3.4f)
				VP1 = 0.0f;
		}
	}
	else if(key_down==3)
	{
		if(LCD_JM==DATA)
		{
			pa7_frq+=1000;
			if(pa7_frq>10000)
				pa7_frq=1000;
			//两个必须一起用
			TIM3->ARR = 1000000/pa7_frq;
			TIM3->CCR2 = (1000000/pa7_frq)*0.1;
		}
	}
	else if(key_down==4)
	{
		
	}
}
        void LED_Proc(void)
u8 ucled=0;
uint32_t uwTick_LED3_Point=0;
void LED_Proc(void)
{
	if(LCD_JM==DATA)
	{
		ucled|=0x01;
	}
	else
	{
		ucled&=~0x01;
	}
	if(LCD_JM==PARA)
	{
		ucled|=0x02;
	}
	else
	{
		ucled&=~0x02;
	}
	if(VR37>VP1)  //LED3闪烁
	{
		if(uwTick - uwTick_LED3_Point>100)
		{
			uwTick_LED3_Point = uwTick;
			ucled^=0x04;
		}
	}
	else
	{
		ucled&=~0x04;
	}
	LED_Set(ucled);
}

 

代码之复杂功能函数

        void RX_Proc(void)
void RX_Proc(void)
{
	if(rx_index==1)
	{
		if(res_buf[0]>='1' && res_buf[0]<='9')
		{
			duty=res_buf[0]-'0';
			TIM3->CCR2 = (1000000/pa7_frq)*(duty*10)/100.0;
		}
		else{
			printf("Error");
		}
		rx_index=0;
		memset(res_buf,0,sizeof(res_buf));
	}
}

总结:本次试题 使用了(LED,KEY,LCD基本模块,PWM,串口复杂模块)

注意,在使用PWM的时候首先第一步就是记得开中断,串口也是的,第一步记得开中断,然后对于PWM的占空比以及频率的设置,并没有调用函数,而是直接使用寄存器控制。

在本次代码中可能对于定时器,有些疑惑,因为我是直接用寄存器操作的,以下是关于定时器中输出PWM的一些相关的介绍

上面是对于我所使用的定时器中要设置参数的注释

PSC:预分频系数

ARR:自动重装载值

CRR:计数值

通常情况下,PSC=80-1,那么通过公式:f(频率) = 80MHz/(PSC-1)/(ARR-1)可知,如果PSC不变,

f = 80 000 000 /  80 / ARR;

f = 1000 000 / ARR;

ARR = 1000 000 / f;

duty(占空比) = CCR/ARR ;

CCR = ARR*duty;

假设我要设置占空比为20%,频率:2000Hz

那么我是不是只要将 pa7_frq = 2000hz,计算出ARR的值,将ARR*0.2,得出CCR的值,然后通过fu'zh设置到单片机中去,那么他就会输出频率2000hz,占空比20%的波形了

	TIM3->ARR = 1000000/pa7_frq;
	TIM3->CCR2 = (1000000/pa7_frq)*0.1;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值