文章目录
- 一、功能简介
- 二、软件设计
- 三、实验现象
- 联系作者
一、功能简介
本项目使用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设计,视频分享,技术交流。