基于STM32的智能电子称(单片机毕设)

前言

源代码下载链接:

需要实物的可以私信博主或者在文章最下方添加好友。

目录

一、项目介绍和演示视频

二、硬件实现

1. 硬件资料

2. PCB图以及原理图

三、软件实现

1. 源码框架

1、各模块初始化

2、初始化模块状态

3、检测蓝牙模块是否发送消息

4、扫描按键

 5、检测是否超出电子称的最大重量

6、刷新重量,并时刻根据商品类型刷新价格来显示在oled上 

7、根据按下的键值或者蓝牙模块发来的命令,进行对应事件的处理

2. 源码示例


一、项目介绍和演示视频

该项目实现内容如下:

本设计采用单片机作为主控制芯片,通过按键和微型屏幕来实现人机交互。同时可以通过无线通讯模块来实现信息的传递。本课题的主要研究内容如下:

  1. 收集并阅读相关资料,确定系统的总体设计方案。
  2. 硬件系统的设计:包括单片机最小开发板、液晶显示模块、压力传感器、蓝牙模块ADC模块等。
  3. 在软件的编程方面采用C语言作为系统程序语言。
  4. 系统实物体的制作以及相关的调试,要求整个系统完整并且稳定运行。

基本要求如下:

  1. 按键结合液晶屏幕,实现按键切换功能。
  2. 用蓝牙模块控制实现系统相关参数的设置。
  3. 液晶屏显示功能提醒词、系统的状态、已设置的参数等。
  4. 实现压力传感器的数据采集。
  5. 实现读取重量的功能并通过液晶屏幕显示
  6. 超过最大重量报警

实物图:

演示视频:

基于STM32的智能电子秤

二、硬件实现

1. 硬件资料

序号元器件型号数量
#DescriptionCommentQuantity
1STM32F103C8T6最小系统板/1
20.96寸OLED屏幕/1
3语音播报模块JQ8900-16P1
4喇叭8欧3W喇叭1
54.7K电阻0603R1
6三极管SS80501
7有源蜂鸣器BUZ-TH_BD12.01
8按键SW-TH_4P4
9主从一体蓝牙模块HC-051
10PM254-1-08-Z-8.5HDR-TH_8P-P2.542
11PM254-1-04-Z-8.5HDR-TH_4P-P2.542
12PM254-1-02-Z-8.5HDR-TH_2P-P2.541
13Type-c充电线/1

2. 原理图和PCB

 原理图:

PCB:

三、软件实现

1. 源码框架

工程文件:

Start:存放stm32配置的起始文件、内核相关文件、系统文件。

Library:存放stm32f103的标准库文件。

User:存放用户文件。

Hardware:存放硬件文件,包括蜂鸣器、HX711、OLED、JQ8900......

System:存放用户写的一些系统文件,例如延时、时钟配置、相关宏定义。

1.1 各模块初始化

Key_Init();//按键初始化

Buzzer_Init();//蜂鸣器初始化

OLED_Init();//oled初始化

Serial_Init();//蓝牙串口初始化

HX711_Init();//HX711初始化

Interface_Init();//接口初始化(屏幕初始化,显示对应内容)

JQ8900_Init();//语音模块初始化

1.2 初始化模块状态

HX711_SetTareWeight();//开机默认去皮一次

JQ8900_SetVolume(15);//设置音量为15

1.3 检测蓝牙模块是否发送消息

如果搜到消息,将消息转换成按键值,之后在进行对应按键按下的处理

if(Serial_GetRxFlag())
{
    Key_Num = Serial_GetRxData();
}

1.4 扫描按键

根据按键设置对应的键值,之后进行对应按键按下的处理

Key_Num = Key_GetNum(); //扫描按键

1.5 检测是否超出电子称的最大重量

代码示例:

