第九届蓝桥杯嵌入式国赛(STM32G4与HAL库实现)

Posted ORI2333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第九届蓝桥杯嵌入式国赛(STM32G4与HAL库实现)相关的知识,希望对你有一定的参考价值。

前言

本程序基于STM32G431RB开发,使用工具为STM32CubeMX + Keil MDK 5 + HAL库。

题目要求

基本要求

完成“电子秤”功能。

硬件框图

在这里插入图片描述

功能描述

基本功能

  1. 通过资源扩展板电位器RP5模拟称重传感器输出信号,STM32采集此电压信号,并计算货物重量。电子秤称重范围0-10kg。
  2. 通过按键选择不同货物、计费及货物单价参数设置等功能。
  3. 通过LCD显示所称货物重量和货物价格等信息。
  4. 设备基本工作流程:选择货物(按键操作)——称重——计费(按键操作)——更新显示及串口输出。

按键功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

显示功能

在这里插入图片描述
在这里插入图片描述

存储功能

在这里插入图片描述

称重功能

在这里插入图片描述

LED指示灯功能

  1. 称重计费状态下,LD1以0.8秒为间隔亮灭
  2. 单价设置状态下,LD1以0.4秒为间隔亮灭

串口功能

  1. 使用竞赛板上的USART2(USB转串口)完成串口输出功能。
  2. 串口通讯波特率:9600bps

资源扩展板跳线配置参考

在这里插入图片描述

代码实现

为了方便提交,或者说不容易遗漏,本工程将绝大部分实现代码写在main.c文件中.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention			: 此为第九届蓝桥杯嵌入式设计大赛程序设计题
  *
  * <h2><center>&copy; Copyright (c) 2021 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"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "i2c - hal.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define BTN_BUFF_LEN 20
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc2;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */
char TextBuff[30];
uint32_t adc_value = 0;
uint32_t key_value = 0;
u16 btn_buff[BTN_BUFF_LEN];
double Weight_Value = 0;
double Goodsprice1 = 0;
double Goodsprice2 = 0;
double Goodsprice3 = 0;
uint8_t SettingTimes = 0;
uint8_t Key_1_Flag = 0;
uint8_t Key_4_Flag = 0;
uint8_t Key_567_Flag = 1;
uint8_t Key_8_Flag = 0;

uint8_t Set_Flag = 0;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
void LCD_cls(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/******************获取ADC值**********************/
uint16_t Get_ADC(uint32_t ch)
{
	ADC_ChannelConfTypeDef sConfig = {0};

	sConfig.Channel = ch;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
	
	HAL_ADC_Start(&hadc2);
	
	HAL_ADC_PollForConversion(&hadc2,10);
	
	return (uint16_t)HAL_ADC_GetValue(&hadc2);
	
}
/*************************************************/

/****************均值滤波**************************/

u16 Get_Adc_Average(u32 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_ADC(ch);
		HAL_Delay(5);
	}
	return temp_val/times;
} 
/***************************************************/

/*********************ADC按键***********************/
u8 key_read()
{
	u16 ADC_temp = 4500;
	 ADC_temp = Get_Adc_Average(ADC_CHANNEL_13,1);
	
	if(ADC_temp<100)
	{
		return 1;
	}
	else if(ADC_temp<400)
	{
		return 2;
	}
	else if(ADC_temp<700)
	{
		return 3;
	}
	else if(ADC_temp<1100)
	{
		return 4;
	}
	else if(ADC_temp<1500)
	{
		return 5;
	}
	else if(ADC_temp<2000)
	{
		return 6;
	}
	else if(ADC_temp<2500)
	{
		return 7;
	}
	else if(ADC_temp<3500)
	{
		return 8;
	}
	else 
		return 0;
}

/***************************************************/

/*******************按键扫描************************/

