蓝桥杯物联网竞赛_STM32L071KBU6_第十五届蓝桥杯物联网竞赛国赛代码解析

发布于:2024-06-06 ⋅ 阅读:(118) ⋅ 点赞:(0)

前言:

这届国赛是目前为止最难一届,我赛后完完整整又做了一遍,花了我两天大概12小时,这个难度完全可以当一个stm32的期末设计,下面将对本届的题结合对应代码做重点解析

对应试题在这里: 第十五届蓝桥杯物联网试题(国赛)

1、配置及代码:

(1) A板:

[1] CUBMX配置:

[2] keil5代码:

main.c:

#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "spi.h"
#include "tim.h"
#include "usart.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 */
#include "Function.h"
#include "oled.h"
#include "lora.h"
/* 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_I2C3_Init();
  MX_TIM3_Init();
  MX_USART2_UART_Init();
  MX_SPI1_Init();
  MX_TIM7_Init();
  /* USER CODE BEGIN 2 */
  Function_OledInit(50);
	LORA_Init();
	HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_3);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		Function_MyMain();
  }
  /* USER CODE END 3 */
}

Function.c:

#include "Function.h"
#include "main.h"
#include "oled.h"
#include "i2c.h"
#include "spi.h"
#include "lora.h"
#include <stdarg.h>
#include <stdio.h>
#include "usart.h"
#include "tim.h"
#include <string.h>

unsigned char URXMSG[20];
unsigned char UTXMSG[20];
unsigned char LTXMSG[20];
unsigned char LRXMSG[20];
int BEIGNNUMBER = 0;
int ENDNUMBER = 0;
unsigned char STATETIM = 0;
unsigned char ARRAY1[20];
int PLUSEVALUE = 0;
uint16_t COUNTNUMBER = 0;
unsigned char MEMORDER[20] = {'N', 'F', ' '};


void OLED_Write(unsigned char type, unsigned char data){
	unsigned char WriteData[2];
	WriteData[0] = type;
	WriteData[1] = data;
	HAL_I2C_Master_Transmit(&hi2c3, 0x78, WriteData, 2, 0xff);
}

void Function_OledInit(unsigned char ms){
	HAL_GPIO_WritePin(OLED_Power_GPIO_Port, OLED_Power_Pin, GPIO_PIN_RESET);
  HAL_Delay(ms);
	OLED_Init();
}


unsigned char SPI_WriteRead(unsigned char address, unsigned char data){
	unsigned char TxData[2], RxData[2];
	TxData[0] = address;
	TxData[1] = data;
	HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxData, RxData, sizeof(TxData), 0xff);
	HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
	return RxData[1];
}

void Function_ArrayClean(unsigned char* array, uint16_t len){
  for(unsigned char i = 0; i < len; i ++) array[i] = '\0';
}


void myprintf(unsigned char address, const char* format, ...) {
    char ARRAY[40];
	
	  // 使用va_list和va_start来处理可变参数
    va_list args;
    va_start(args, format);

    // 使用vsprintf将可变参数列表格式化的字符串存储到ARRAY中
    vsprintf(ARRAY, format, args);
    
    // 清理可变参数列表
    va_end(args);

    // 假设OLED_ShowString函数可以在OLED屏幕上显示字符串
    OLED_ShowString(address, (unsigned char*)ARRAY);
}

void Function_UartTxOk(){
  HAL_UART_Transmit(&huart2, (unsigned char* )"OK ", 5, 0xff);
}

void Function_UartTxError(){
  HAL_UART_Transmit(&huart2, (unsigned char* )"ERROR ", 8, 0xff);
}

