【STM32单片机】自动售货机控制系统设计

news2024/12/1 0:22:14

文章目录

  • 一、功能简介
  • 二、软件设计
  • 三、实验现象
  • 联系作者


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用OLED显示模块、矩阵按键模块、LED和蜂鸣器、继电器模块等。
主要功能:
系统运行后,OLED显示系统初始界面,可通过矩阵按键S1和S5选择商品,OLED液晶显示商品价格,共有8种价格商品可供选择,且选择的商品对应LED会有指示。可通过S9和S13选择商品数量,当需要返回时可按下S16键,选择好商品和数量后可按下S12键,此时OLED显示累计商品总价,此时可通过键盘输入投币数,OLED显示投币值,若投币数值大于等于商品累计总价,则驱动继电器出货,且蜂鸣器报警提示,OLED显示找零数。若投币数小于商品累计总价,则OLED显示继续投币。


二、软件设计

/*
作者:嗨小易(QQ:3443792007)

*/


//系统功能控制
void sys_fun_ctrl(void)
{
	u8 key=0;
	static u8 sta=0;

	//扫描按键
	key=KEY_Matrix_Scan();
	//商品选择和数量显示
	if((key==1 || key==5) && sta==0)
	{
		sta=1;//仅显示一次
		OLED_Clear();
		OLED_ShowString(0,0,"Money:",16);
		OLED_ShowString(10*8,0,"Num:",16);
		OLED_ShowString(0,30,"OK",16);
		OLED_ShowString(14*8,30,"NO",16);	
	}
	if(sta)
	{
		switch(key)
		{
			case 1://商品价格+
				sys_ctrl.pric++;
				if(sys_ctrl.pric>8)sys_ctrl.pric=1;
				break;
			case 5://商品价格-
				sys_ctrl.pric--;
				if(sys_ctrl.pric<1)sys_ctrl.pric=8;	
				break;
			case 9://商品数量+
				sys_ctrl.num++;
				if(sys_ctrl.num>9)sys_ctrl.num=1;
				break;
			case 13://商品数量-
				sys_ctrl.num--;
				if(sys_ctrl.num<1)sys_ctrl.num=9;	
				break;
	
			case 12://OK,商品选择完成
				//总计商品价格
				sys_ctrl.pric=sys_ctrl.pric*sys_ctrl.num;	
				break;
	
			case 16://NO,返回/取消
				sta=0;
				sys_ctrl.runflag=0;
				//关闭LED指示灯
				LED1=1;LED2=1;LED3=1;LED4=1;
				LED5=1;LED6=1;LED7=1;LED8=1;
				sys_parm_init();
				sys_open_show();	
				break;
	
			case 2://投币1
				sys_ctrl.coin+=1;	
				break;
			case 3://投币50
				sys_ctrl.coin+=50;	
				break;
			case 6://投币5
				sys_ctrl.coin+=5;	
				break;
			case 7://投币100
				sys_ctrl.coin+=100;	
				break;
			case 10://投币10
				sys_ctrl.coin+=10;	
				break;
			case 14://投币20
				sys_ctrl.coin+=20;	
				break;
		}
		
		//商品价格和数量显示
		if(key==1 || key==5 || key==9 || key==13)
		{
			//商品价格显示
			OLED_ShowxNum(6*8,0,sys_ctrl.pric,1,16,0,1);
			//商品数量显示
			OLED_ShowxNum(14*8,0,sys_ctrl.num,1,16,0,1);
	
			//商品LED指示
			switch(sys_ctrl.pric)
			{
				case 1: 
					LED1=0;LED2=1;LED3=1;LED4=1;
					LED5=1;LED6=1;LED7=1;LED8=1;
					break;
				case 2: 
					LED1=1;LED2=0;LED3=1;LED4=1;
					LED5=1;LED6=1;LED7=1;LED8=1;
					break;
				case 3: 
					LED1=1;LED2=1;LED3=0;LED4=1;
					LED5=1;LED6=1;LED7=1;LED8=1;
					break;
				case 4: 
					LED1=1;LED2=1;LED3=1;LED4=0;
					LED5=1;LED6=1;LED7=1;LED8=1;
					break;
				case 5: 
					LED1=1;LED2=1;LED3=1;LED4=1;
					LED5=0;LED6=1;LED7=1;LED8=1;
					break;
				case 6: 
					LED1=1;LED2=1;LED3=1;LED4=1;
					LED5=1;LED6=0;LED7=1;LED8=1;
					break;
				case 7: 
					LED1=1;LED2=1;LED3=1;LED4=1;
					LED5=1;LED6=1;LED7=0;LED8=1;
					break;
				case 8: 
					LED1=1;LED2=1;LED3=1;LED4=1;
					LED5=1;LED6=1;LED7=1;LED8=0;
					break;
			}
		}
		//OK,商品选择完成
		if(key==12)
		{
			OLED_Clear();
			OLED_ShowString(0,0,"SUM:",16);
			OLED_ShowString(7*8,0,"Input:",16);
			OLED_ShowString(0,30,"OK",16);
			OLED_ShowString(14*8,30,"NO",16);
			//商品总价显示
			OLED_ShowxNum(4*8,0,sys_ctrl.pric,2,16,0,1);
			sys_ctrl.runflag=1;//商品选择完成标记
		}	
	}	
	
	//投币显示
	if((key==2 || key==3 || key==6 || key==7 || key==10 || key==14)&& sys_ctrl.runflag==1)
	{
		OLED_ShowxNum(13*8,0,sys_ctrl.coin,3,16,0,1);
		OLED_Refresh_Gram();//刷新显示缓存
		delay_ms(1500);//能显示一下投币数	
	}
	if(sys_ctrl.coin!=0 && sys_ctrl.runflag==1)
	{
		//如果投币数大于商品价格累计总和,则启动继电器出货和找零
		if(sys_ctrl.coin>=sys_ctrl.pric)
		{
			OLED_Clear();
			OLED_ShowString(0,0,"Shipment...",16);
			OLED_ShowString(0,30,"Change:",16);
			//显示找零数据
			sys_ctrl.change=sys_ctrl.coin-sys_ctrl.pric;
			OLED_ShowxNum(7*8,30,sys_ctrl.change,3,16,0,1);
			OLED_Refresh_Gram();//刷新显示缓存			
			LED0=0;//打开商品输出
			BEEP_Alarm(1000,100);//打开蜂鸣器
			delay_ms(1000);delay_ms(1000);
			LED0=1;//关闭商品输出
			//关闭LED指示灯
			LED1=1;LED2=1;LED3=1;LED4=1;
			LED5=1;LED6=1;LED7=1;LED8=1;
			sys_parm_init();
			sys_open_show();
			sta=0;
			sys_ctrl.runflag=0;
		}
		//如果投币数小于商品价格累计总和,则显示继续投币提示信息
		else
		{
			OLED_ShowString(0,0,"Please continue to coin...",16);
		}	
	}
	OLED_Refresh_Gram();//刷新显示缓存
}