void Key_Scan()
{
	
	static u8 key_up=1;     //按键松开标志
	if(key_up && key_value != 0){
		key_up = 0;
		if(key_value == 1){
			Key_1_Flag++;
			
			if(Key_1_Flag > 2) 	Key_1_Flag = 0;
		}
		if(key_value == 2){
			if(Key_4_Flag == 1){
				Goodsprice1 += 0.01;
			}
			if(Key_4_Flag == 2){
				Goodsprice2 += 0.01;
			}
			if(Key_4_Flag == 3){
				Goodsprice3 += 0.01;
			}
			
			if(Goodsprice1 > 10) Goodsprice1 = 10;
			if(Goodsprice2 > 10) Goodsprice2 = 10;
			if(Goodsprice3 > 10) Goodsprice3 = 10;
			
			Set_Flag = 1;
		}
		
			if(key_value == 3){
			if(Key_4_Flag == 1){
				Goodsprice1 -= 0.01;
			}
			if(Key_4_Flag == 2){
				Goodsprice2 -= 0.01;
			}
			if(Key_4_Flag == 3){
				Goodsprice3 -= 0.01;
			}
			
			if(Goodsprice1 < 0) Goodsprice1 = 0;
			if(Goodsprice2 < 0) Goodsprice2 = 0;
			if(Goodsprice3 < 0) Goodsprice3 = 0;
			
			Set_Flag = 1;

		}
		
		
		if(key_value == 4){			
			Key_4_Flag++;
			if(Key_4_Flag > 3){
				Key_4_Flag = 0;
			}
			
		}
		
		if(key_value == 5){
			Key_567_Flag = 1;
		}
		
		if(key_value == 6){
			Key_567_Flag = 2;
		}
		
		if(key_value == 7){
			Key_567_Flag = 3;
		}
		
		if(key_value == 8){
			Key_8_Flag = 1;
		}
		
	}
	else if(key_value == 0){
		key_up = 1;
		Key_8_Flag = 0;
	}
	
}
/*******************************************************/


/************************设置界面************************/


void SettingDisplay()
{
	LCD_SetBackColor(Blue);
	LCD_DisplayStringLine(Line0,(uint8_t *)" parameter settings  ");
	LCD_DisplayStringLine(Line1,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line5,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line6,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line7,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line8,(uint8_t *)"                     ");
	
	
	sprintf(TextBuff,"PriceGoods1:%.2fY/kg", Goodsprice1);
	if(Key_4_Flag == 1){
			LCD_SetBackColor(Green);
			LCD_DisplayStringLine(Line2,(uint8_t *)TextBuff);
			LCD_SetBackColor(Blue);
	}
	else{
	LCD_DisplayStringLine(Line2,(uint8_t *)TextBuff);
	}
	
	sprintf(TextBuff,"PriceGoods2:%.2fY/kg", Goodsprice2);
	if(Key_4_Flag == 2){
			LCD_SetBackColor(Green);
			LCD_DisplayStringLine(Line3,(uint8_t *)TextBuff);
			LCD_SetBackColor(Blue);
	}
	else{
	LCD_DisplayStringLine(Line3,(uint8_t *)TextBuff);
	}
	
	sprintf(TextBuff,"PriceGoods3:%.2fY/kg", Goodsprice3);
	if(Key_4_Flag == 3){
			LCD_SetBackColor(Green);
			LCD_DisplayStringLine(Line4,(uint8_t *)TextBuff);
			LCD_SetBackColor(Blue);
	}
	else{
	LCD_DisplayStringLine(Line4,(uint8_t *)TextBuff);
	}

	
	
	sprintf(TextBuff,"    Setting times:%d", SettingTimes);
	LCD_DisplayStringLine(Line9,(uint8_t *)TextBuff);
	
}
/***************************************************************/



/****************************称重界面***************************/