void Function_HandleURxMsg(){
  if(URXMSG[0] == '$' && URXMSG[1] == '\0'){
	  LORA_Tx((unsigned char* )"$", 1);
	}
	
	if(URXMSG[0] == '?' && URXMSG[1] == '\0'){
	  LORA_Tx((unsigned char* )"?", 1);
	}
	
	if(URXMSG[0] == '@' && URXMSG[1] == '\0'){
		
		sprintf((char* )LTXMSG, "%d", PLUSEVALUE);
    LORA_Tx(LTXMSG, 10);	
    Function_ArrayClean(LTXMSG, sizeof(LTXMSG));	
		
	}
	
	if(URXMSG[0] == 'F'){
	 
	 if(strncmp((char* )URXMSG, "FS1:", 4) == 0 || strncmp((char* )URXMSG, "FS2:", 4) == 0)	LORA_Tx(URXMSG, 20);  // 判断是不是正确的
	 else Function_UartTxError(); 
	}
	
	unsigned char temp = URXMSG[0];
	if(temp == '$' && URXMSG[1] == '\0'){  // 切换和同步命令需要返还OK
	  Function_UartTxOk();  // 返还OK
		Function_ArrayClean(URXMSG, sizeof(URXMSG));  // 清理
	}		
 	
	if(((temp == '?' || temp == '@') && URXMSG[1] == '\0') || temp == 'F'){  // 参数和查询指令交给B端处理后统一返还
	  Function_ArrayClean(URXMSG, sizeof(URXMSG));
	}		 
 
	if(URXMSG[0] != '\0') {  // 接收了其他垃圾消息
		Function_ArrayClean(URXMSG, sizeof(URXMSG));
		Function_UartTxError();  // 返还错误
	}
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){  // 10ms
  	if(COUNTNUMBER < 300) COUNTNUMBER ++;
	  else{
		  COUNTNUMBER = 0;
			HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET);  // 随手关灯
		}
}

void Function_LoRxMsg(){  // B端处理后的结果
  LORA_Rx(LRXMSG);
	if(LRXMSG[0] != '\0'){

	  if(LRXMSG[0] == '0') Function_UartTxError();  // A端接收的数据不正确
		else if(LRXMSG[0] == 'R' || LRXMSG[0] == 'N'){  // 接收到LORB传递的数据
			HAL_UART_Transmit(&huart2, LRXMSG, strlen((char* )LRXMSG), 0xff);
			HAL_TIM_Base_Start_IT(&htim7);  // 开启定时器
			HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET);  // 开灯
		}
		else if(LRXMSG[0] == '1') Function_UartTxOk();  // A端接收的数据正确
		Function_ArrayClean(LRXMSG, sizeof(LRXMSG));  // 清除接收的数据
	}
	
}
 

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
	//OLED_ShowString(0, "ok");
	if(STATETIM == 0){
		STATETIM ++;
		BEIGNNUMBER = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_3);
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_3, TIM_ICPOLARITY_FALLING);
	}else if(STATETIM == 1){
		STATETIM ++;
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_3, TIM_ICPOLARITY_RISING);
	}else if(STATETIM == 2){
		STATETIM ++;
		ENDNUMBER = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_3);
	}
}

void Function_UartRxMsg(){
  HAL_UARTEx_ReceiveToIdle_IT(&huart2, URXMSG, 50);
	if(URXMSG[0] != '\0'){
	  HAL_Delay(10);  // 让cpu等待DMA把数据接收完
		memcpy(MEMORDER, URXMSG, 20);
		 
		Function_HandleURxMsg();
	}
}

void Function_PluseShow(){
  if(STATETIM == 3){
		PLUSEVALUE = (int)(1000000 * 1.0 / (ENDNUMBER - BEIGNNUMBER));
		myprintf(2, "     %dHZ      ",  PLUSEVALUE);
		//myprintf(0, "   %d  ", ENDNUMBER - BEIGNNUMBER); 
		//myprintf(2, "   %.1f   ", (ENDNUMBER - BEIGNNUMBER) / 10.0);
		STATETIM = 0;
	  HAL_Delay(200);
	}
}

void Function_MyMain(){
  Function_UartRxMsg();
  //myprintf(0, URXMSG);
  myprintf(0, "     %s       ", MEMORDER);  // 显示最近一次接收到的数据
  Function_LoRxMsg();
  Function_PluseShow();
	//Function_HandleURxMsg();
}