三、实验现象

B站演示视频:https://space.bilibili.com/444388619
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


联系作者

专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1255732.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#的函数

可以发现首字母一般为动词 可以看出void是返回空值 这个就不是放回空值了 例如 函数修饰符 1、如上面的实例一样——无修饰符&#xff1a;如果一个参数没有用参数修饰符标记&#xff0c;则认为它将按值进行传递&#xff0c;这将以为着被调用的方法收到原始数据的一份副本。&am…

2024北京交通大学计算机考研分析

24计算机考研|上岸指南 北京交通大学 北京交通大学是教育部是首批进入国家“211工程”建设高校&#xff0c;是全国具有研究生院的56所高校之一&#xff0c;计算机与信息技术学院为北京交通大学下属二级学院&#xff0c;学院成立于2000年3月&#xff0c;其前身是成立于1977年的…

面向对象编程:Rust的面向对象特性

欢迎关注我的公众号lincyang新自媒体&#xff0c;回复关键字【程序员经典书单】&#xff0c;领取程序员的100本经典书单 大家好&#xff01;我是lincyang。 今天我们将深入探讨Rust语言中的面向对象编程&#xff08;OOP&#xff09;特性&#xff0c;并将其与其他流行编程语言进…

C# PIE-SDK二次开发界面汉化方法

那些最好的程序员不是为了得到更高的薪水或者得到公众的仰慕而编程&#xff0c;他们只是觉得这是一件有趣的事情&#xff01; C# PIE-SDK二次开发界面汉化方法 &#x1f340;前言&#x1f338;配置方法&#x1f355;拷贝语言包文件夹&#x1f354;增加窗体代码&#x1f35f;运行…

链表?细啊!超详细的知识点总结!

链表 定义&#xff1a;链表是一种递归的数据结构&#xff0c;它或者为空&#xff08;null)&#xff0c;或者是指向一个结点&#xff08;node&#xff09;的引用&#xff0c;该结点含有一个泛型的元素和一个指向另一条链表的引用。 ​ 其实链表就是有序的列表&#xff0c;它在内…

GPT实战系列-GPT训练的Pretraining,SFT,Reward Modeling,RLHF

GPT实战系列-GPT训练的Pretraining&#xff0c;SFT&#xff0c;Reward Modeling&#xff0c;RLHF 文章目录 GPT实战系列-GPT训练的Pretraining&#xff0c;SFT&#xff0c;Reward Modeling&#xff0c;RLHFPretraining 预训练阶段Supervised FineTuning &#xff08;SFT&#x…

文档向量化工具(二):text2vec介绍

目录 前言 text2vec开源项目 核心能力 文本向量表示模型 本地试用 安装依赖 下载模型到本地&#xff08;如果你的网络能直接从huggingface上拉取文件&#xff0c;可跳过&#xff09; ​运行试验代码 前言 在上一篇文章中介绍了&#xff0c;如何从不同格式的文件里提取…

