基于GEC6818的简易自动售货机的设计

第一阶段的学习已经完成,老师布置了一个阶段验收项目,我以为是电子相册,谁知道,是这个,售货机,来说一下自己的心得体会吧
1 大二下学期的时候,有一个一周的简易项目需要完成,学生信息管理系统,不涉及到UI,数据库,网络,就是一个简简单单的vc6环境下的学生信息管理系统,功能?增删改查即可,老师说完要求,所有人,一半的人开始抱怨,难,另一半的人开始敲了,少数人开始思考怎么写,过了一会老师才说,你们是不是没做过项目呀,“是!”,“我去”,教你们,先画流程图,框架图,功能模块图,先写报告,编程是小事,第一次听老师提及项目这个词
2培训班老师说完,就开始想我应该怎么写,老师给我支招,先画流程图,再在主函数中写自己要做的东西的备注,先做什么再做什么
3画完流程图,写完备注后,思路果然清晰了许多,知道自己应该怎么做,做完后哪里可以优化升级一下了,编程?一天完成的差不多了,编程确实是小事
好了,给大家带来代码吧

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdbool.h>
#include "fp.h"

extern int *lcd_memory;
extern int lcd_fd ;
extern char n_16x32[][64] ;
extern char n_buf[][16];

int main()
{
	int x , y ;
	int pet_number = 0 ;//代表pet的标号,范围为 1~8,
	int page_current = 1 ;//代表当前页数
	int pet_select = 0 ;
	struct input_event events ;
	int touch_fd = open_lcd() ;
	// 2 打开触摸屏
	// 3 初始化链表
	listnode head = init_list() ;
	// 4 信息录入(从文件夹下的data.txt录入)如果没有自己插入
	int struNumber = info_entering(head,"./petData.txt") ;//信息录入
	show_all(head);
	printf(" struNumber : mainfile : %d\n",struNumber);
	listnode newOne = head->next ;
	if(struNumber == 0)// if no member in txt , aumotically add pets information
	{
		add_node(head,1,"Pikachu",1,100,"./pica.bmp");
		add_node(head,2,"cabi",0,150,"./cabi.bmp");
		add_node(head,3,"jng",0,130,"./jng.bmp");
		add_node(head,4,"littleGray",1,170,"./littleGray.bmp");
		add_node(head,5,"mwzz",1,200,"./mwzz.bmp");
		add_node(head,6,"spike",1,300,"./spike.bmp");
		add_node(head,7,"pinkball",1,200,"./pinkBall.bmp");
		add_node(head,8,"xhl",1,300,"./xhl.bmp");
	}
	//电脑端显示所有的信息
	show_all(head);
// 5 进入欢迎界面 3秒后进入售卖界面
	show_bmp( "./bg.bmp");
	pageshow( head , 1);//刚开始显示第一页
// 6 如果点击上一页或者下一页,便刷新
    int pos[3] = {-1,-1,-1};
    while(1)
	{
		kick_pos(pos);
		printf("x = %d   y = %d    pressure = %d\n", pos[0], pos[1], pos[2]);	
		x = pos[0];
		y = pos[1];
		if(CANCEL_SIGN)
		{
			//cancel(head);
			pet_select = 0 ;
			if(page_current == 1)
			{
				pageshow(head,1) ;
			}
			else
			{
				pageshow(head,2) ;
			}
		}
		if(PREV)
		{
			Next_And_Prev( &page_current , head , pet_select );
		}
		if(NEXT)
		{
			Next_And_Prev( &page_current , head , pet_select );
		}
		if(PET_1)
		{
			kick_pet( page_current , &pet_select , head , 1 ) ;
			show_all(head);
		}
		if(PET_2)
		{
			kick_pet( page_current , &pet_select , head , 2 ) ;
			show_all(head);
		}
		if(PET_3)
		{
			kick_pet( page_current , &pet_select , head , 3 ) ;
			show_all(head);
		}
		if(PET_4)
		{
			kick_pet( page_current , &pet_select , head , 4 ) ;
			show_all(head);
		}
		if(CHECK)
		{
			if(pet_select >= 1 && pet_select <= 8 )
			{
				show_bmp( "./bg.bmp");
				//show_pay1( "./pay.bmp" , head, pet_select, "./paysign.bmp");
				confirm_mode("./payConfirm.bmp" , head , &pet_select);
				//confirm_mode(char *confirmPic , listnode head , int petNumber  , int *pet_select)
				pet_select = 0 ;
				if(page_current == 1)
				{
					pageshow(head,1) ;
				}
				else
				{
					pageshow(head,2) ;
				}
				
			}
			show_all(head);
		}	
		if(ZONE_EXIT)
		{
			info_save( head );
			clear_lcd();
			break;
		}
	}	
	return 0;
}


#ifndef _FP_H_  
#define _FP_H_  
typedef struct node{
	int petNumber;
	char petName[20] ;
	int petSurplus;
	double petPrice;
	char petPic[50] ;
	struct node *next;   //next指向后一个节点指针(后继指针),
}*listnode;


