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

本文档介绍了一个嵌入式系统的实现,包括LCD显示、按键交互、ADC采集、EEPROM参数存储等功能。系统通过ADC采集按键状态,实现按键识别,并根据按键操作进行参数设置和数据显示。主循环中,程序读取ADC值,更新重量和价格信息,并通过UART发送数据。此外,详细展示了IIC接口的EEPROM读写操作,用于参数保存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

全部代码均是本人的一点思路,有不正确的地方,请指出,谢谢。

一、题目

功能简述

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

二、模块初始化以及功能分析

1.模块的初始化

需要使用的模块:LCD、按键B1~B8、ADC2双路检测、EEPROM参数存储
在这里插入图片描述

2.模块功能分析

LCD–>屏幕显示
按键B1~B8–>按键实现人机交互
ADC2–>两路注入通道测量电压值
EEPROM–>参数存储

三、函数实现

1.主函数分析

	/* IIC初始化 */
	I2CInit();
	/* LCD初始化 */
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	/* 参数初始化 */
	mode = 0;
	Number = 0;
	Location = 0;
	LED_number = 400;
	
	if(IIC_Read(0x07) != 1)
	{
		IIC_Write(0x00,0);HAL_Delay(5);//存储整数部分
		IIC_Write(0x01,20);HAL_Delay(5);//存储小数部分
		
		IIC_Write(0x02,0);HAL_Delay(5);
		IIC_Write(0x03,20);HAL_Delay(5);
		
		IIC_Write(0x04,0);HAL_Delay(5);
		IIC_Write(0x05,20);HAL_Delay(5);
		
		IIC_Write(0x06,0);HAL_Delay(5);
		IIC_Write(0x07,1);HAL_Delay(5);
	}

	Price[0] = IIC_Read(0x00)*100;					
	HAL_Delay(5);
	Price[0] = (double)(Price[0]+IIC_Read(0x01))/100;
	HAL_Delay(5);
	Price[1] = IIC_Read(0x02)*100;					
	HAL_Delay(5);
	Price[1] = (double)(Price[0]+IIC_Read(0x03))/100;
	HAL_Delay(5);
	Price[2] = IIC_Read(0x04)*100;					
	HAL_Delay(5);
	Price[2] = (double)(Price[0]+IIC_Read(0x05))/100;
	HAL_Delay(5);

	Time = IIC_Read(0x06);
	/* 关闭LED提示 */
	GPIOC->ODR |= 0xff00;
	GPIOD->ODR |= (1 << 2);
	GPIOD->ODR &= ~(1 << 2);
	HAL_Delay(200);

while(1)

/* 显示 */
	  Display();
		/* 两路adc采集 */
		HAL_ADC_Start(&hadc2);
		ADC_Value[0] = HAL_ADC_GetValue(&hadc2);
		HAL_Delay(10);
		HAL_ADC_Start(&hadc2);
		ADC_Value[1] = HAL_ADC_GetValue(&hadc2);
		HAL_ADC_Stop(&hadc2);
		/* 分别对重量和按键进行操作 */
		Weight = (double)(ADC_Value[0] & 0xfff)/0xfff*10;
	  key = Scan_Btn(ADC_Value[1] & 0xfff);
	  if(key && !key_last)	KEY_Handle(key);
		key_last = key;
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		/* LED提示 */
	  if(LED)
		  GPIOC->ODR &=~(1<<8);
	  else
		  GPIOC->ODR |= (1<<8);
	  GPIOC->ODR |= 0xfe00;
	  GPIOD->ODR |= (1 << 2);
	  GPIOD->ODR &= ~(1 << 2);

2.子函数分析

1.void Display(void)

mode为0时,显示初始页面.为1时,显示参数设置页面

void Display(void)
{
	if(mode == 0)
	{
		sprintf((char *)str,"  Weight & Charge  ");
		LCD_DisplayStringLine(Line1,str);
		
		sprintf((char *)str,"Number:  %d          ",Number+1);
		LCD_DisplayStringLine(Line3,str);
		
		sprintf((char *)str,"Price:   %.2lfYuan/kg",Price[Number]);
		LCD_DisplayStringLine(Line5,str);
		
		sprintf((char *)str,"Weight:  %.2lfkg     ",Weight);
		LCD_DisplayStringLine(Line7,str);
		
		sprintf((char *)str,"Total:   %.2lfYuan   ",money);
		LCD_DisplayStringLine(Line9,str);
	}
	else if(mode == 1)
	{
		sprintf((char *)str,"  Parameter Setting  ");
		LCD_DisplayStringLine(Line1,str);
		if(Location == 0)
			LCD_SetTextColor(Red);
		sprintf((char *)str,"Price 1: %.2lfYuan/kg",Price[0]);
		LCD_DisplayStringLine(Line3,str);
		LCD_SetTextColor(White);
		
		if(Location == 1)
			LCD_SetTextColor(Red);
		sprintf((char *)str,"Price 2: %.2lfYuan/kg",Price[1]);
		LCD_DisplayStringLine(Line5,str);
		LCD_SetTextColor(White);
		
		if(Location == 2)
			LCD_SetTextColor(Red);
		sprintf((char *)str,"Price 3: %.2lfYuan/kg",Price[2]);
		LCD_DisplayStringLine(Line7,str);
		LCD_SetTextColor(White);
		
		sprintf((char *)str,"Count:     %d        ",Time);
		LCD_DisplayStringLine(Line9,str);
	}
}

2.uint8_t Scan_Btn(uint16_t btn_tmp)

ADC采集值识别按键