Function.h:

#ifndef __FUNCTION_H__
#define __FUNCTION_H__
#include "main.h"

void OLED_Write(unsigned char type, unsigned char data);

void Function_OledInit(unsigned char ms);

void Function_MyMain();

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

#endif

(2) B板:

[1] CUBMX配置:

[2] keil5代码:

main.c:

#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "spi.h"
#include "tim.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 */
#include "Function.h"
#include "oled.h"
#include "lora.h"
/* 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_I2C3_Init();
  MX_SPI1_Init();
  MX_TIM2_Init();
  MX_TIM7_Init();
  MX_ADC_Init();
  /* USER CODE BEGIN 2 */
  Function_OledInit(50);
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);  // 开启方波 1kHZ
	HAL_TIM_Base_Start_IT(&htim7);
	LORA_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		Function_MyMain();
  }
  /* USER CODE END 3 */
}

Function.c

#include "Function.h"
#include "main.h"
#include "i2c.h"
#include "oled.h"
#include <stdio.h>
#include "tim.h"
#include "adc.h"
#include <stdarg.h>
#include "spi.h"
#include "lora.h"
#include <string.h>
#include <stdlib.h>

float FS1 = 6.0;
float FS2 = 6.0;
float F1VL = 0;
float F2VL = 0;
unsigned char STATEADC = 0;  // ADC状态
unsigned char OLEDSHOW = 0;  // OLED显示
uint16_t COUNTNUM = 0;
unsigned char LEDSTATE = 0;
float DERTF1F2 = 0;  // 获取FS1与FS2差值 / 0.2
unsigned char INDEX = 7;  // 算一下AA中第一个A的具体位置
unsigned char MEMWINNER[20] = {'N', 'F', ' '};
uint16_t ADCRUNNUM = 0;
unsigned char RUNSHOWARR[20];
unsigned char LORXMSG[20];
int NEWPWM = 0;
int CLK = 32000000;
int MAINDRT = 32000000;
int INDEXX = 0;
int INDEXY = 0;  // 获取要调的参数


void OLED_Write(unsigned char type, unsigned char data){
	unsigned char WriteData[2];
	WriteData[0] = type;
	WriteData[1] = data;
	HAL_I2C_Master_Transmit(&hi2c3, 0x78, WriteData, 2, 0xff);
}

void Function_OledInit(unsigned char ms){
	HAL_GPIO_WritePin(OLED_Power_GPIO_Port, OLED_Power_Pin, GPIO_PIN_RESET);
  HAL_Delay(ms);
	OLED_Init();
}

unsigned char SPI_WriteRead(unsigned char address, unsigned char data){
	unsigned char TxData[2], RxData[2];
	TxData[0] = address;
	TxData[1] = data;
	HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1, TxData, RxData, sizeof(TxData), 0xff);
	HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
	return RxData[1];
}


void myprintf(unsigned char address, const char* format, ...) {
    char ARRAY[40];
	
	  // 使用va_list和va_start来处理可变参数
    va_list args;
    va_start(args, format);

    // 使用vsprintf将可变参数列表格式化的字符串存储到ARRAY中
    vsprintf(ARRAY, format, args);
    
    // 清理可变参数列表
    va_end(args);

    // 假设OLED_ShowString函数可以在OLED屏幕上显示字符串
    OLED_ShowString(address, (unsigned char*)ARRAY);
}

void Function_ArrayClean(unsigned char* array, uint16_t len){
  for(unsigned char i = 0; i < len; i ++) array[i] = '\0';
}

