【STM32单片机】数学自动出题器设计

news/2024/7/5 1:50:26

文章目录

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


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED模块等。
主要功能:
系统运行后,OLED液晶显示出题器开机界面,默认结果范围为100,可按下S13键进入范围值设置,S1-S10键输入0-9数字,最大输入3位数;若输入有误可按下S11键撤回,若输入完成,可按下S12键进入答题界面;如果无需设置,则按下S16键进入答题界面;出题的计算结果范围则为前面设置的范围内。
此时显示屏会显示答题时间、得分、计算题(程序内设置了加减乘除,默认仅开启加减运算功能)和计算结果输入窗口,可按下S1-S10键输入答案,如果结果正确,
得分+5,否则显示错误提示,且需重新输入结果。答案正确则自动进入下一题,如此循环。当得分为100,则完成测试。


二、软件设计

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

*/


//系统生成题目
void sys_generate_subject(void)
{
	u8 key=0;
	u8 buf[3];
	u16 result=0;
	
	OLED_Clear();
	OLED_ShowString(0,0, "00:00:00   Socre:   ",12);
	OLED_ShowString((X_WIDTH-6*12)/2,16,"  +  =",24);
	OLED_DrawRectanglex(0,45,X_WIDTH,18,1);
	OLED_ShowString(2,46,"-->   ",16);
	
	TIM_Cmd(TIM3,ENABLE); //打开定时器	
	
	while(1)
	{
		//显示时间
		OLED_ShowxNum(0,0,sys_ctrl.hour,2,12,0x80,1);
		OLED_ShowxNum(6*3,0,sys_ctrl.min,2,12,0x80,1);
		OLED_ShowxNum(6*6,0,sys_ctrl.sec,2,12,0x80,1);
		//显示得分
		OLED_ShowxNum(17*6,0,sys_ctrl.score,3,12,0x80,1);
		
		//开始生成题目
		if(sys_ctrl.start==1)
		{
			sys_ctrl.start=0;
			srand(sys_ctrl.sec);//播种
			//生成随机符号值,加和减
			sys_ctrl.sign=rand()%2;
			//显示符号
			switch(sys_ctrl.sign)
			{
				case 0://加
					OLED_ShowString((X_WIDTH-6*12)/2+2*12,16,"+",24);
					//生成有效的两个计算数,在指定范围数内
					//rand() % (b-a+1)+ a ; 就表示 a~b 之间的一个随机整数
					sys_ctrl.num[0]=rand()%((sys_ctrl.range-1)-1+1)+1;
					sys_ctrl.num[1]=rand()%(sys_ctrl.range-sys_ctrl.num[0])+1;
					break;
				case 1://减
					OLED_ShowString((X_WIDTH-6*12)/2+2*12,16,"-",24);
					//生成的第一个数必须大于第二个数
					while(1)
					{
						sys_ctrl.num[0]=rand()%((sys_ctrl.range-1)-1+1)+1;
						sys_ctrl.num[1]=rand()%(sys_ctrl.range-sys_ctrl.num[0])+1;
						if(sys_ctrl.num[0]>=sys_ctrl.num[1])break;
					}
					break;
				case 2://乘
					OLED_ShowString((X_WIDTH-6*12)/2+2*12,16,"*",24);
					sys_ctrl.num[0]=rand()%((sys_ctrl.range-1)-1+1)+1;
					sys_ctrl.num[1]=rand()%(sys_ctrl.range-sys_ctrl.num[0])+1;
					break;
				case 3://除
					OLED_ShowString((X_WIDTH-6*12)/2+2*12,16,"/",24);
					//生成的第一个数必须大于第二个数
					while(1)
					{
						sys_ctrl.num[0]=rand()%((sys_ctrl.range-1)-1+1)+1;
						sys_ctrl.num[1]=rand()%(sys_ctrl.range-sys_ctrl.num[0])+1;
						if(sys_ctrl.num[0]>=sys_ctrl.num[1])break;
					}
					break;
			}
			//显示生成的两个计算数
			OLED_ShowxNum((X_WIDTH-6*12)/2,16,sys_ctrl.num[0],2,24,0,1);
			OLED_ShowxNum((X_WIDTH-6*12)/2+3*12,16,sys_ctrl.num[1],2,24,0,1);
		}
		//开始答题
		else
		{
			key=KEY_Matrix_Scan();
			if(key!=0)BEEP_Alarm(50,100);//提示音
			//输入数值键范围0-9
			if(key>0 && key<=10)
			{
				//最多输入3位数
				if(sys_ctrl.cnt<3)
				{
					//第一位输入0,后面都是0
					if(sys_ctrl.cnt==0 && key==1)
					{
						buf[sys_ctrl.cnt]=key-1;
						OLED_ShowNum(2+8*3+(sys_ctrl.cnt)*8,46,buf[sys_ctrl.cnt-1],1,16);
					}	
					else
					{
						buf[sys_ctrl.cnt]=key-1;
						sys_ctrl.cnt++;//输入位数+1
						OLED_ShowNum(2+8*3+(sys_ctrl.cnt-1)*8,46,buf[sys_ctrl.cnt-1],1,16);
					}	
				}
			}
			//按下删除键
			else if(key==11)
			{
				sys_ctrl.cnt--;
				if(sys_ctrl.cnt<0)sys_ctrl.cnt=0;
				OLED_ShowString(2+8*3+(sys_ctrl.cnt)*8,46," ",16);
			}	
			//按下确定键
			else if(key==12)
			{
				//获取范围值
				switch(sys_ctrl.cnt)
				{
					case 1://1位
						sys_ctrl.result=buf[0];
						break;
					case 2://2位
						sys_ctrl.result=buf[0]*10+buf[1];
						break;
					case 3://3位
						sys_ctrl.result=buf[0]*100+buf[1]*10+buf[2];
						break;
				}
				
				//根据符号计算生成题目的数值
				switch(sys_ctrl.sign)
				{
					case 0://加
						result=sys_ctrl.num[0]+sys_ctrl.num[1];
						break;
					case 1://减
						result=sys_ctrl.num[0]-sys_ctrl.num[1];
						break;
					case 2://乘
						result=sys_ctrl.num[0]*sys_ctrl.num[1];
						break;
					case 3://除
						result=sys_ctrl.num[0]/sys_ctrl.num[1];
						break;
				}
				//如果答题正确
				if(result==sys_ctrl.result)
				{
					sys_ctrl.start=1;
					sys_ctrl.cnt=0;
					sys_ctrl.score+=5;
					if(sys_ctrl.score>=100)
					{
						TIM_Cmd(TIM3,DISABLE); //关闭定时器
						sys_parm_init();//系统参数初始化
						break;
					}	
					OLED_ShowString(2+8*3,46,"   ",16);
				}
				//如果答题错误
				else
				{
					sys_ctrl.cnt=0;
					OLED_ShowString(2+8*3,46,"Error!",16);
					OLED_Refresh_Gram();//刷新显示缓存
					delay_ms(500);
					OLED_ShowString(2+8*3,46,"      ",16);
				}
			}		
		}
		
		OLED_Refresh_Gram();//刷新显示缓存
	}
}