uint8_t Scan_Btn(uint16_t btn_tmp)
{
	if(btn_tmp < 0x0FFF/14){
		return 1;
	}else if((btn_tmp > 0x0FFF/14) && (btn_tmp < 0x0FFF/14*3)){
		return 2;
	}else if((btn_tmp > 0x0FFF/14*3) && (btn_tmp < 0x0FFF/14*5)){
		return 3;
	}else if((btn_tmp > 0x0FFF/14*5) && (btn_tmp < 0x0FFF/14*7)){
		return 4;
	}else if((btn_tmp > 0x0FFF/14*7) && (btn_tmp < 0x0FFF/14*9)){
		return 5;
	}else if((btn_tmp > 0x0FFF/14*9) && (btn_tmp < 0x0FFF/14*11)){
		return 6;
	}else if((btn_tmp > 0x0FFF/14*11) && (btn_tmp < 0x0FFF/14*13)){
		return 7;
	}else if((btn_tmp > 0x0FFF/14*13) && (btn_tmp < 4000)){
		return 8;
	}
	else{
		return 0;
	}
}

3.void KEY_Handle(uint8_t key)

按键处理操作,内含有长按短按等各种操作。

void KEY_Handle(uint8_t key)
{
	uint16_t bb;
	if(key == B1_Press)
	{
		LED_number = 400;
		mode = !mode;
		if(!mode)
		{
			LED_number = 800;
			Time++;
			EEPROM_Conserve();
			sprintf((char *)arr,"U.W.1:%.2lf\r\n",Price[0]);
			HAL_UART_Transmit(&huart1,arr,strlen((char *)arr),50);
			sprintf((char *)arr,"U.W.2:%.2lf\r\n",Price[1]);
			HAL_UART_Transmit(&huart1,arr,strlen((char *)arr),50);
			sprintf((char *)arr,"U.W.3:%.2lf\r\n",Price[2]);
			HAL_UART_Transmit(&huart1,arr,strlen((char *)arr),50);
		}
	}
	else if(key == B2_Press && mode == 1)
	{
		Price[Location] +=0.01f;
		HAL_Delay(800);
		while(1)
		{
			HAL_ADC_Start(&hadc2);
			HAL_ADC_GetValue(&hadc2);
			HAL_Delay(10);
			HAL_ADC_Start(&hadc2);
			bb = HAL_ADC_GetValue(&hadc2);
			HAL_ADC_Stop(&hadc2);
			if(Scan_Btn(bb & 0xfff) == B2_Press)
			{
				Price[Location] +=0.01f;
			}
			else
				break;
			if(Price[Location] >= 10.0f)
				Price[Location] = 10;
			Display();
		}
	}
	else if(key == B3_Press && mode == 1)
	{
		Price[Location] -=0.01f;
		HAL_Delay(800);
		while(1)
		{
			HAL_ADC_Start(&hadc2);
			HAL_ADC_GetValue(&hadc2);
			HAL_Delay(10);
			HAL_ADC_Start(&hadc2);
			bb = HAL_ADC_GetValue(&hadc2);
			HAL_ADC_Stop(&hadc2);
			if(Scan_Btn(bb & 0xfff) == B3_Press)
			{
					Price[Location] -=0.01f;
			}
			else
				break;
			if(Price[Location] <= 0.0f)
				Price[Location] = 0;
			Display();
		}
		
	}
	else if(key == B4_Press && mode == 1)
	{
		Location++;
		Location %= 3;
	}
	else if(key == B5_Press)
	{
		Number = 0;
	}
	else if(key == B6_Press)
	{
		Number = 1;
	}
	else if(key == B7_Press)
	{
		Number = 2;
	}
	else if(key == B8_Press)
	{
		money = Price[Number]*Weight;
		sprintf((char *)arr,"U.W.%d:%.2lf\r\n",Number+1,Price[Number]);
		HAL_UART_Transmit(&huart1,arr,strlen((char *)arr),50);
		sprintf((char *)arr,"G.W:%.2lf\r\n",Weight);
		HAL_UART_Transmit(&huart1,arr,strlen((char *)arr),50);
		sprintf((char *)arr,"Total:%.2lf\r\n",money);
		HAL_UART_Transmit(&huart1,arr,strlen((char *)arr),50);
	}

4.EEPROM读写操作

void IIC_Write(uint8_t address,uint8_t data)
{
	I2CStart();
	I2CSendByte(0xA0);
	I2CWaitAck();
	
	I2CSendByte(address);
	I2CWaitAck();
	I2CSendByte(data);
	I2CWaitAck();
	I2CStop();
}
uint8_t IIC_Read(uint8_t address)
{
	uint16_t data;
	I2CStart();
	I2CSendByte(0xA0);
	I2CWaitAck();
	
	I2CSendByte(address);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xA1);
	I2CWaitAck();
	data = I2CReceiveByte();
	I2CSendNotAck();
	I2CStop();
	return data;
}

5.void EEPROM_Conserve(void)

参数存储

void EEPROM_Conserve(void)
{
	IIC_Write(0x00,(uint8_t)(Price[0]*100)/100);HAL_Delay(5);//存储整数部分
	IIC_Write(0x01,(uint8_t)(Price[0]*100)%100);HAL_Delay(5);//存储小数部分
	
	IIC_Write(0x02,(uint8_t)(Price[1]*100)/100);HAL_Delay(5);
	IIC_Write(0x03,(uint8_t)(Price[1]*100)%100);HAL_Delay(5);
	
	IIC_Write(0x04,(uint8_t)(Price[2]*100)/100);HAL_Delay(5);
	IIC_Write(0x05,(uint8_t)(Price[2]*100)%100);HAL_Delay(5);
	
	IIC_Write(0x06,Time);HAL_Delay(5);
}

测试:

在这里插入图片描述

总结

手写不易,请多支持,共同学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值