第十七章:十三届省赛真题
摘要:本文介绍了基于STM32的两块开发板(A板和B板)的硬件功能与软件实现。A板通过I2C驱动OLED显示串口接收数据,并实现按键控制LED状态及LoRa数据传输;B板完成ADC电压采集、OLED显示及LoRa数据接收控制LED。关键代码包括:I2C通信的OLED驱动、串口中断处理、按键扫描消抖以及ADC数据采集转换。系统采用HAL库开发,实现了双板间的无线数据交互与状态同步,展示了STM32在
·
1.真题






2.STM32CuBEmx
A板:
1.I2C

3.按键和LED
4.USART

B板:
1.ADC
2.I2C
3.LORA
4.LED和按键
3.软件编程
A板:
1.OLED
void OLED_Write(uint8_t addr,uint8_t data)
{
uint8_t buf[2];
buf[0] = addr;
buf[1] = data;
HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf,2, 10);
}
void OLED_Src(void)
{
sprintf((char *)oled_str," RX:%c",rx_data);
OLED_ShowString(0, 0, oled_str, 16);
sprintf((char *)oled_str," NUM:%d ",uart_num);
OLED_ShowString(0, 2, oled_str, 16);
}
2.USART
// 串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart2) {
switch (rx_data) {
case '@':
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
uart_num++;
lora_tx[3] = HAL_GPIO_ReadPin(LD3_GPIO_Port,LD3_Pin);
break;
case '#':
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
uart_num++;
lora_tx[4] = HAL_GPIO_ReadPin(LD2_GPIO_Port,LD2_Pin);
break;
case '$':
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
uart_num++;
lora_tx[5] = HAL_GPIO_ReadPin(LD1_GPIO_Port,LD1_Pin);
break;
default:
if (HAL_UART_GetState(&huart2) == HAL_UART_STATE_READY) {
HAL_UART_Transmit(&huart2, (uint8_t *)error_msg, sizeof(error_msg)-1, 100);
}
break;
}
// 重新启动中断接收
HAL_UART_Receive_IT(&huart2, (uint8_t *)&rx_data, 1);
}
}
3.按键
#include "key.h"
uint8_t Key_Scan(void)
{
uint8_t key_val = 0;
if(HAL_GPIO_ReadPin(key1_GPIO_Port,key1_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(key1_GPIO_Port,key1_Pin) == GPIO_PIN_RESET)
{
key_val = 1;
while(HAL_GPIO_ReadPin(key1_GPIO_Port,key1_Pin) == GPIO_PIN_RESET);
}
}
if(HAL_GPIO_ReadPin(Key2_GPIO_Port,Key2_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(Key2_GPIO_Port,Key2_Pin) == GPIO_PIN_RESET)
{
key_val = 2;
while(HAL_GPIO_ReadPin(Key2_GPIO_Port,Key2_Pin) == GPIO_PIN_RESET);
}
}
return key_val;
}
void Key_src(void)
{
if(uwTick - key_tick < 100)
return;
else
key_tick = uwTick;
uint8_t key_val,key_down,key_up,key_old;
key_val = Key_Scan();
key_down = key_val&(key_val^key_old);
key_up = ~key_val&(key_val^key_old);
key_old = key_val;
if(key_val == 1)
{
lora_tx[2]++;
LORA_Tx(lora_tx,6);
}
}
main.c
#include "main.h"
#include "i2c.h"
#include "subghz.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "oled.h"
#include "lora.h"
#include "key.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
__IO uint32_t key_tick = 0;
uint8_t oled_str[30];
volatile char rx_data; // 用于中断接收
char error_msg[] = "error\r\n";
uint32_t uart_num = 0;
uint8_t lora_tx[6] = {0x01,0x02,0x00,0x01,0x01,0x01};
/* 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 */
int fputc(int ch,FILE *p)
{
HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,0xffff);
return ch;
}
void Key_src(void)
{
if(uwTick - key_tick < 100)
return;
else
key_tick = uwTick;
uint8_t key_val,key_down,key_up,key_old;
key_val = Key_Scan();
key_down = key_val&(key_val^key_old);
key_up = ~key_val&(key_val^key_old);
key_old = key_val;
if(key_val == 1)
{
lora_tx[2]++;
LORA_Tx(lora_tx,6);
}
}
void OLED_Src(void)
{
sprintf((char *)oled_str," RX:%c",rx_data);
OLED_ShowString(0, 0, oled_str, 16);
sprintf((char *)oled_str," NUM:%d ",uart_num);
OLED_ShowString(0, 2, oled_str, 16);
}
/* 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 */
MX_USART2_UART_Init();
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_SUBGHZ_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
OLED_Init();
LORA_Init();
HAL_UART_Receive_IT(&huart2,(uint8_t *)&rx_data, 1);
printf("this is 16 HAL A init\r\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
Key_src();
OLED_Src();
/* 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
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEDiv = RCC_HSE_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
RCC_OscInitStruct.PLL.PLLN = 6;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|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;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
// 串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart2) {
switch (rx_data) {
case '@':
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
uart_num++;
lora_tx[3] = HAL_GPIO_ReadPin(LD3_GPIO_Port,LD3_Pin);
break;
case '#':
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
uart_num++;
lora_tx[4] = HAL_GPIO_ReadPin(LD2_GPIO_Port,LD2_Pin);
break;
case '$':
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
uart_num++;
lora_tx[5] = HAL_GPIO_ReadPin(LD1_GPIO_Port,LD1_Pin);
break;
default:
if (HAL_UART_GetState(&huart2) == HAL_UART_STATE_READY) {
HAL_UART_Transmit(&huart2, (uint8_t *)error_msg, sizeof(error_msg)-1, 100);
}
break;
}
// 重新启动中断接收
HAL_UART_Receive_IT(&huart2, (uint8_t *)&rx_data, 1);
}
}
B板:
1.ADC
void ADC_Src(void)
{
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc,100);
adc_val1 = HAL_ADC_GetValue(&hadc);
HAL_ADC_PollForConversion(&hadc,100);
adc_val2 = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop(&hadc);
adc_volt1 = (3.3f * adc_val1)/4095.f;
adc_volt2 = (3.3f * adc_val2)/4095.f;
}
2.OLED
void OLED_Write(uint8_t addr,uint8_t data)
{
uint8_t buf[2];
buf[0] = addr;
buf[1] = data;
HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf,2, 10);
}
void OLED_Src(void)
{
if(key_flag == 1)
{
sprintf((char *)oled_str," RP1:%3.1f",adc_volt1);
OLED_ShowString(0, 0, oled_str, 16);
sprintf((char *)oled_str," RP2:%3.1f",adc_volt2);
OLED_ShowString(0, 2, oled_str, 16);
}
if(key_flag == 2)
{
sprintf((char *)oled_str," NUM:%d",state_num);
OLED_ShowString(0, 0, oled_str, 16);
if((ld2_state == 0) && (ld3_state == 0))
{
sprintf((char *)oled_str," STA:ON");
OLED_ShowString(0, 2, oled_str, 16);
}
else{
sprintf((char *)oled_str," STA:OFF");
OLED_ShowString(0, 2, oled_str, 16);
}
}
}
3.LORA
LORA_Rx(lora_rx,6);
if((lora_rx[0] == 0x01) && (lora_rx[1] == 0x02))
{
state_num = lora_rx[2];
ld1_state = lora_rx[5];
ld2_state = lora_rx[4];
ld3_state = lora_rx[3];
if(!ld1_state)
HAL_GPIO_WritePin(LD1_GPIO_Port,LD1_Pin,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LD1_GPIO_Port,LD1_Pin,GPIO_PIN_SET);
if(!ld2_state)
HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_SET);
if(!ld3_state)
HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin,GPIO_PIN_SET);
}
4.按键
#include "key.h"
uint8_t Key_Scan(void)
{
uint8_t key_val = 0;
if(HAL_GPIO_ReadPin(Key1_GPIO_Port,Key1_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(Key1_GPIO_Port,Key1_Pin) == GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(Key1_GPIO_Port,Key1_Pin) == GPIO_PIN_RESET);
key_val = 1;
}
}
if(HAL_GPIO_ReadPin(Key2_GPIO_Port,Key2_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(Key2_GPIO_Port,Key2_Pin) == GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(Key2_GPIO_Port,Key2_Pin) == GPIO_PIN_RESET);
key_val = 2;
}
}
return key_val;
}
void Key_Src(void)
{
if(uwTick - key_tick < 200)
return;
else
key_tick = uwTick;
key_val = Key_Scan();
key_down = key_val & (key_val ^ key_old);
key_up = ~key_val & (key_val ^ key_old);
key_old = key_val;
if(key_val == 1)
{
OLED_Clear();
if(key_flag == 1)
{
key_flag = 2;
}
else
{
key_flag = 1;
}
}
}
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)