//应用控制系统
void app_sys_ctrl_demo(void)
{
	LED_Init();
	USART1_Init(115200);
	OLED_Init();
	KEY_Matrix_Init();
	BEEP_Init();
	TIM3_Init(1000,36000-1);  //定时500ms
	sys_parm_init();//系统参数初始化
	
	while(1)
	{
		sys_open_show();//系统开机界面显示
		sys_generate_subject();//系统生成题目
	}
}





三、实验现象

B站演示视频:https://space.bilibili.com/444388619

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


联系作者

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


http://lihuaxi.xjx100.cn/news/1595712.html

相关文章

用《斗破苍穹》的视角打开C#委托2 委托链 / 泛型委托 / GetInvocationList

委托链 经过不懈地努力&#xff0c;我终于成为了斗师&#xff0c;并成功掌握了两种斗技——八极崩和焰分噬浪尺。于是&#xff0c;我琢磨着&#xff0c;能不能搞一套连招&#xff0c;直接把对方带走。 using System; using System.Collections.Generic; using System.Linq; u…

Vue中...(扩展运算符)的作用

对数组和对象而言&#xff0c;就是将运算符后面的变量里东西每一项拆下来。 &#xff08;一&#xff09;操作数组 // 1.把数组中的元素孤立起来 let iArray [1, 2, 3]; console.log(...iArray); // 打印结果 1 2 3// 2.在数组中添加元素 let iArray [1, 2, 3]; console.log…

云资源上传的审核机制

云资源上传的审核机制可以通过以下几个步骤进行判断&#xff1a; 扫描检测&#xff1a;使用自动化工具对云资源进行扫描和检测&#xff0c;以识别潜在的违规内容或安全风险。这可以包括使用恶意软件检测工具、敏感信息检测工具、版权侵权检测工具等。 人工审核&#xff1a;对于…

网站安全维护:守护您的数字领土

在这个数字时代&#xff0c;网站已成为企业和个人展示自己的重要平台。然而&#xff0c;随着互联网的高速发展&#xff0c;网站安全问题也日益严峻。黑客和入侵软件等威胁不断涌现&#xff0c;因此&#xff0c;保护网站免受这些威胁的影响变得至关重要。本文将探讨网站安全维护…

GitLab平台安装中经典安装语句含义解析

yum -y install policycoreutils openssh-server openssh-clients postfix 这是一个Linux命令&#xff0c;用于使用YUM包管理器安装指定的软件包。下面是对这个命令各部分的解释&#xff1a; yum&#xff1a;这是一个Linux命令行工具&#xff0c;用于管理RPM&#xff08;Red …

Helm部署EMQX集群

端口说明&#xff1a; 端口说明集群内端口Nodeport备注mqtt188331274Port for MQTTmqttssl888331170Port for MQTT(SSL)mgmt8081无ws808330099Port for WebSocket/HTTPwss808432580Port for WSS/HTTPSdashboard1808331303Port for dashboard 一、Helm在线部署EMQX集群 1、安…

电影产业的数据洞察:爬虫技术在票房分析中的应用

概述 电影产业是一个庞大而复杂的行业&#xff0c;涉及到各种各样的因素&#xff0c;如导演、演员、类型、主题、预算、宣传、口碑、评分、奖项等。这些因素都会影响电影的票房收入&#xff0c;也会反映出电影市场的动态和趋势。为了更好地了解电影产业的数据洞察&#xff0c;…

为何说医疗器械售后前景呈持续发展趋势?

为何说医疗器械售后前景呈持续发展趋势&#xff1f;如果医院的设备突然不运转了无法工作了&#xff0c;医院如果不及时维修&#xff0c;一天下来不仅患者有生命危险&#xff0c;医院的经济损失也不可估量&#xff0c;但是你知道这些医院的这些设备是怎么维修的吗&#xff1f;医…