void Function_GetAdc(){
  uint16_t AdcData[2];
	float AdcValue[2];
	for(unsigned char i = 0; i < 2; i ++){
	  HAL_ADC_Start(&hadc);
		HAL_ADC_PollForConversion(&hadc, 0xff);
		AdcData[i] = HAL_ADC_GetValue(&hadc);
		AdcValue[i] = AdcData[i] * 3.30f / 4095;
	}
	HAL_ADC_Stop(&hadc);
	F1VL = FS1 / 3.0 * AdcValue[1] - 0.1 * FS1;
	F2VL = FS2 / 3.0 * AdcValue[0] - 0.1 * FS1;
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){  // 按键
  //OLED_ShowString(0, "we");
	OLEDSHOW = (OLEDSHOW + 1) % 3;
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){  // 10ms中断一次
	
	/* 为run状态服务 */
	if(STATEADC == 2){   
		
		
		if(ADCRUNNUM % 20 == 0) Function_GetAdc();  // 按题意理解采集器在run状态才会采集且采集间隔为0.2s
    ADCRUNNUM ++;
		
		
		// 更新A的坐标
	  if(F1VL >= F2VL){
			
			DERTF1F2 = (int)((F1VL - F2VL) / 0.2);  // 记得要强转int一下,注意(int)的优先级
			if(DERTF1F2 >= 7) INDEX = 0;  // 更新A的坐标
			else INDEX = 7 - DERTF1F2;
			
		}else{
			
		  DERTF1F2 = (int)((F2VL - F1VL) / 0.2);
			if(DERTF1F2 + 7 >= 14) INDEX = 14;
			else INDEX = 7 + DERTF1F2;
			
		}
		
		if(INDEX == 0 || INDEX == 14){  // 判断AA是否在左右两边
			
			if(COUNTNUM < 500) COUNTNUM ++;
			else{  // 坚持5s,记录获胜者
				
				COUNTNUM = 0;
				ADCRUNNUM = 0;
				STATEADC = 0;
				
				if(INDEX == 0) sprintf((char* )MEMWINNER, "RP1:%.1f    ", F1VL); 
				else sprintf((char* )MEMWINNER, "RP2:%.1f ", F2VL);
				
				LEDSTATE = 1;  // 有人获胜开启LD5
				
			}
			
		}else COUNTNUM = 0;  // AA没在边缘不记时
	
	}
	
	
	
	/* 为LED闪烁服务 */
	if(LEDSTATE == 1){    
	  
		if(COUNTNUM < 500){
			if(COUNTNUM % 10 == 0) HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);  // 0.1s也就是100ms,整10倍数闪烁一次即可
			COUNTNUM ++;
		}else{
			
			COUNTNUM = 0;
			LEDSTATE = 0;
			
			HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET);  // 将LD5灯关掉
			
		}
		
	}
	
}

void Function_RunStateShow(){
  for(unsigned char i = 0; i < 16; i ++) RUNSHOWARR[i] = '#';   
	RUNSHOWARR[INDEX] = 'A';
	RUNSHOWARR[INDEX + 1] = 'A';  // 填充 
	myprintf(0, "      RUN       ");
	myprintf(2, (char* )RUNSHOWARR);
}

void Function_OledShow(){
  if(OLEDSHOW == 0){
		if(STATEADC == 0){
			myprintf(0, "      Idle      ");
			myprintf(2, "#######AA#######");
		}else if(STATEADC == 1){
			myprintf(0, "      Ready     ");
			myprintf(2, "#######AA#######");
		}else if(STATEADC == 2){
			Function_RunStateShow();
		}
	}else if(OLEDSHOW == 1){
		myprintf(0, "    F1:%.1fKN    ", F1VL);
    myprintf(2, "    F2:%.1fKN    ", F2VL);		
	}else if(OLEDSHOW == 2){
		myprintf(0, "    FS1:%.1fKN   ", FS1);
		myprintf(2, "    FS2:%.1fKN   ", FS2);
		//myprintf(2, "      kkkk      ");
	}
}