extern char n_buf[][16];
extern char n_16x32[][64];

extern int *lcd_memory;
extern int lcd_fd ;

#define PAY_1 x >= 124  && y >= 24 && x < 230 && y < 120
#define PAY_2 x >= 276  && y >= 24 && x < 380 && y < 120
#define PAY_3 x >= 426  && y >= 24 && x < 530 && y < 120
#define PAY_4 x >= 576  && y >= 24 && x < 680 && y < 120

#define PET_1 x >= 40  && y >= 60 && x < 190 && y < 360
#define PET_2 x >= 230  && y >= 60 && x < 380 && y < 360
#define PET_3 x >= 420  && y >= 60 && x < 570 && y < 360
#define PET_4 x >= 610  && y >= 60 && x < 760 && y < 360
#define CANCEL_SIGN x >= 40  && y >= 370 && x < 190 && y < 470
#define PREV x >= 230  && y >= 370 && x < 380 && y < 470
#define NEXT x >= 420  && y >= 370 && x < 570 && y < 470
#define CHECK x >= 610  && y >= 370 && x < 760 && y < 470

#define ZONE_CONFIRM x >= 0  && y >= 380 && x < 360 && y < 480
#define ZONE_CANCEL x >= 440  && y >= 380 && x < 800 && y < 480
#define ZONE_EXIT x >= 770  && y >= 0 && x < 800 && y < 30
int lcd_draw_bmp( int x0 , int y0 , char* bmpAddress );
int open_lcd();
void show_all(listnode head);
listnode init_list();
int info_entering( listnode head , char* fileAddress );
int show_bmp( char* bmpAddress);
int add_node(listnode head,int petNumber,char* petName,int petSurplus,double petPrice ,char* petPic);
int pageshow(listnode head , int page);
void kick_pos(int *pos);
void show_num16x32(int x,int y, int num, int color);
void show_money(int x, int y, int money);
int show_pay( char* payAddress , listnode head, int petNumber ,char* paySignAddress);
void kick_pet( int page_current , int* pet_select , listnode head , int zoneNumber );
void Next_And_Prev( int* page_current , listnode head , int pet_select );
void confirm_mode(char *confirmPic , listnode head , int *pet_select);
int soldout_draw_bmp( int picNumber,  char *bmpname);
bool soldout_judge( listnode head , int petNumber);
int pay_way(listnode tmp, int petNumber);
void draw_bar(int x0, int y0, int width, int height, int speed, int color);
int info_save( struct node *head );
void close_lcd();
void clear_lcd();
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdbool.h>
#include "fp.h"


int *lcd_memory ;
int lcd_fd ;