if(HX711_ReadCount()>Weight_Max) //超过设定的最大重量
{
    //显示超重界面

    OLED_Clear();

    OLED_ShowF16x16(1,7,26);//警告

    OLED_ShowF16x16(1,9,27);


    OLED_ShowF16x16(2,3,28);//超出最大重量

    OLED_ShowF16x16(2,5,29);

    OLED_ShowF16x16(2,7,30);

    OLED_ShowF16x16(2,9,31);

    OLED_ShowF16x16(2,11,32);

    OLED_ShowF16x16(2,13,33);


    OLED_ShowF16x16(4,1,34);//请按下返回键返回

    OLED_ShowF16x16(4,3,35);

    OLED_ShowF16x16(4,5,36);

    OLED_ShowF16x16(4,7,37);

    OLED_ShowF16x16(4,9,38);

    OLED_ShowF16x16(4,11,39);

    OLED_ShowF16x16(4,13,37);

    OLED_ShowF16x16(4,15,38);

    while(Key_GetNum()!='4');

    OLED_Clear();

    Interface_Init();//接口初始化(屏幕初始化,显示对应内容)
}

//如果超过最大重量,显示提醒界面,等待按下返回键回到正常界面

1.6 刷新重量,并时刻根据商品类型刷新价格来显示在oled上 

代码示例:

Weight = HX711_Get_Weight(); //称重

Show_Weight(); //显示重量

Price = Commdoity_Price[Commodity_Num]*Weight;

lprice = (uint32_t)Price;

OLED_ShowNum(4,6,lprice,4);

1.7 根据按下的键值或者蓝牙模块发来的命令,进行对应事件的处理

代码示例:

if(Key_Num == '1') //去皮
{

    Key_Num = 0;

    JQ8900_Play(2);

    HX711_SetTareWeight();

    Show_States(1); //显示 状态 去皮

    Delay_s(1);

    Show_States(0); //显示 状态 称重

}
else if(Key_Num == '2') //切换商品
{

    Key_Num = 0;

    JQ8900_Play(1);

    (Commodity_Num == CNUM-1)?(Commodity_Num = 0):(Commodity_Num++);

    Show_Commodity(Commodity_Num);

}
else if((Key_Num >= 'a') && (Key_Num <= 'f')) //蓝牙直接切换到某商品

{

    Commodity_Num = Key_Num - 'a';

    Show_Commodity(Commodity_Num);

}
else if(Key_Num == '3') //打印账单

{

    JQ8900_Play(3);

    Key_Num = 0;

    Buzzer_ON();

    Delay_ms(500);

    Buzzer_OFF();

    Serial_SendCommodity(Commodity_Num);

    Serial_SendString("0.");

    Serial_SendNumber(Commdoity_Price[Commodity_Num]*100,2);

    Serial_SendString("yuan/gram\n");


    Serial_SendString("Bying ");

    Serial_SendNumber(Weight,4);

    Serial_SendString("gram and costing ");

    Serial_SendNumber(lprice,3);

    Serial_SendByte('.');

    Serial_SendNumber(rprice,2);

    Serial_SendString("yuan\n");
}

2. 源码示例

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Key.h"
#include "Buzzer.h"
#include "OLED.h"
#include "Serial.h"
#include "HX711.h"
#include "JQ8900.h"

#define Weight_Max 1000   //最大称重质量为5kg,这里不取到满,留一点缓冲
#define CNUM 6		//商品个数

uint8_t Key_Num, Commodity_Num;			//键码
uint32_t Weight;	//皮重,重量
float Price;			//多少钱一克,价格
float Commdoity_Price[CNUM] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6};	//对应每种商品单价
uint32_t Weight_last;//去皮之前的重量

void Show_States(uint8_t num);
void Interface_Init(void);
void Show_Commodity(uint8_t num);
void Show_Weight(void);
void Serial_SendCommodity(uint8_t num);