void GoodsDisplay(uint8_t id, double Goodsprice)
{
	Weight_Value =Get_Adc_Average(ADC_CHANNEL_17,20) * 10.0 / 4096;
	
	LCD_DisplayStringLine(Line0,(uint8_t *)"  Weighing charges  ");
	
	sprintf(TextBuff," Goods ID:%d         ", id);
	LCD_DisplayStringLine(Line2,(uint8_t *)TextBuff);
	
	sprintf(TextBuff," Goods Price:%.2fY/Kg", Goodsprice);
	LCD_DisplayStringLine(Line3,(uint8_t *)TextBuff);
	
	sprintf(TextBuff," Goods Weight:%.2fKg", Weight_Value);
	LCD_DisplayStringLine(Line4,(uint8_t *)TextBuff);
	
	double Sum_Price = Goodsprice *  Weight_Value;
	sprintf(TextBuff," Sum Price:%.2f Y", Sum_Price);
	LCD_DisplayStringLine(Line5,(uint8_t *)TextBuff);
	
	LCD_DisplayStringLine(Line1,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line9,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line6,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line7,(uint8_t *)"                     ");
	LCD_DisplayStringLine(Line8,(uint8_t *)"                     ");
	
	if(Key_8_Flag == 1){
		printf("U.W.%d:%.2f\\n",id,Goodsprice);
		printf("G.W:%.2f\\n", Weight_Value);
		printf("Total:%.2f\\n",Sum_Price);
		printf("\\n");
	}
	
}

/****************************************************************/

//IIC读函数
uint8_t M24C02_Read(unsigned char address)
{
	unsigned char val;
	
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	
	I2CSendByte(address);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	val = I2CReceiveByte();
	I2CWaitAck();
	I2CStop();
	
	return val;
	
}

//IIC写函数
void M2402_write(unsigned char address, uint16_t info)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	
	I2CSendByte(address);
	I2CWaitAck();
	
	I2CSendByte(info);
	I2CWaitAck();
	I2CStop();
}


void Seting_Save()
{
	
	if(Set_Flag == 1){
		SettingTimes++;
		 Set_Flag = 0;
	}
	

	
	
	sprintf(TextBuff,"    Setting times:%d", SettingTimes);
	LCD_DisplayStringLine(Line9,(uint8_t *)TextBuff);
	
	

	
	uint16_t temp_z = Goodsprice1;
	uint16_t temp_x = (Goodsprice1-temp_z)*100;
	
	M2402_write(0x00,temp_z);
	HAL_Delay(5);	
	M2402_write(0x01,temp_x);
	HAL_Delay(5);
	
	
	temp_z = Goodsprice2;
	temp_x = (Goodsprice2-temp_z)*100;
	
	M2402_write(0x02,temp_z);
	HAL_Delay(5);	
	M2402_write(0x03,temp_x);
	HAL_Delay(5);
	
	temp_z = Goodsprice3;
	temp_x = (Goodsprice3-temp_z)*100;
	
	M2402_write(0x04,temp_z);
	HAL_Delay(5);	
	M2402_write(0x05,temp_x);
	HAL_Delay(5);
	
	M2402_write(0x06,SettingTimes);
	HAL_Delay(5);
	
}

void Printf_Save()
{
    static u8 Printf_Flag=1;     //按键松开标志
    if(Printf_Flag && Key_1_Flag == 2)
    {
    
        Printf_Flag=0;
        if(Key_1_Flag == 2){
					
				printf("U.W.1:%.2f\\n",Goodsprice1);
				printf("U.W.2:%.2f\\n",Goodsprice2);
				printf("U.W.3:%.2f\\n",Goodsprice3);
		


				}					
               
    }else if(Key_1_Flag != 2)Printf_Flag = 1;
 
}

/* 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_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	以上是关于第九届蓝桥杯嵌入式国赛(STM32G4与HAL库实现)的主要内容,如果未能解决你的问题,请参考以下文章

第九届蓝桥杯嵌入式国赛(STM32G4与HAL库实现)

STM32G4备战蓝桥杯嵌入式---实战---第九届嵌入式国赛(电子秤)

STM32G4备战蓝桥杯嵌入式---实战---第九届嵌入式国赛(电子秤)

STM32G4备战蓝桥杯嵌入式---实战---第九届嵌入式国赛(电子秤)

第十届蓝桥杯嵌入式国赛(STM32G4及HAL库)

第十届蓝桥杯嵌入式国赛(STM32G4及HAL库)