效果

如图:





流程

用户登录 -> 功能选择 -> 相应的功能

思路

  • 对于整个软件的使用而言,触摸屏坐标点的获取是必不可缺的,所以我们单独开一个获取触摸屏坐标点的线程,从始至终运行

  • 然后考虑到密码登录有两种形式,我们得开两个线程去处理,我们可以设置一个是否登录的全局变量,然后当未登陆的时候就一直循环,这样登陆得问题就得到解决了

  • 接下来是功能页面,当用户登陆界面结束后,就跳转到功能选择页面,这里我做的是左边是“立即下单”,右边是“历史订单”

  • 对于“立即下单”,我们要做的就是对每个商品能进行增加或者减少的操作,最终下单,下单后我们将这个单号的数据存储到对应的文件里面

  • 对于“历史订单”我们需要注意对于订单号的存储信息处理以及布局即可,我这里省事所以就只显示10条记录

  • 还有就是要创建一个获取温湿度的线程,然后在用户登陆后实时显示在左上角

代码

主要逻辑流程

为了更加清楚的看懂流程,我这里只展示main.c的内容,其余内容请在Github中获取https://github.com/MangataTS/GEC6818-project

如果打不开的话,可以从这里快速下载:http://acm.mangata.ltd/file/2/project.zip

#include <stdio.h>
#include <pthread.h>
#include "picture.h"
#include "getxy.h"
#include "font.h"
#include "UARTdh11.h"
#include "RFID.h"
#include <stdbool.h>
#include <string.h>
#include <termios.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#define true 1
#define false 0
#define PASSLEN 4
//************素材内容************
char *number[]={//数字"sucai/0.bmp","sucai/1.bmp","sucai/2.bmp","sucai/3.bmp","sucai/4.bmp","sucai/5.bmp","sucai/6.bmp","sucai/7.bmp","sucai/8.bmp","sucai/9.bmp",
};
char *del="sucai/del.bmp";
char *login="sucai/login.bmp";
char *background="sucai/back.bmp";
char *whiteblock="sucai/whiteblock.bmp";
char *shownumbers="sucai/shownumbers.bmp";
char *Error_login="sucai/errorlogin.bmp";
char *Login_Logo="sucai/login_logo.bmp";
char *NC[]={"sucai/CMWZ.bmp","sucai/FMYZC.bmp","sucai/KKNC.bmp","sucai/LMBH.bmp"
};
char *JGB="sucai/JGB.bmp";
char *XIADAN="sucai/XDCN.bmp";
//************素材内容************
int locpass=0;
int tolid = 0;
struct Good{int value;int number;char name[20];
};
int IDok;   //身份识别默认失败 0失败 1成功
char a[20][40];
extern char WsdString[20];void *Pcamera(void *arg);#if 1
//初始化,从文件中读取信息
void Message_init(){FILE *fp_message = fopen("Message_table.txt","r");if(fp_message == NULL) {fp_message = fopen("Message_table.txt","w");fclose(fp_message);return;}char buf[40];while(fgets(buf,40,fp_message)){//读取这些订单信息strcpy(a[tolid++],buf);tolid %= 10;//限制读取十条}fclose(fp_message);
}
//显示主界面
void show_Main(){show_anybmp(background,0,0);//背景show_anybmp(Login_Logo,90,90);//logoInit_Font();Display_characterX(300,0,"全全奶茶",0x00D2691E,3);UnInit_Font();//显示数字键盘for(int x = 310,i = 1;i <= 3; ++i,x += 60){for(int y = 240,j = 1;j <= 3; ++j,y += 60){show_anybmp(number[(i-1)*3+j],x,y);}}show_anybmp(number[0],360,420);//数字0show_anybmp(del,590,240);//删除键show_anybmp(login,590,340);//登陆键show_anybmp(shownumbers,280,90);//显示输入的数字
}
//下单界面
void show_Right(struct Good *goods){Init_Font();Clean_Area(0, 0,  800, 480, 0x00FFFFFF);printf("YES2\n");show_anybmp(NC[0],250,0);show_anybmp(NC[1],500,0);show_anybmp(NC[2],250,240);show_anybmp(NC[3],500,240);show_anybmp(JGB,700,0);//商品的左上角显示商品的数量char num[10];Clean_Area(250,0,20,20,0x00FF0000);sprintf(num,"%d",goods[0].number);Display_characterX(250,0,num,0x00FFFFFF,1);Clean_Area(500,0,20,20,0x00FF0000);sprintf(num,"%d",goods[1].number);Display_characterX(500,0,num,0x00FFFFFF,1);Clean_Area(250,240,20,20,0x00FF0000);sprintf(num,"%d",goods[2].number);Display_characterX(250,240,num,0x00FFFFFF,1);Clean_Area(500,240,20,20,0x00FF0000);sprintf(num,"%d",goods[3].number);Display_characterX(500,240,num,0x00FFFFFF,1);//商品的左上角显示商品的数量//logo?int sum_number = 0;int sum_value = 0;for(int i = 0;i < 4; ++i){sum_number += goods[i].number;//总数量sum_value += goods[i].value * goods[i].number;//总价值}
//    Display_characterX(10,10,"温湿度:",0x00D2691E,2);Display_characterX(10,90,WsdString,0x00D2691E,2);Display_characterX(10,300,"数量:",0x00D2691E,2);sprintf(num,"%d",sum_number);Display_characterX(120,300,num,0x00D2691E,2);Display_characterX(10,350,"共计:",0x00D2691E,2);sprintf(num,"%d¥",sum_value);Display_characterX(120,350,num,0x00D2691E,2);Clean_Area(0,0,250,80,0x00FFD700);//返回按钮Display_characterX(65,20,"返回",0x00FFFFFF,3);Clean_Area(0,400,250,80,0x00FFD700);//确认按钮Display_characterX(10,420,"确定下单",0x00FFFFFF,3);//数量
//  左上角的商品Clean_Area(250, 200,  199, 40, 0x00FFF0F5);Display_characterX(250,180,"-",0x00D2691E,5);Display_characterX(350,180,"+",0x00D2691E,5);
//  右上角的商品Clean_Area(500, 200,  199, 40, 0x00FFF0F5);Display_characterX(500,180,"-",0x00D2691E,5);Display_characterX(600,180,"+",0x00D2691E,5);
//  左下角的商品Clean_Area(250, 440,  199, 40, 0x00FFF0F5);Display_characterX(250,420,"-",0x00D2691E,5);Display_characterX(350,420,"+",0x00D2691E,5);
//  右下角的商品Clean_Area(500, 440,  199, 40, 0x00FFF0F5);Display_characterX(500,420,"-",0x00D2691E,5);Display_characterX(600,420,"+",0x00D2691E,5);UnInit_Font();
}
void Faild_login(){show_anybmp(Error_login,100,90);sleep(1);//睡1sshow_Main();//清空主界面locpass = 0;//将密码指针移到开头
}
//密码线程
int is_in(int x,int y,int startx,int starty,int endx,int endy){//判断触摸点是否在这个点内if(x >= startx && x <= endx && y >= starty && y<= endy){//如果在这个范围内返回1return 1;}return 0;
}
//
void *Ppass(void *arg)
{char password[4];char *banzipassword="4399";//内置密码while(!IDok){//        printf("(%d,%d)\n",x,y);if(x == -1 || y == -1) continue;if(x > 590 && x < 690 && y > 240 && y < 300){//点击删除框is_in(x,y,590,240,690,300)if(locpass == 0) {//表示密码框为空printf("密码框为空!\n");}else{//删除操作locpass--;show_anybmp(whiteblock,280+60*locpass,90);//覆盖前面一个位置}x = y = 0;}else if(x > 590 && x < 690 && y > 340 && y < 400){//点击登陆框is_in(x,y,590,340,690,400)if(locpass != 4){printf("密码框未输满!\n");}else{int fg = true;for(int i = 0;i < PASSLEN; ++i) {if(password[i] != banzipassword[i]){fg = false;}}if(fg) {//如果对了,那么显示奖励图片printf("密码正确!\n");x = y = 0;IDok = 1;printf("通过密码认证!\n");}else {//如果错了printf("密码错误!\n");Faild_login();}}x = y = -1;}else{if(locpass == 4) {//密码框已满printf("密码框已满!\n");}else{//点击数字框int locnumber;for(int XX = 310,i = 1;i <= 3; ++i,XX += 60){for(int YY = 240,j = 1;j <= 3; ++j,YY += 60){if(x > XX && x < (XX + 60) && y > YY && y < (YY + 60)){//is_in(x,y,XX,YY,XX+60,YY+60)locnumber = (i-1)*3+j;show_anybmp(number[locnumber],280+locpass*60,90);//显示输入的数字password[locpass++] = '0'+locnumber;}}}if(x > 360 && x < 420 && y > 420 && y < 480) {//数字0  is_in(x,y,360,420,420,480)locnumber = 0;show_anybmp(number[locnumber], 280 + locpass * 60, 90);password[locpass++] = '0' + locnumber;}}x = y = -1;}}pthread_exit(NULL); //退出该线程
}
//RFID线程int set_serial_uart_rfid(int ser_fd)//串口初始化
{struct termios new_cfg,old_cfg;/*保存并测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/if (tcgetattr(ser_fd, &old_cfg) != 0){perror("tcgetattr");return -1;}bzero( &new_cfg, sizeof(new_cfg));/*原始模式*//* 设置字符大小*/new_cfg = old_cfg;cfmakeraw(&new_cfg); /* 配置为原始模式 *//*波特率为115200*/cfsetispeed(&new_cfg, B9600);cfsetospeed(&new_cfg, B9600);new_cfg.c_cflag |= CLOCAL | CREAD;/*8位数据位*/new_cfg.c_cflag &= ~CSIZE;new_cfg.c_cflag |= CS8;/*无奇偶校验位*/new_cfg.c_cflag &= ~PARENB;/*1位停止位*/new_cfg.c_cflag &= ~CSTOPB;/*清除串口缓冲区*/tcflush( ser_fd,TCIOFLUSH);new_cfg.c_cc[VTIME] = 0;new_cfg.c_cc[VMIN] = 1;tcflush ( ser_fd, TCIOFLUSH);/*串口设置使能*/tcsetattr( ser_fd ,TCSANOW,&new_cfg);
}void *Prfid(void *arg)
{//1、打开串口设备int fd = open("/dev/ttySAC1" , O_RDWR|O_NOCTTY);if(fd < 0){perror ("open failed 1");exit(0);}printf("fd = %d\n",fd);//2、初始化串口set_serial_uart_rfid(fd);char request[8] = {0};get_Sjz(request);char fpz[9] = {0};get_Fpz(fpz);char buf[10] = {0};int ret;printf("[%d]\n", __LINE__);while(!IDok){printf("[%d]\n", __LINE__);ret = write(fd, request, 7);printf("write ret = %d\n",ret);for(int i = 0;i < 7; ++i) {printf("%x",request[i]);}putchar('\n');ret = read(fd, buf, 10);printf("read ret = %d\n",ret);printf("buf[2] = %x\n",buf[2]);printf("[%d]\n", __LINE__);if(ret > 0){if(buf[2] == 0){printf("请求成功\n");write(fd, fpz, 8);ret = read(fd, buf, 10);if(ret > 0){printf("防碰撞\n");if(buf[0] == 0x0a && buf[2] == 0x00){int cardid = (buf[7]<<24) | (buf[6] << 16) | (buf[5] << 8) | buf[4];if(cardid == 0x3D458719){IDok = 1;printf("刷卡成功!\n");break;}printf("OX%X\n",cardid);printf("CARDID = 0x%x 0x%x 0x%x 0x%x\n",buf[7],buf[6],buf[5],buf[4]);sleep(2);}}}else{printf("请求失败\n");}}}printf("exit RFID*****************\n");pthread_exit(NULL); //退出该线程
}
//下单弹窗
void submit_table(struct Good *goods){//提交页面show_anybmp(XIADAN,200,40);//显示下单成功的图片FILE* fd_table = fopen("Message_table.txt","w");char buf[40];memset(buf,0,sizeof buf);int value = 0;for(int i = 0;i < 4; ++i) value += goods[i].value * goods[i].number;time_t timep;struct tm *p;time(&timep);p = gmtime(&timep);char TIM[20];sprintf(TIM,"date:%d-%d-%d ",(int)(1900+p->tm_year),(int)(1+p->tm_mon),(int)p->tm_mday);strcat(buf,TIM);char HF[20];sprintf(HF,"cost: %d",value);strcat(buf,HF);printf("buf = %s \ntolid = %d\n",buf,tolid);strcpy(a[tolid++],buf);tolid%=10;for(int i = 0;i < 10; ++i) {if(strcmp(a[i],""))fprintf(fd_table,"%s\n",a[i]);}fclose(fd_table);sleep(1);//暂停1s
}void histoy_submit_table() {Init_Font();Display_characterX(10,30,WsdString,0x00D2691E,2);Clean_Area(0, 0,  800, 480, 0x00FFE4E1);//刷新背景Display_characterX(280,0,"历史订单",0x00D2691E,4);Clean_Area(700, 0, 100, 80, 0x00DCDCDC);//返回框Display_characterX(690,15,"返回",0x00D2691E,3);//这个订单是左侧的五个int cnt = 0;for(int i = 0;i < 5; ++i) {if(strcmp(a[i],"\n") == 0 || strcmp(a[i],"") == 0) continue;a[i][strlen(a[i])-1] ='\0';Display_characterX(0,80 + cnt * 80,a[i],0x00FFFFFF,2);cnt++;}for(int i = 5;i < 10; ++i) {a[i][strlen(a[i])-1] ='\0';if(strcmp(a[i],"\n") == 0 || strcmp(a[i],"") == 0) continue;if(cnt < 5) {Display_characterX(0,80 + cnt * 80,a[i],0x00FFFFFF,2);}else {Display_characterX(400,80 + (cnt-5) * 80,a[i],0x00FFFFFF,2);}cnt++;}while(1){Clean_Area(0, 0,  200, 80, 0x00FFE4E1);//刷新背景Display_characterX(10,30,WsdString,0x00D2691E,2);if(x > 700 && x < 800 && y > 0 && y < 80) {//返回框UnInit_Font();return;}}
}void show_check(){Init_Font();Clean_Area(0, 0,  400, 480, 0x00FFA500);//左侧点单Display_characterX(50,200,"即刻点单",0x00FF4500,4);Clean_Area(400, 0,  400, 480, 0x00AFEEEE);//右侧历史订单Display_characterX(450,200,"历史订单",0x00FF4500,4);UnInit_Font();
}#endifint main(int argc, char *argv[])
{IDok = 0;//初始化设备文件Message_init();//历史订单lcd_init();        //液晶屏ts_init();     //触摸屏//开启坐标获取线程pthread_t coordTid;pthread_create(&coordTid, NULL, getxy, NULL); //实时获取坐标show_Main();//身份认证:密码识别或者RFIDpthread_t passTid, rfidTid, cameraTid, dht11Tid;pthread_create(&passTid, NULL, Ppass, NULL);        //创建密码线程pthread_create(&rfidTid, NULL, Prfid, NULL);        //创建rfid线程pthread_create(&dht11Tid, NULL, funcTH, NULL);        //创建dht11线程->温湿度while(!IDok);    //直到身份认证成功show_check();while(1) {Init_Font();Clean_Area(0, 0,  200, 80, 0x00FFA500);//温湿度Display_characterX(10,10,WsdString,0x00D2691E,2);UnInit_Font();if(x > 0 && x < 400 && y > 0 && y < 480) {//左侧进入点单x = y = -1;struct Good G[4];memset(G,0,sizeof G);for(int i = 0;i < 4; ++i) G[i].number = 0;G[0].value = 13;//草莓丸子G[1].value = 10;//蜂蜜柚子G[2].value = 12;//可可奶茶G[3].value = 11;//柠檬薄荷show_Right(G);while(1) {Init_Font();Clean_Area(0, 80,  200, 80, 0x00FFFFFF);//左侧点单Display_characterX(10,90,WsdString,0x00D2691E,2);UnInit_Font();if(x > 250 && x < 350 && y > 200 && y < 240) {//左上角的删除printf("LEFT_UP_DEL\n");if(G[0].number)G[0].number--;show_Right(G);x = y = -1;}else if(x > 350 && x < 450 && y > 200 && y < 240) {//左上角的增加printf("LEFT_UP_ADD\n");G[0].number++;show_Right(G);x = y = -1;}else if(x > 500 && x < 600 && y > 200 && y < 240) {//右上角的删除printf("RIGHT_UP_DEL\n");if(G[1].number)G[1].number--;show_Right(G);x = y = -1;}else if(x > 600 && x < 700 && y > 200 && y < 240) {//右上角的增加printf("RIGHT_UP_ADD\n");G[1].number++;show_Right(G);x = y = -1;}else if(x > 250 && x < 350 && y > 440 && y < 480) {//左下角的删除printf("LEFT_DOWN_DEL\n");if(G[2].number)G[2].number--;show_Right(G);x = y = -1;}else if(x > 350 && x < 450 && y > 440 && y < 480) {//左下脚的增加printf("LEFT_DOWN_ADD\n");G[2].number++;show_Right(G);x = y = -1;}else if(x > 500 && x < 600 && y > 440 && y  < 480) {//右下角的删除printf("LEFT_DOWN_DEL\n");if(G[3].number)G[3].number--;show_Right(G);x = y = -1;}else if(x > 600 && x < 700 && y > 440 && y < 480) {//右下角的增加printf("RIGHT_DOWN_ADD\n");G[3].number++;show_Right(G);x = y = -1;}else if(x > 0 && x < 250 && y > 400 && y < 480) {//提交订单的需求printf("SUBMIT_S\n");if(G[0].number + G[1].number + G[2].number + G[3].number == 0){//如果没有选中,那么就不能提交x = y = -1;continue;}submit_table(G);show_Right(G);x = y = -1;}else if(x > 0 && x < 250 && y > 0 && y < 80) {//返回上一个界面x = y = -1;show_check();break;}}x = y = -1;}else if(x > 400 && x < 800 && y > 0 && y < 480){//进入历史订单x = y = -1;histoy_submit_table();x = y = -1;show_check();}}//资源释放lcd_close();   //液晶屏ts_close();        //触摸屏return 0;
}

这里的注释写的蛮多的,相信各位也能看得懂,我也就不一一赘述了

一些小坑点

1.对于每次获取坐标后,一定要将其清零,或者手动赋值一个不会使用的坐标点,否则会一直点下去

2.刷屏严重是刷新的频率太高了

3.对于控件的坐标点一定要提前规划好

4.这个font.h字体是稍微有点倾斜的,所以不要想将其纠正了

5.我的这个makefile文件是经过修改的,如果你想直接跑起来的话,得去改一下makefile,怎么改应该不用说了吧

6.RFID模块如果没反应,有可能是线松了

7.RFID模块线程read函数堵塞,原因还不知道,原因调出来了,可能是串口初始化的时候的波特率不正确

8.后面再看吧

小学期Deadline之GEC6818点奶茶系统相关推荐

  1. 小学期项目(C语言)————外卖点餐系统(功能齐全)

    这个项目是大一下期学校小学期的时候写的,当时只学过C语言所以是纯C语言编写的,也没有进行分文件编写,所以有五百六十多行,当时一个人写了三天左右写出来的,先给大家展示一下效果,虽然界面并不美观,但是该有 ...

  2. 北科大计算机小学期,北京科技大学小学期计算机实践(C++源代码)

    北京科技大学的暑期小学期有计算机实践,要求编写一个小的数据库查询系统,这个代码仅供参考,因为并不完善,自己并没有学得很好,不喜勿喷. /* 创建者:沈冲 完成时间:2011-7-21 */ #incl ...

  3. 第六阶段 小学期(一)——电子商务

    小学期开始了,我们首先体验了电子商务的B2B和B2C模型,了解了两种不同模型的不同特点 B2B(也有写成 BTB,是Business-to-Business的缩写)是指企业与企业之间通过专用网络或In ...

  4. 北邮计算机学不学单片机,北邮小学期PC单片机.docx

    2013年小学期单片机设计实验报告 题目:乐动时钟 班级:2011211118 班内序号:12 姓名:杨帆 实验组号:35 实验摘要 本次实验我们制作的乐动闹钟总体上来说是一款懒人闹钟,可以随时通过电 ...

  5. 软工小学期实践PART ONE

    本次小学期的目标是要做出一套前后端相连的客户信息服务系统. 首先,老师先让我们安装了需要的软件,以及配置相应的环境. 在安装Myeclipse中,我就遇到了一个问题,安装后打开时会弹出如下窗口: 经过 ...

  6. 计算机小学期实践报告,小学期计算机实践报告

    小学期计算机实习报告 一.实习目的 通过完成任务,学习并熟悉相关软件.了解并熟悉设计过程,从初步设计到实现到不断完善,掌握设计流程. 二 .实习任务 1.计算器程序 制作一个计算器程序: 支持2进制. ...

  7. c语言小学期大作业学生管理系统,小学期完成

    小学期...给我最深刻的启发就是...这辈子打死我都不做程序员...太TM累了... 小学期的任务是这样的: 题目概述: 某学校近年来招生规模不断扩大,每个院系的专业.班级.学生的数量急剧增加,在校学 ...

  8. 21秋计算机网络小学期——UDP服务器的设计(Python)

    21秋计算机网络小学期--UDP服务器的设计(Python) 本程序是我都小学期作业,内部肯定存在很多不是最合适的代码跟算法,望大佬指正. 最终成品链接 本文已经迁移到个人博客,博客链接:http:/ ...

  9. 小学期学Java有感

    大二末的小学期,为期四周的时间将要学完Java这门课程. 由于已经有了C,C++,数据结构算法等基础,这门课的进度可谓飞快.从最初的HelloWorld到今天未完成的视频压缩,其间才过去了11天. 由 ...

最新文章

  1. 小酌重构系列[8]——提取接口
  2. 最新综述:基于深度学习方式的单目物体姿态估计与跟踪
  3. Servlet第一篇【介绍Servlet、HTTP协议、WEB目录结构、编写入门Servlet程序、Servlet生命周期】...
  4. “重金求来”Alibaba技术官并发编程笔记,附赠复习资料
  5. python2.7 + selenium3.4.3浏览器的选择
  6. Docker源码分析(八):Docker Container网络(下)
  7. Python PIL : import _imaging _imagingft : No module named _imaging _imagingft(转)
  8. DCOS实践分享(4):如何基于DC/OS整合SMACK(Spark, Mesos, Akka, Cassandra, Kafka)
  9. 计算机考博哪个学校好考,管理学博士哪个学校好考
  10. C++设计模式-职责链模式
  11. 收藏 | 有没有什么可以节省大量时间的 Deep Learning 效率神器?
  12. quartz启动 mysql报错_quartz启动报错,本地是好的,部署到服务器就不行了,大神求助~~...
  13. [WARNING] Unable to autodetect 'javac' path, using 'javac' from the environment.
  14. LSTM模型实战案例:TensorFlow实现预测3位彩票号码
  15. 赤菟CH32V307 RISC-V 开发板 rt-thread 的坑 - esp8266的使用
  16. 课程设计题目:电力系统运行方式分析和计算
  17. dhcp服务器修改网关地址,5.1.9 配置DHCP客户端网关地址
  18. 今天有空,不如来找找“双鸭山大学”的由来吧~
  19. web前端利用leaflet生成粒子风场,类似windy
  20. C语言简单直观打印二叉树

热门文章

  1. 搜索指定期刊下的领域相关文章
  2. springmvc web.xml和application.xml配置详情(附:完整版pom.xml)
  3. 个人开发—进度记录(二)
  4. Django积木块八——三级联动
  5. 集合源码(一)之hashMap、ArrayList
  6. 弹窗样式 idialog,purebox,artdialog4.1.2,jquery.alert.v1.2
  7. Razor语法(四)
  8. Eclipse建立webservice客户端
  9. 用编程语言和计算机沟通
  10. 实战PHP数据结构基础之队列