int main(void)
{
	uint32_t lprice=0, rprice;
	
	Key_Init();//按键初始化
	Buzzer_Init();//蜂鸣器初始化
	OLED_Init();//oled初始化
	Serial_Init();//蓝牙串口初始化
	HX711_Init();//HX711初始化
	Interface_Init();//接口初始化(屏幕初始化,显示对应内容)
	JQ8900_Init();//语音模块初始化
	
	HX711_SetTareWeight();//开机默认去皮一次
	JQ8900_SetVolume(25);//设置音量为15
	while (1)
	{
		if(Serial_GetRxFlag())
		{
			Key_Num = Serial_GetRxData();
		}
		else
		{
			Key_Num = Key_GetNum();			//扫描按键
		}
		if(HX711_Get_Weight()>Weight_Max-Weight_last) //超过设定的最大重量
		{
			//显示超重界面
			OLED_Clear();
			OLED_ShowF16x16(1,7,26);//警告
			OLED_ShowF16x16(1,9,27);
			
			OLED_ShowF16x16(2,3,28);//超出最大重量
			OLED_ShowF16x16(2,5,29);
			OLED_ShowF16x16(2,7,30);
			OLED_ShowF16x16(2,9,31);
			OLED_ShowF16x16(2,11,32);
			OLED_ShowF16x16(2,13,33);
			
			OLED_ShowF16x16(4,1,34);//请按下返回键返回
			OLED_ShowF16x16(4,3,35);
			OLED_ShowF16x16(4,5,36);
			OLED_ShowF16x16(4,7,37);
			OLED_ShowF16x16(4,9,38);
			OLED_ShowF16x16(4,11,39);
			OLED_ShowF16x16(4,13,37);
			OLED_ShowF16x16(4,15,38);
			
			while(Key_GetNum()!='4');
			OLED_Clear();
			Interface_Init();//接口初始化(屏幕初始化,显示对应内容)
			
		}
		
		Weight = HX711_Get_Weight();	//称重
		Show_Weight();					//显示重量
		
		Price = Commdoity_Price[Commodity_Num]*Weight;
		lprice = (uint32_t)Price;
		OLED_ShowNum(4,6,lprice,4);
		
		if(Key_Num == '1')	//去皮
		{
			Key_Num = 0;
			JQ8900_Play(1);	
			Weight_last=HX711_Get_Weight();//获取此时的重量
			HX711_SetTareWeight();
			Show_States(1);		//显示 状态 去皮
			Delay_s(1);
			Show_States(0);		//显示 状态 称重
			
		}
		else if(Key_Num == '2')	//切换商品
		{
			Key_Num = 0;
			JQ8900_Play(2);
			(Commodity_Num == CNUM-1)?(Commodity_Num = 0):(Commodity_Num++);
			Show_Commodity(Commodity_Num);
		}
		else if((Key_Num >= 'a') && (Key_Num <= 'f'))	//蓝牙直接切换到某商品
		{
			Commodity_Num = Key_Num - 'a';
			Show_Commodity(Commodity_Num);
		}
		else if(Key_Num == '3')	//打印账单
		{
			JQ8900_Play(3);	
			Key_Num = 0;
			Buzzer_ON();
			Delay_ms(500);
			Buzzer_OFF();
			Serial_SendCommodity(Commodity_Num);
			Serial_SendString("0.");
			Serial_SendNumber(Commdoity_Price[Commodity_Num]*100,2);
			Serial_SendString("yuan/gram\n");
			
			Serial_SendString("Bying ");
			Serial_SendNumber(Weight,4);
			Serial_SendString("gram and costing ");
			Serial_SendNumber(lprice,3);
			Serial_SendByte('.');
			Serial_SendNumber(rprice,2);
			Serial_SendString("yuan\n");
			
		}

		Delay_ms(50);
	}
}

void Interface_Init(void)
{
	OLED_ShowF16x16(1,1,13);	//状
	OLED_ShowF16x16(1,3,14);	//态
	OLED_ShowChar(1,5,':');
	Show_States(0);
	
	OLED_ShowF16x16(2,1,17);	//重
	OLED_ShowF16x16(2,3,18);	//量
	OLED_ShowChar(2,5,':');
	OLED_ShowF16x16(2,10,19);	//克
	
	Show_Commodity(Commodity_Num);
	OLED_ShowChar(3,5,':');
	OLED_ShowF16x16(3,10,0);	//元
	OLED_ShowChar(3,12,'/');
	OLED_ShowF16x16(3,13,19);	//克
	
	OLED_ShowF16x16(4,1,22);	//价
	OLED_ShowF16x16(4,3,23);	//格
	OLED_ShowChar(4,5,':');
	OLED_ShowF16x16(4,10,0);	//元
}