4.整数输入,并输出变量类型【2023.11.26】

1.问题描述 使用 input 函数读入一个整数&#xff0c;并将该整数输出&#xff0c;并在下一行输出变量类型 2.解决思路 使用 type 函数获取变量类型 输入的内容从 input() 函数获取时&#xff0c;它们是字符串类型。但是&#xff0c;我们需要将其转换为整数类型&#xff0c;以…

乘法原理 LeetCode 828. 统计子串中的唯一字符

我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符&#xff0c;并返回唯一字符的个数。 例如&#xff1a;s "LEETCODE" &#xff0c;则其中 "L", "T","C","O","D" 都是唯一字符&#xff0c;…

速记:一个TL431应用电路

一个TL431应用电路 仿真结果 输出电压为&#xff1a;5V 负载电阻为&#xff1a; R4 50Ω 如果负载R4加重 显然负载加重&#xff0c;输出就达不到5V. 三极管T1 的作用 没有三极管的情况 同样是保持负载 R 50Ω 可见三极管的作用就是用来放大电流

带你用uniapp从零开发一个仿小米商场_8. 配置pages.json从而实现头部搜索框

通过观察小米商城的头部导航栏的时候可以发现,它是由一个文字图标,和一个输入框,还有一个扫描二维码的按钮 有两种实现方式,一种是自己写一个自定义导航,还有一种是用官方的 这里使用官方的,实现去到pages.json文件,找到index这个页面配置 可以通过给它设置app-plus app-pl…

线性模型加上正则化

使用弹性网络回归&#xff08;Elastic Net Regression&#xff09;算法来预测波士顿房屋价格。弹性网络回归是一种结合了L1和L2正则化惩罚的线性回归模型&#xff0c;能够处理高维数据和具有多重共线性的特征。弹性网络回归的目标函数包括数据拟合损失和正则化项&#xff1a; m…

基于jmeter的性能全流程测试

做性能测试的步骤 1、服务器性能监控 首先要在对应服务器上面安装性能监控工具&#xff0c;比如linux系统下的服务器&#xff0c;可以选择nmon或者其他的监控工具&#xff0c;然后在jmeter模拟场景跑脚本的时候&#xff0c;同时启动监控工具&#xff0c;这样就可以获得jmeter…

【LabVIEW学习】3.labview制作安装程序

一。生成exe文件 1.创建可执行文件 &#xff08;1&#xff09;创建项目 注意&#xff1a; 1.创建.exe文件&#xff0c;这个文件在labview环境下才可以运行&#xff0c;如果直接传递给其他电脑&#xff08;没有labview环境&#xff09;&#xff0c;他是不可以运行的。 2.如果已…

线程的状态以及状态转移

一. 线程的状态 NEW: 线程刚被创建, 但是并未启动. 还没调用start方法.RUNNABLE: 这里没有区分就绪和运行状态. 因为对于Java对象来说, 只能标记为可运行, 至于什么时候运行, 不是JVM来控制的了, 是OS来进行调度的, 而且时间非常短暂, 因此对于Java对象的状态来说, 无法区分.T…

一文读懂MySQL基础与进阶

Mysql基础与进阶 Part1 基础操作 数据库操作 在MySQL中&#xff0c;您可以使用一些基本的命令来创建和删除数据库。以下是这些操作的示例&#xff1a; 创建数据库&#xff1a; 要创建一个新的数据库&#xff0c;您可以使用CREATE DATABASE命令。以下是示例&#xff1a; CREA…

重量级消息,微软将ThreadX RTOS全家桶贡献给Eclipse基金会,免费供大家商用,宽松的MIT授权方式

从明年第1季度开始&#xff0c;任何人&#xff0c;任何厂家的芯片都可以免费商用&#xff0c;MIT授权就这点好。 贡献出来后&#xff0c;多方可以一起努力开发&#xff0c;当前首批兴趣小组AMD, Cypherbridge, Microsoft, NXP, PX5, Renesas, ST Microelectronics, Silicon Lab…

华为IE题中的QoS题配置案例

要求&#xff1a;保证局域网视频网段流量50M&#xff0c;在链路空闲时可以到100M 1、拥塞避免&#xff1a;根据AF队列的特性&#xff0c;把视频流量放入AF队列并设置为50M带宽&#xff0c;因为AF队列不但可以保证有50M&#xff0c;AF还可以暂用空闲带宽。 2、流量监管&#xf…

SASS的导入文件详细教程

文章目录 前言导入SASS文件使用SASS部分文件默认变量值嵌套导入原生的CSS导入后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Sass和Less &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努…

卷积神经网络(CNN)车牌识别

文章目录 一、前言二、前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据3. 查看数据3.数据可视化4.标签数字化 二、构建一个tf.data.Dataset1.预处理函数2.加载数据3.配置数据 三、搭建网络模型四、设置动态学习率五、编译六、训练八、保存和…