void Function_PwmChange(){  // 传过来的PWM不一定能整除,选择最接近的PWM
	NEWPWM = (int)strtof((char* )LORXMSG, NULL);  // 获取要配置的新的PWM
	MAINDRT = CLK;
	for(int i = 1; i <= 65535; i ++){
	  for(int j = 1; j <= 65535; j ++){
		  
			if(i * j * NEWPWM - CLK > MAINDRT) break;  // 差值太大说明j太大
			int temp = abs(i * j * NEWPWM - CLK); 
			
			if(temp <= MAINDRT){  // 如果差值很小
				MAINDRT = temp;
				INDEXX = i;
				INDEXY = j;
			}

		}
		if(MAINDRT == 0) break;  // 能整除就没必要继续了
  }
	__HAL_TIM_SET_PRESCALER(&htim2, INDEXX - 1);
	__HAL_TIM_SET_AUTORELOAD(&htim2, INDEXY - 1);  // 修改预分频与自动重装载
	
	//myprintf(0, "MIN: %d    ", MAINDRT); 
	//myprintf(2, "NPM: %d    ",CLK / INDEXX / INDEXY);
	//myprintf(2, "%d %d", INDEXX, INDEXY);
}

void Function_LoRxMsg(){
  LORA_Rx(LORXMSG);
	//myprintf(0, LORXMSG);
	if(LORXMSG[0] == '$'){  // 切换模式
		STATEADC = (STATEADC + 1) % 3;
		//myprintf(0, "%d", STATEADC);
	}
	
	if(LORXMSG[0] == '?'){  // 发送上一次的胜利者
	  LORA_Tx(MEMWINNER, sizeof(MEMWINNER));
	}
	
	if(LORXMSG[0] >= '0' && LORXMSG[0] <= '9'){  // 传回了脉冲信号
		//myprintf(2, "%d", STATEADC);
		if(STATEADC == 0){
			Function_PwmChange();
			LORA_Tx((unsigned char* )"1", 1);
		}
		else LORA_Tx((unsigned char* )"0", 1);  // 传回报错信息 
	}
	
	if(LORXMSG[0] == 'F'){  // 修改命令
	  
		unsigned char memfs[20];
		memcpy(memfs, LORXMSG + 4, 10);
		char* q = NULL;
		float temp = strtof((char* )memfs, &q);
		if(*q != '\0') LORA_Tx((unsigned char* )"0", 1);  // 错误数据
		else if(LORXMSG[2] == '1'){
			FS1 = temp;
			LORA_Tx((unsigned char* )"1", 1);
		}else if(LORXMSG[2] == '2'){
		  FS2 = temp;
			LORA_Tx((unsigned char* )"1", 1);  // 返回成功信息
		}
		//myprintf(0, "temp: %.1f", temp);
		//myprintf(2, "F1: %.1f F2: %.1f", FS1, FS2);
	}
	
	
	
	if(LORXMSG[0] != '\0') Function_ArrayClean(LORXMSG, sizeof(LORXMSG));
}

void Function_K1K2Ctrl(){
  if(STATEADC == 0){  // 空闲
		HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(K2_GPIO_Port, K2_Pin, GPIO_PIN_RESET);
	}else if(STATEADC == 1){
		HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(K2_GPIO_Port, K2_Pin, GPIO_PIN_RESET);
	}else if(STATEADC == 2){
		HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(K2_GPIO_Port, K2_Pin, GPIO_PIN_SET);
	}
}	

void Function_MyMain(){
	Function_LoRxMsg();
	Function_K1K2Ctrl();
	Function_OledShow();
	//myprintf(0, "%d,%c,%s,%.1fH", 20, 'a', "hello", 11.1);
	 
}

Function.h:

#ifndef __FUNCTION_H__
#define __FUNCTION_H__
#include "main.h"

void OLED_Write(unsigned char type, unsigned char data);

void Function_OledInit(unsigned char ms);

void Function_MyMain();

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

void myprintf(unsigned char address, const char* format, ...);

unsigned char SPI_WriteRead(unsigned char address, unsigned char data);

#endif

2、代码解析:


网站公告

今日签到

点亮在社区的每一天
去签到