void Show_States(uint8_t num)
{
	
	switch(num){
		case 0:
			OLED_ShowF16x16(1,7,20);	//称
			OLED_ShowF16x16(1,9,17);	//重
			break;
		case 1:
			OLED_ShowF16x16(1,7,15);	//去
			OLED_ShowF16x16(1,9,16);	//皮
			break;
		case 2:
			OLED_ShowF16x16(1,7,21);	//计
			OLED_ShowF16x16(1,9,22);	//价
			break;
	}
	
}

void Show_Commodity(uint8_t num)
{
	uint8_t i;
	switch(num){
		case 0:
			OLED_ShowF16x16(3,1,1);	//苹
			OLED_ShowF16x16(3,3,2);	//果
		
			i = (uint8_t)Commdoity_Price[num];
			OLED_ShowNum(3,6,i,1);
			OLED_ShowChar(3,7,'.');
			OLED_ShowNum(3,8,(uint8_t)((Commdoity_Price[num]-i)*100),2);
			
			break;
		case 1:
			OLED_ShowF16x16(3,1,3);	//香
			OLED_ShowF16x16(3,3,4);	//蕉
		
			i = (uint8_t)Commdoity_Price[num];
			OLED_ShowNum(3,6,i,1);
			OLED_ShowChar(3,7,'.');
			OLED_ShowNum(3,8,(uint8_t)((Commdoity_Price[num]-i)*100),2);
		
			break;
		case 2:
			OLED_ShowF16x16(3,1,5);	//橘
			OLED_ShowF16x16(3,3,6);	//子
					
			i = (uint8_t)Commdoity_Price[num];
			OLED_ShowNum(3,6,i,1);
			OLED_ShowChar(3,7,'.');
			OLED_ShowNum(3,8,(uint8_t)((Commdoity_Price[num]-i)*100),2);
		
			break;
		case 3:
			OLED_ShowF16x16(3,1,7);	//葡
			OLED_ShowF16x16(3,3,8);	//萄
					
			i = (uint8_t)Commdoity_Price[num];
			OLED_ShowNum(3,6,i,1);
			OLED_ShowChar(3,7,'.');
			OLED_ShowNum(3,8,(uint8_t)((Commdoity_Price[num]-i)*100),2);
		
			break;
		case 4:
			OLED_ShowF16x16(3,1,9);	//菠
			OLED_ShowF16x16(3,3,10);	//萝
					
			i = (uint8_t)Commdoity_Price[num];
			OLED_ShowNum(3,6,i,1);
			OLED_ShowChar(3,7,'.');
			OLED_ShowNum(3,8,(uint8_t)((Commdoity_Price[num]-i)*100),2);
		
			break;
		case 5:
			OLED_ShowF16x16(3,1,11);	//西
			OLED_ShowF16x16(3,3,12);	//瓜
					
			i = (uint8_t)Commdoity_Price[num];
			OLED_ShowNum(3,6,i,1);
			OLED_ShowChar(3,7,'.');
			OLED_ShowNum(3,8,(uint8_t)((Commdoity_Price[num]-i)*100),2);
		
			break;
	}
	
}

void Show_Weight(void)
{
	OLED_ShowNum(2,6,Weight,4);
}

void Serial_SendCommodity(uint8_t num)
{
	switch(num){
		case 0:
			Serial_SendString("apple ");
			break;
		case 1:
			Serial_SendString("banana ");
			break;
		case 2:
			Serial_SendString("orange ");
			break;
		case 3:
			Serial_SendString("grape ");
			break;
		case 4:
			Serial_SendString("pineapple ");
			break;
		case 5:
			Serial_SendString("watermelon ");
			break;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热爱嵌入式的小佳同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值