//8*16
char n_buf[][16] ={
				{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,
				 0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"0",0*/

				{0x00,0x00,0x00,0x08,0x0E,0x08,0x08,0x08,
				0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"1",1*/

				{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x20,
				0x20,0x10,0x08,0x04,0x42,0x7E,0x00,0x00},/*"2",2*/

				{0x00,0x00,0x00,0x3C,0x42,0x42,0x20,0x18,
				0x20,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"3",3*/

				{0x00,0x00,0x00,0x20,0x30,0x28,0x24,0x24,
				0x22,0x22,0x7E,0x20,0x20,0x78,0x00,0x00},/*"4",4*/

				{0x00,0x00,0x00,0x7E,0x02,0x02,0x02,0x1A,
				0x26,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"5",5*/

				{0x00,0x00,0x00,0x38,0x24,0x02,0x02,0x1A,
				0x26,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"6",6*/

				{0x00,0x00,0x00,0x7E,0x22,0x22,0x10,0x10,
				0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00},/*"7",7*/

				{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,
				0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00},/*"8",8*/

				{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,
				0x64,0x58,0x40,0x40,0x24,0x1C,0x00,0x00} /*"9",9*/
				};	


//16*16				
char n_16x32[][64] = {
					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0xC0,0x07,0x60,0x0C,
					0x30,0x18,0x18,0x30,0x18,0x30,0x18,0x20,
					0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,
					0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,
					0x0C,0x60,0x18,0x20,0x18,0x30,0x18,0x30,
					0x30,0x18,0x60,0x0C,0xC0,0x07,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"0",0*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,
					0xF8,0x01,0x80,0x01,0x80,0x01,0x80,0x01,
					0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,
					0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,
					0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,
					0x80,0x01,0xC0,0x03,0xF8,0x1F,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",1*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0xE0,0x07,0x10,0x1C,
					0x08,0x18,0x04,0x30,0x04,0x30,0x0C,0x30,
					0x0C,0x30,0x00,0x30,0x00,0x18,0x00,0x08,
					0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00,
					0x40,0x00,0x20,0x20,0x10,0x20,0x08,0x20,
					0x04,0x30,0xFC,0x1F,0xFC,0x1F,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",2*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0xE0,0x03,0x18,0x0E,
					0x0C,0x0C,0x0C,0x18,0x0C,0x18,0x0C,0x18,
					0x00,0x18,0x00,0x0C,0x00,0x06,0xC0,0x03,
					0x00,0x0E,0x00,0x18,0x00,0x10,0x00,0x30,
					0x00,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x10,
					0x0C,0x18,0x18,0x0C,0xE0,0x03,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"3",3*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0E,
					0x00,0x0E,0x00,0x0F,0x80,0x0E,0x80,0x0E,
					0x40,0x0E,0x60,0x0E,0x20,0x0E,0x10,0x0E,
					0x10,0x0E,0x08,0x0E,0x04,0x0E,0x04,0x0E,
					0xFE,0x7F,0x00,0x0E,0x00,0x0E,0x00,0x0E,
					0x00,0x0E,0x00,0x0E,0x00,0x0E,0xC0,0x7F,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"4",4*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0xF0,0x3F,0xF0,0x3F,
					0x10,0x00,0x10,0x00,0x10,0x00,0x08,0x00,
					0x08,0x00,0xC8,0x07,0x28,0x0C,0x18,0x18,
					0x08,0x10,0x00,0x30,0x00,0x30,0x00,0x30,
					0x00,0x30,0x0C,0x30,0x0C,0x30,0x04,0x18,
					0x04,0x18,0x08,0x0C,0xF0,0x03,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"5",5*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x10,
					0x20,0x30,0x10,0x30,0x18,0x00,0x18,0x00,
					0x08,0x00,0x0C,0x00,0x8C,0x0F,0x6C,0x18,
					0x3C,0x30,0x1C,0x60,0x0C,0x60,0x0C,0x60,
					0x0C,0x60,0x0C,0x60,0x18,0x60,0x18,0x20,
					0x30,0x30,0x60,0x18,0xC0,0x07,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"6",6*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0xF8,0x3F,0xF8,0x3F,
					0x1C,0x10,0x0C,0x08,0x04,0x08,0x04,0x04,
					0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x01,
					0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,
					0x80,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,
					0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"7",7*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0xE0,0x07,0x30,0x0C,
					0x18,0x18,0x0C,0x30,0x0C,0x30,0x0C,0x30,
					0x1C,0x30,0x38,0x18,0x70,0x08,0xE0,0x07,
					0xB0,0x07,0x18,0x0E,0x0C,0x1C,0x06,0x38,
					0x06,0x30,0x06,0x30,0x06,0x30,0x06,0x30,
					0x0C,0x18,0x18,0x0C,0xE0,0x03,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"8",8*/

					{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
					0x00,0x00,0x00,0x00,0xE0,0x03,0x18,0x04,
					0x0C,0x08,0x0C,0x18,0x06,0x10,0x06,0x30,
					0x06,0x30,0x06,0x30,0x06,0x30,0x06,0x38,
					0x0C,0x3C,0x18,0x36,0xF0,0x31,0x00,0x30,
					0x00,0x18,0x00,0x18,0x00,0x18,0x0C,0x0C,
					0x0C,0x06,0x0C,0x03,0xF0,0x01,0x00,0x00,
					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/*"9",9*/	
};
//void draw_bar(int x0, int y0, int width, int height, int speed, int color);
// 1 打开lcd


/******************************************
*
*	函数功能:	打开显示屏,并关联一块与显示屏规格相同的内存
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019,8,19
*
*	参数说明:	全局变量 int *lcd_memory; int lcd_fd ;
*
*
*********************************************/
int open_lcd()
{
	//打开显示屏
	lcd_fd = open("/dev/fb0",O_RDWR);
	if(lcd_fd == -1)
	{
		perror("open lcd error");
		return -1;
	}
	
	//把显存映射到用户空间
	lcd_memory = mmap(NULL,	               //由系统自己寻找一个合适起始地址 
				      800*480*4,           //要映射多大的空间
					  PROT_READ|PROT_WRITE,//得到空间权限  可读可写
					  MAP_SHARED,		   //作为共享内存使用
					  lcd_fd, 			   //可用的描述符,入口
					  0);
	
}


/******************************************
*
*	函数功能:	初始化链表
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019,8,19
*
*	
*   返回头结点地址
*
*********************************************/
//初始链表
listnode init_list()
{
	listnode head = malloc(sizeof(struct node)); //申请头结点空间
	if(head == NULL)
	{
		perror("list init error");
		return NULL;
	}
	head->next = NULL;
	return head;//返回头结点地址
}

/******************************************
*
*	函数功能:	将数据数据从文件(fileAddress)录入到head链表中
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019,8,19
*
*	参数说明:	链表的头结点
*
*   返回值:    录入成功的个数
*
*********************************************/
int info_entering( listnode head , char* fileAddress )
{
	FILE *fp = fopen(fileAddress,"r");
    if(fp == NULL)
	{
		perror("fopen petData error");
		return -1;
	}
	else
    {
		printf("fopen petData succeed\n");
	}
    int sizeOfStru = sizeof(struct node);
    long sizeOfTXT ;  
	int struNumber;//stru number
	if( fseek(fp,0,SEEK_END) == -1 )
	{
		perror(" set seek failed\n");
		return -1;
	}//get the size of txt  
	else
		sizeOfTXT = ftell(fp);
	printf(" number :%ld\n",sizeOfTXT);
	rewind(fp);
	struNumber =(int) (sizeOfTXT/sizeOfStru);// get how many strus
	int i,ret;
	printf(" fp : %ld\n",ftell(fp));
	struct node tmp;
	printf(" struNUmber : %d\n",struNumber);
	for( i = 0 ; i < struNumber ; i++ )
	{
	  
		ret = fread(&tmp,sizeOfStru,1,fp);
		if( ret == 0 )
			perror("fread txt file error\n");
		//add_node(head,tmp.id_num,tmp.status,tmp.chinese,tmp.math,tmp.English,tmp.passwd,tmp.address,tmp.sex);
		printf(" fp : %ld\n",ftell(fp));
	}
	fclose(fp);
	return struNumber;
}

/******************************************
*
*	函数功能:	将数据数据从文件(fileAddress)录入到head链表中
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019,8,19
*
*	参数说明:  自己定义的链表新节点,以及新节点中的所有元素数据
*
*   返回值:    无
*
*********************************************/
//初始化数据,将参数中的数据按结点中的成员的数据类型赋给新的成员结点
void data_init(listnode newnode ,int petNumber,char* petName,int petSurplus,double petPrice ,char* petPic)
{
	newnode->petNumber = petNumber;
	strcpy(newnode->petName,petName);
	newnode->petSurplus = petSurplus;
	newnode->petPrice = petPrice;
	strcpy(newnode->petPic,petPic);
}

/******************************************
*
*	函数功能:	显示bmp图片
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019,8,19
*
*	参数说明:  图片地址
*
*   返回值:    错误返回 -1
*
*********************************************/
//显示 bmp图片
int show_bmp( char* bmpAddress)
{
	
	if( bmpAddress == NULL  )
	{
		printf(" wrong address\n") ;
		return -1 ;
	}
	char bmp_info[54] = {0};
	char bmp_data[800*480*4] = {0};
	char *p = bmp_data;
	//3 打开bmp图片
	int bmp_fd = open(bmpAddress,O_RDWR);
	if(bmp_fd == -1)
	{
		perror(" open lcd error");
		return -1;
	}
		
	//4 读取54个字节的头信息
	int bmpinfo_read_ret = read(bmp_fd,bmp_info,54);
	if(bmpinfo_read_ret == -1)
	{
		perror(" read bmp error \n");
		return -1;	
	}
	int bmp_width  = bmp_info[18] | bmp_info[19] << 8;
	int bmp_height = bmp_info[22] | bmp_info[23] << 8;
	printf(" width : %d\n",bmp_width); 
	printf(" height : %d\n",bmp_height); 
	int bmp_type   = 24;
	
	//5 读取颜色数据
	int bmpcolor_read_ret = read(bmp_fd,bmp_data,800*480*4);	
	if(bmpcolor_read_ret == -1)
	{
		perror(" read bmp color  error \n");
		return -1;	
	}
	
	//6 处理数据
	int i,j, color;
	for(i = 0; (i < 480) && (i < bmp_height); i++)
	{
		for(j = 0; (j < 800) && (j < bmp_width); j++)
		{
			color = *p | *(p+1) << 8 | *(p+2) << 16; 
			p += 3;	
			* (lcd_memory + 800*480 - 1 - ( 800*i + j)) = color;
		}
	}
}

/******************************************
*
*	函数功能:	插入新节点
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019,8,19
*
*	参数说明:  链表头节点,新节点的所有数据
*
*   返回值:    无
*
*********************************************/
int add_node(listnode head,int petNumber,char* petName,int petSurplus,double petPrice ,char* petPic)
{
	listnode newnode = malloc(sizeof(struct node));
	if(newnode == NULL)
	{
		perror("malloc newnode error");
		return -1;
	}
	//2、初始化节点数据
    data_init( newnode, petNumber, petName, petSurplus, petPrice , petPic);	
	//3找到链表尾部
	listnode p = head;
	while(p->next != NULL)  //如果p->next不等于 NULL,证明后面还有节点
	{
		p = p->next;	
	}
	newnode->next = p->next;
	p->next = newnode;	
	//printf("尾插法所接入的数据 %d,%c\n", p->next->id_num,p->next->status);
    return 0;
}



/******************************************
*
*	函数功能:	将图片展现在特定的位置(x0,y0将会为图片的左上角)
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  链表头节点,图片起始位置
*
*   返回值:    无
*
*********************************************/
int lcd_draw_bmp(int x0, int y0, char *bmpname)  
{
	int i, j;
	int bmp_fd = 0;
	int color = 0; //存储整理好颜色
	char blue, green, red; //临时存储单个颜色
	int bmp_height, bmp_width; //存储高度信息和宽度信息
	char bmp_info[54] = {0};
	char bmp_data[800*480*4] = {0};
	char *data_p = bmp_data;
	//把图片的颜色数取出,整理一下,写入
	bmp_fd = open(bmpname, O_RDONLY);
	if(bmp_fd == -1)
	{
		perror("open bmp error");
		return -1;
	}
	read(bmp_fd, bmp_info, 54); //读取属性信息
	
	//得到宽度信息
	bmp_width  = bmp_info[18];
	bmp_width |= bmp_info[19] << 8;
	//得到高度信息
	bmp_height  = bmp_info[22];
	bmp_height |= bmp_info[23] << 8;
	printf("width = %d\nheight = %d\n", bmp_width, bmp_height);
	read(bmp_fd, bmp_data, 800*480*4);			  
	//-----------------------------------------------
	//写颜色数据到入口
	for(i = y0+bmp_height-1; i >= y0; i--)
	{
		for(j = x0; j < x0+bmp_width; j++)
		{
			blue  = *data_p++;  //i*3
			green = *data_p++;
			red   = *data_p++;
			
			color = blue << 0 | green << 8 | red << 16;
			*(lcd_memory+i*800+j) = color;			
		}		
	}
	//把图片关掉
	close(bmp_fd);
}

/******************************************
*
*	函数功能:	将链表中的数按表的格式展示在电脑端
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019,8,19
*
*	参数说明:  链表头节点
*
*   返回值:    无
*
*********************************************/
//将链表中的数按表的格式展示在电脑端
void show_all(listnode head)
{
	listnode tmp = head;
	//printf("\tI\tS\tC\tM\tE\tA\t\tSEX\n\n");
        while(tmp->next != NULL)
	{
	
		printf("\t%d\t%s\t%d\t%f\t%s\t\n\n",tmp->next->petNumber,tmp->next->petName,tmp->next->petSurplus,tmp->next->petPrice ,tmp->next->petPic);
	    tmp = tmp->next;
	}
}

/******************************************
*
*	函数功能:	按照页号(page),将链表中的指定数据打印出来
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  头节点名,页号
*
*   返回值:    出错返回-1
*
*********************************************/
//按照页号(page),将链表中的指定数据打印出来
int pageshow(listnode head , int page )
{
	show_bmp("./bg.bmp");
	int petX = 40 ;
	int petY = 60 ;
	int petMoney = 30 ;
	int time = 1 ;
	listnode p = head;
	if( page == 1 )
	{
		while( p->next != NULL && time %5 != 0)  //如果p->next不等于 NULL,证明后面还有节点
		{
			p = p->next;	
			lcd_draw_bmp( ((p->petNumber - 1 )*148 + petX * time ), petY, p->petPic);
			show_money((( p->petNumber - 1 )*148 + petX *( time - 1 )  )+60, petMoney, p->petPrice);
			if( !soldout_judge( head , p->petNumber ) )
			{
				soldout_draw_bmp(p->petNumber,  "./soldout.bmp");
			}
			time++;
		}
		
	}
	if( page == 2 )
	{
		time = 1;
		while( time != 5 )
		{
			p = p->next;
			time++;
		}
		time = 1;
		while( time != 5 )  //如果p->next不等于 NULL,证明后面还有节点
		{	
			p = p->next;
			lcd_draw_bmp( (( p->petNumber - 5 )*148 + petX * time ), petY, p->petPic);
			show_money((( p->petNumber - 5 )*148 + petX *( time - 1 ))+60, petMoney, p->petPrice);
			if( !soldout_judge( head , p->petNumber ) )
			{
				soldout_draw_bmp(p->petNumber,  "./soldout.bmp");
			}
			time++;
		}
	}
	lcd_draw_bmp( 228, 370, "./leftArrow.bmp");
	lcd_draw_bmp( 418, 370, "./rightArrow.bmp");
	lcd_draw_bmp( 608, 370, "./check.bmp");
	lcd_draw_bmp( 40, 370, "./cancel.bmp");
	lcd_draw_bmp( 772, 0, "./exit.bmp");
	
}

/******************************************
*
*	函数功能:	按照图片的编号,将标记图片打印在传入参数的图片的位置上
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  图片名,图片编号
*
*   返回值:    出错返回-1
*
*********************************************/
//按照图片的编号,将标记图片打印在传入参数的图片的位置上
int pointer_draw_bmp( int picNumber,  char *bmpname)  
{
	int i, j;
	int x0,y0;
	if( picNumber <= 4 )
		x0 = ( picNumber - 1 )*148 + picNumber*40 ;
	else
		x0 = ( picNumber - 5 )*148 + (picNumber - 4)*40 ;
	y0 =  260;
	int bmp_fd = 0;
	int color = 0; //存储整理好颜色
	char blue, green, red; //临时存储单个颜色
	int bmp_height, bmp_width; //存储高度信息和宽度信息
	char bmp_info[54] = {0};
	char bmp_data[800*480*4] = {0};
	char *data_p = bmp_data;
	//把图片的颜色数取出,整理一下,写入
	bmp_fd = open(bmpname, O_RDONLY);
	if(bmp_fd == -1)
	{
		perror("open bmp error");
		return -1;
	}
	read(bmp_fd, bmp_info, 54); //读取属性信息
	
	//得到宽度信息
	bmp_width  = bmp_info[18];
	bmp_width |= bmp_info[19] << 8;
	//得到高度信息
	bmp_height  = bmp_info[22];
	bmp_height |= bmp_info[23] << 8;
	printf("width = %d\nheight = %d\n", bmp_width, bmp_height);
	read(bmp_fd, bmp_data, 800*480*4);			  
	//-----------------------------------------------
	//写颜色数据到入口
	for(i = y0+bmp_height-1; i >= y0; i--)
	{
		for(j = x0; j < x0+bmp_width; j++)
		{
			blue  = *data_p++;  //i*3
			green = *data_p++;
			red   = *data_p++;
			
			color = blue << 0 | green << 8 | red << 16;
			*(lcd_memory+i*800+j) = color;			
		}		
	}
	//把图片关掉
	close(bmp_fd);

}

/******************************************
*
*	函数功能:	根据用户在触摸屏上的点击,修改pos中数据(数据修改为横坐标,纵坐标,pressure值)
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  位置数组
*
*   返回值:    无
*
*********************************************/
//
void kick_pos(int* pos)
{
	struct input_event events;
	pos[0] = -1, pos[1] = -1, pos[2] = -1;
	int touch_fd = open("/dev/input/event0", O_RDWR);
	if(touch_fd == -1)
		perror("open touch error");
	
	while(1)
	{
		int ret = read(touch_fd, &events, sizeof(events));
		if(ret == -1)
			perror("read error");
		//分析报告
		if(events.type == EV_ABS)
		{
			if(events.code == ABS_X)
				pos[0] = events.value;
			if(events.code == ABS_Y)
				pos[1] = events.value;
			if(events.code == ABS_PRESSURE)
			{
				pos[2] = events.value;
				if(pos[2] == 0)
					//printf("x = %d   y = %d    pressure = %d\n", pos[0], pos[1], pos[2]);	
					close(touch_fd);
					break;
			}
		}	
	}
}

/******************************************
*
*	函数功能:	展示支付模块,先显示支付选择的界面,用户可以通过点击按钮选择支付方式
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  支付图片的地址,头节点,宠物号,各类图片地址
*
*   返回值:    无
*
*********************************************/
int show_pay( char* payAddress , listnode head, int petNumber ,char* paySignAddress)
{
	//先显示支付选择的界面
	//用户可以通过点击按钮选择支付方式
	listnode tmp = head ;
	while( (tmp->next)->petNumber != petNumber )
	{
		tmp = tmp->next;
	}
	//lcd_draw_bmp(222, 60, (tmp->next)->petPic);
	lcd_draw_bmp(0,0, "./newPay.bmp");
	lcd_draw_bmp(250,390, paySignAddress);//115,12
	show_money(365, 402, (tmp->next)->petPrice);//三位数时,定位为555,312
	pay_way((tmp->next), petNumber);
	return 1;
}

/******************************************
*
*	函数功能:	确认模块
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  确认的图片地址,头节点,宠物选择
*
*   返回值:    无
*
*********************************************/
void confirm_mode(char *confirmPic , listnode head , int *pet_select)
{
	int x, y;
	lcd_draw_bmp(0, 360, confirmPic) ;
	listnode tmp = head ;
	while( (tmp->next)->petNumber != *pet_select )
	{
		tmp = tmp->next;
	}
	lcd_draw_bmp(222, 60, (tmp->next)->petPic);
	show_money(555, 240, (tmp->next)->petPrice);//三位数时,定位为555,312
	int pos_confirm[3] = {-1,-1,-1};
	while(1)
	{
		kick_pos(pos_confirm);
		printf("x = %d   y = %d    pressure = %d\n", pos_confirm[0], pos_confirm[1], pos_confirm[2]);	
		x = pos_confirm[0];
		y = pos_confirm[1];
		if(ZONE_CONFIRM)
		{
			show_pay( "./pay.bmp" , head, *pet_select, "./paysign.bmp");
			*pet_select = 0;
			break;
		}
		if(ZONE_CANCEL)
		{
			*pet_select = 0;
			pageshow(head , 1);
			break;
		}		
	}	
}

/******************************************
*
*	函数功能:	16*32 数字显示
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  数字显示的起始地址,颜色
*
*   返回值:    无
*
*********************************************/
//显示数字16*32
void show_num16x32(int x,int y, int num, int color)
{
	int i = 0,j = 0, s = 0;
	char A = 0x1;
	int k;
	
	k = 0;
	for(i = 0; i < 32; i++)
	{	
		s = 0;
		for(j = 0; j < 8; j++)
		{
			if(A<<s  & n_16x32[num][k])
			{
				*(lcd_memory+ (i+y)*800 + (j+x)) = color;
			}
			s++;	
		}
		s = 0;
		k++;
		for(j = 8 ; j < 16; j++)
		{	
			if(A<<s  & n_16x32[num][k])
			{
				*(lcd_memory+ (i+y)*800 + (j+x)) = color;
			}
			s++;
		}
		k++;
	}		
}

/******************************************
*
*	函数功能:	显示金额
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  数字起始地址,金额
*
*   返回值:    无
*
*********************************************/				
//显示金额 2300   1  0  0  0     2   int = 2331/1000  
void show_money(int x, int y, int money)
{
	
	if(money >= 1000)
		show_num16x32(x, y, money/1000, 0xff0000); //显示 千位
	show_num16x32(x+20, y, money%1000/100, 0xff0000); //显示 百位
	show_num16x32(x+40, y, money%1000%100/10, 0xff0000); //显示 十位
	show_num16x32(x+60, y, money%10, 0xff0000); //显示 个位
}

/******************************************
*
*	函数功能:	宠物选择数
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  当前页,宠物选择数,头节点,区域数区域选择( zoneNumber = 1 ~ 4 )
*
*   返回值:    无
*
*********************************************/
void kick_pet( int page_current , int* pet_select , listnode head , int zoneNumber )
{
	if( page_current == 1 )
	{
		if( *pet_select != zoneNumber)
		{
			*pet_select = zoneNumber ;
			pageshow(head,1) ;
		}
		if ( soldout_judge( head , *pet_select ) )
			pointer_draw_bmp( *pet_select,"./pointer.bmp");
		else
			soldout_draw_bmp( *pet_select , "./soldout.bmp" );
	}
	if( page_current == 2 )
	{
		if( *pet_select != ( zoneNumber + 4 ) )
		{
			*pet_select = zoneNumber + 4 ;
			pageshow(head,2) ;
		}
		if ( soldout_judge( head , *pet_select ) )
			pointer_draw_bmp( *pet_select,"./pointer.bmp");
		else
			soldout_draw_bmp( *pet_select , "./soldout.bmp" );
	}
	
}

/******************************************
*
*	函数功能:	上一页,下一页
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  当前页,宠物选择数,头节点,
*
*   返回值:    无
*
*********************************************/
void Next_And_Prev( int* page_current , listnode head , int pet_select )
{
	if( *page_current == 1 )
	{
		pageshow(head,2) ;
		if(pet_select <= 8 && pet_select >= 5)
		{
			pointer_draw_bmp(pet_select - 4 , "./pointer.bmp");
		}
	}
	else
	{
		pageshow(head,1) ;
		if(pet_select <= 4 && pet_select >= 1)
		{
			pointer_draw_bmp(pet_select  , "./pointer.bmp");
		}
	}
			
	if( *page_current == 1 )
		*page_current = 2 ;
	else if( *page_current == 2 )
		*page_current = 1 ;
}

/******************************************
*
*	函数功能:	售尽标志显示
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  照片数,图片地址
*
*   返回值:    失败返回负一
*
*********************************************/
int soldout_draw_bmp( int picNumber,  char *bmpname)  
{
	int i, j;
	int x0,y0;
	if( picNumber <= 4 )
		x0 = ( picNumber - 1 )*148 + picNumber*40 ;
	else
		x0 = ( picNumber - 5 )*148 + (picNumber - 4)*40 ;
	y0 =  60;
	int bmp_fd = 0;
	int color = 0; //存储整理好颜色
	char blue, green, red; //临时存储单个颜色
	int bmp_height, bmp_width; //存储高度信息和宽度信息
	char bmp_info[54] = {0};
	char bmp_data[800*480*4] = {0};
	char *data_p = bmp_data;
	//把图片的颜色数取出,整理一下,写入
	bmp_fd = open(bmpname, O_RDONLY);
	if(bmp_fd == -1)
	{
		perror("open bmp error");
		return -1;
	}
	read(bmp_fd, bmp_info, 54); //读取属性信息
	//得到宽度信息
	bmp_width  = bmp_info[18];
	bmp_width |= bmp_info[19] << 8;
	//得到高度信息
	bmp_height  = bmp_info[22];
	bmp_height |= bmp_info[23] << 8;
	printf("width = %d\nheight = %d\n", bmp_width, bmp_height);
	read(bmp_fd, bmp_data, 800*480*4);			  
	//-----------------------------------------------
	//写颜色数据到入口
	for(i = y0+bmp_height-1; i >= y0; i--)
	{
		for(j = x0; j < x0+bmp_width; j++)
		{
			blue  = *data_p++;  //i*3
			green = *data_p++;
			red   = *data_p++;
			
			color = blue << 0 | green << 8 | red << 16;
			*(lcd_memory+i*800+j) = color;			
		}		
	}
	//把图片关掉
	//close(bmp_fd);
}

/******************************************
*
*	函数功能:	售尽判断
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  宠物编号,头节点
*
*   返回值:    判断相应宠物的数量是否为0,为0返回false,否则返回true;
*
*********************************************/

bool soldout_judge( listnode head , int petNumber )
{
	listnode tmp = head->next ;
	while( tmp->petNumber != petNumber )
	{
		tmp = tmp->next;
	}
	if(tmp->petSurplus == 0)
		return false ;
	else
		return true ;
}

/******************************************
*
*	函数功能:	支付方式选择
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  宠物编号,头节点
*
*   返回值:    1
*
*********************************************/
int pay_way(listnode tmp, int petNumber)
{
	int pos[3] = { -1 , -1 , -1 };
	int x , y;
	while(1)
	{
		kick_pos(pos);
		printf(" payway :x = %d   y = %d    pressure = %d\n", pos[0], pos[1], pos[2]);	
		x = pos[0];
		y = pos[1];
		if(PAY_1)
		{
			lcd_draw_bmp(250, 150, "./cash.bmp");
			draw_bar(250, 460, 300, 19, 100, 0xff0000);
			(tmp->petSurplus)--;
			sleep(3);
			break;
		}
        if(PAY_2)
		{
			lcd_draw_bmp(250, 150, "./wecharPay.bmp");
			draw_bar(250, 460, 300, 19, 100, 0xff0000);
			(tmp->petSurplus)--;
			sleep(3);
			break;
		}
		if(PAY_3)
		{
			lcd_draw_bmp(250, 150, "./pay.bmp");
			draw_bar(250, 460, 300, 19, 100, 0xff0000);
			(tmp->petSurplus)--;
			sleep(3);
			break;
		}
		if(PAY_4)
		{
			lcd_draw_bmp(250, 150, "./bank.bmp");
			draw_bar(250, 460, 300, 19, 100, 0xff0000);
			(tmp->petSurplus)--;
			sleep(3);
			break;
		}
	}
    return 1;	
}

/******************************************
*
*	函数功能:	画进度条
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  进度条起始位置,进度条宽度,高度,速度,颜色
*
*   返回值:    无
*
*********************************************/
//画进度条
void draw_bar(int x0, int y0, int width, int height, int speed, int color)
{
	int i, j;
	for(i = x0; i < x0+width; i++)
	{
		for(j = y0; j < y0+height; j++)
		{
			*(lcd_memory+j*800+i) = color;		
		}
		usleep(speed);
	}	
}

/******************************************
*
*	函数功能:	数据存储
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  头节点
*
*   返回值:    失败返回负一
*
*********************************************/
int info_save( struct node *head )
{
	int number = 0;
	int i = 0 ;
	struct node *tmpSave;
	int ret;
	FILE *fp = fopen("./petData.txt","w+");
    if(fp == NULL)
	{
		perror("fopen petData.txt error");
		return -1;
	}
	else
    {
		printf("fopen petData.txt succeed\n");
	}   
	listnode tmp = head;
	while(tmp->next != NULL)
	{
	    number++;	
	    tmp = tmp->next;
	}
	tmp = head;
	printf(" head : %d\n",number);
	tmpSave = tmp->next;
	for( i = 0 ; i < number ; i++ )
	{
		
		ret = fwrite(tmpSave,sizeof(struct node),1,fp);
		tmpSave = tmpSave->next; //fseek(fp,sizeof(struct node),SEEK_CUR);
	}
      //  printf(" end : %d\n",);
    fclose(fp);    
    return 1;   
}

/******************************************
*
*	函数功能:	关闭lcd屏幕
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  无
*
*   返回值:    无
*
*********************************************/
void close_lcd()
{
	//取消映射和关闭lcd
	munmap(lcd_memory, 800*480*4);
	close(lcd_fd);	
}

/******************************************
*
*	函数功能:	清屏
*
*	函数版本:  v1.0
*
*	编写作者:	荆州张球王
*
*	编写时间:	2019.8.19
*
*	参数说明:  无
*
*   返回值:    无
*
*********************************************/
void clear_lcd()
{
	//把屏幕描成黑色-------------------------------------------
	memset(lcd_memory, 0, 800*480*4);
}



然后我来说说过程中我遇到的问题吧
1 图片的格式问题,开发板为800480的板子,我们图片格式选用的是bmp,24位的,图片格式(height,width)一定要是4的倍数,我刚开始用的是150300,所以图片总是斜着的,颜色也不对,找了半天,发现是图片的问题
2 当把程序分成几个部分时,头文件的问题,以及结构体,全局变量应该怎么放,这需要注意,可以看看我是怎么做的
3 最蠢的问题,多文件编译时,一定要注意,gcc file1.c file2.c … -o xxx 文件要写全,否则会出现一大堆 函数未定义的问题 ,这不是语法,逻辑上的问题,所以怎么找也找不出来,很气人的

发布了23 篇原创文章 · 获赞 16 · 访问量 2939

猜你喜欢

转载自blog.csdn.net/qq_41861442/article/details/99757312