本人刚不久参加了蓝桥杯电子赛嵌入式组,想要记录一下之前的学习成果,如有不正确的地方,欢迎大家交流与评论
目录
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
试题题目
试题完整代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© 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;