綜合設計——基於STC15W4K32S4(第三部分)

“所有模式功能都有啦,快快把它們聯繫起來,好激動哦!!”

3.7 模式選擇

關於模式選擇,就是一個switch函數。通過紅外遙控來更改mode的值,之後==switch(mode)==來進行對應的模式切換,不過有些模式需要初始化,所以設置了一個mode_pre來存放上一次模式的值,當mode!=mode_pre時,說明模式切換了,之後進入新模式的初始化,進行mode_pre=mode賦值操作,這樣初始化就只進行了一次,之後在進入switch(mode)就會正常的模式運行了。

定義了一些變量

u8 mode=0xff;				//當前模式
u8 mode_pre=0xff;			//上次模式

正常的模式是從mode=0開始的,單片機上電時先不進行任何模式,所以先設置成0xff。

代碼很簡單,在這裏就不畫流程圖了,直接上代碼圖片(完整代碼太長,就放最後代碼附錄裏了,下面是模式選擇的框架)
在這裏插入圖片描述

3.8 其餘的一些小模式

3.8.1 短動畫

如果放較長的動畫,單片機的存儲器不夠用,需要用SD卡,但是。。時間不夠,一切從簡,從網上找了一個短一點的動畫,更確切的是表情包,分出來的圖片只有6張。

放動畫的原理也很簡單,也就是很快的刷新圖片,根據人眼的視覺暫留效應。只要能成功顯示一張圖片,那麼動畫也就是瞬間的事了。

拍的不是很清楚,見諒撒,嘻嘻嘻!
在這裏插入圖片描述
在這裏插入圖片描述

3.8.2 顯示正弦,餘弦,中心水平垂直線、圓

這個模式純粹的就是調用LCD12864裏的函數,沒有什麼新奇的東西,具體代碼請看鏈接: LCD12864——基於STC15W5K32S4
在這裏插入圖片描述

“到這裏基本就結束啦,最後附上主函數的代碼”

3.9 主函數

#include "STC15Fxxxx.h"
#include "delay.h"
#include "LCD12864.h"
#include "picture.h"
#include "HC595.h"
#include "timer.h"
#include "remotecontrol.h"
#include "adc.h"
#include "jisuan.h"
#include "PS2.h"
#include "Tetris.h"
void main(void)
{
	u8 i=0;
	P0M1 = 0;	P0M0 = 0;	//設置爲準雙向口
	P1M1 = 0;	P1M0 = 0;	//設置爲準雙向口
	P2M1 = 0;	P2M0 = 0;	//設置爲準雙向口
	P3M1 = 0;	P3M0 = 0;	//設置爲準雙向口
	P4M1 = 0;	P4M0 = 0;	//設置爲準雙向口
	P5M1 = 0;	P5M0 = 0;	//設置爲準雙向口
	P6M1 = 0;	P6M0 = 0;	//設置爲準雙向口
	P7M1 = 0;	P7M0 = 0;	//設置爲準雙向口
	jisuaninit();
	
	HC595_Init();		//595初始化
	//DisableHC595();	//595關閉
	Timer_Init();		//定時器初始化
	ADCinit();			//ADC初始化
	
	delay_ms(100); 		//啓動等待,等LCD講入工作狀態
	LCD12864_Init(); 	//LCD初始化
	delay_ms(5); 		//延時片刻(可不要)
	PS2_Init();			//PS2初始化
	EA = 1;				//開啓總中斷
	LCD12864_Clear();	//LCD清屏
	DisplayListChar(0,1,uctech);	//顯示字庫中的中文數字
	DisplayListChar(0,2,net);		//顯示字庫中的中文數字
	DisplayListChar(0,3,mcu);		//顯示字庫中的中文
	DisplayListChar(0,4,qq);		//顯示字庫中的中文數字
	delay_ms(5000);			//延時
	delay_ms(5000);
	LCD12864_Clear();		//LCD清屏
	ShowList();				//顯示列表目錄
	while(1)
	{
		 if(B_1ms)   //1ms到
        {
            B_1ms = 0;
            if(B_IR_Press)      //檢測到收到紅外鍵碼
            {
                B_IR_Press = 0;
                RemotecontrolSwitch();
				/*****顯示接收到的紅外編碼*******/
				//要顯示紅外編碼的話要把搖桿的顯示部分註釋/
//                LED8[0] = (u8)((UserCode >> 12) & 0x0f);    //用戶碼高字節的高半字節
//                LED8[1] = (u8)((UserCode >> 8)  & 0x0f);    //用戶碼高字節的低半字節
//                LED8[2] = (u8)((UserCode >> 4)  & 0x0f);    //用戶碼低字節的高半字節
//                LED8[3] = (u8)(UserCode & 0x0f);            //用戶碼低字節的低半字節
//                LED8[6] = IR_code >> 4;
//                LED8[7] = IR_code & 0x0f;
				/*******************************/
            }
			Mode_Switch();//模式選擇函數
			Read_PS2(); //讀取PS2函數
			delay_ms(150);
			if(!PS2_RedLight())
			{
				LED8[0] = (u8)((out[7] >> 4) & 0x0f);	//左搖桿左右模擬值高半字節
				LED8[1] = (u8)(out[7]& 0x0f);			//左搖桿左右模擬值低半字節
				LED8[2] = (u8)((out[8] >> 4) & 0x0f);	//左搖桿上下模擬值高半字節
				LED8[3] = (u8)(out[8]& 0x0f);			//左搖桿上下模擬值高半字節
				LED8[4] = DIS_;
				LED8[5] = (u8)(Point_L_ShowLine & 0x0f);
				LED8[6] = DIS_;	//按鍵高半字節(右按鍵的上下左右,L1,L2,L3,R1,R2,R3)
				LED8[7] = (u8)(Point_R_ShowLine & 0x0f);			//按鍵低半字節(右按鍵的上下左右,L1,L2,L3,R1,R2,R3)
			}
			else
			{
				LED8[0] = (u8)((out[3] >> 4) & 0x0f);	//按鍵高半字節(左按鍵的上下左右)
				LED8[1] = (u8)(out[3]& 0x0f);			//按鍵低半字節(左按鍵的上下左右)
				LED8[2] = DIS_;
				LED8[3] = DIS_;
				LED8[4] = DIS_;
				LED8[5] = DIS_;
				LED8[6] = (u8)((out[4] >> 4) & 0x0f);	//按鍵高半字節(右按鍵的上下左右,L1,L2,R1,R2)
				LED8[7] = (u8)(out[4]& 0x0f);			//按鍵低半字節(右按鍵的上下左右,L1,L2,R1,R2)
			}
        }
	}
}

附錄代碼

模式選擇的代碼
/********************************
功能:模式選擇
*********************************/
void Mode_Switch(void)
{
	u8 i;
	switch(mode)
	{
		case 0://計算器
					if((B_list==1)||(mode!=mode_pre))
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;
						lie=2;
						LCD12864_Clear();
					}
					else
					{
						jisuan();//計算器函數
						break;		
					}

		case 1://遙控畫線
					if((B_list==1)||(mode!=mode_pre))
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;
						lie=3;
						LCD12864_fill_GDRAM(0x00);
						LCD12864_Clear();
						LCD12864_Circle(Tantan_x,Tantan_y,Tantan_r,0);
						Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//左搖桿座標起始點顯示
						Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//右搖桿座標起始點顯示
					}
					else
					{
						if(out[4]==0xFB)//L1
						{
							Fangxing(Point_L_x,Point_L_y,Point_L_r,0);
							Point_L_r++;
							if(Point_L_r>=6)Point_L_r=6;
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);
						}
						if(out[4]==0xFE)//L2
						{
							Fangxing(Point_L_x,Point_L_y,Point_L_r,0);
							Point_L_r--;
							if(Point_L_r<=1)Point_L_r=1;
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);
						}
						
						if(out[4]==0xF7)//R1
						{
							Point_R_ShowLine=!Point_R_ShowLine;	
							if(!Point_R_ShowLine)Jiahao(Point_R_x,Point_R_y,Point_R_r,1);
							else 
							{
								Jiahao(Point_R_x,Point_R_y,Point_R_r,0);
								LCD12864_Fill_Point(Point_R_x,Point_R_y,1);
							}
						}
						if(out[4]==0xFD)//R2
						{
							LCD12864_fill_GDRAM(0x00);//設置GDRAM
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//左搖桿座標起始點顯示
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						//左搖桿左右
						i=PS2_AnologData(7);//讀取一次左搖桿左右的模擬值(out[7]中)0~255  
						//(模擬值小於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						if((i<=0x40)||(out[3]==Left_L))
						{
							Fangxing(Point_L_x,Point_L_y,Point_L_r,0);//上次的點滅掉
							
							Point_L_x--;
							if(Point_L_x<Point_L_r)Point_L_x=Point_L_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						//(模擬值大於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						else if((i>=0xBF)||(out[3]==Right_L))
						{
							Fangxing(Point_L_x,Point_L_y,Point_L_r,0);//上次的點滅掉
							
							Point_L_x++;
							if(Point_L_x>(127-Point_L_r))Point_L_x=127-Point_L_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						//右搖桿左右
						i=PS2_AnologData(5);//讀取一次右搖桿左右的模擬值(out[5]中)0~255 
						//(模擬值小於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						if((i<=0x40)||(out[4]==Left_R))
						{
							if(!Point_R_ShowLine) Jiahao(Point_R_x,Point_R_y,Point_R_r,0);//上次的點滅掉
							
							Point_R_x--;
							if(Point_R_x<Point_R_r)Point_R_x=Point_R_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
							
						}
						//(模擬值大於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						else if((i>=0xBF)||(out[4]==Right_R))
						{
							
							if(!Point_R_ShowLine) Jiahao(Point_R_x,Point_R_y,Point_R_r,0);//上次的點滅掉
							
							Point_R_x++;
							if(Point_R_x>(127-Point_R_r))Point_R_x=127-Point_R_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						//左搖桿上下
						i=PS2_AnologData(8);//讀取一次左搖桿上下的模擬值(out[7]中)0~255 
						//(模擬值小於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						if((i<=0x40)||(out[3]==Up_L))
						{
							Fangxing(Point_L_x,Point_L_y,Point_L_r,0);//上次的點滅掉
							
							Point_L_y--;
							if(Point_L_y<Point_L_r)Point_L_y=Point_L_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						//(模擬值大於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						else if((i>=0xBF)||(out[3]==Down_L))
						{
							Fangxing(Point_L_x,Point_L_y,Point_L_r,0);//上次的點滅掉
							
							Point_L_y++;
							if(Point_L_y>(63-Point_L_r))Point_L_y=63-Point_L_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						//右搖桿上下
						i=PS2_AnologData(6);//讀取一次右搖桿上下的模擬值(out[6]中)0~255  
						//(模擬值小於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						if((i<=0x40)||(out[4]==Up_R))
						{
							if(!Point_R_ShowLine) Jiahao(Point_R_x,Point_R_y,Point_R_r,0);//上次的點滅掉
							
							Point_R_y--;
							if(Point_R_y<Point_R_r)Point_R_y=Point_R_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						//(模擬值大於自己定的值)|| (左按鍵(out[3]中)的值==PS2中規定的值)
						//關於out,模擬值的定義在PS2.c中
						else if((i>=0xBF)||(out[4]==Down_R))
						{
							if(!Point_R_ShowLine) Jiahao(Point_R_x,Point_R_y,Point_R_r,0);//上次的點滅掉
							
							Point_R_y++;
							if(Point_R_y>(63-Point_R_r)) Point_R_y=63-Point_R_r;
							
							Fangxing(Point_L_x,Point_L_y,Point_L_r,1);//刷新點
							if(Point_R_ShowLine)
								Jiahao(Point_R_x,Point_R_y,0,1);//刷新點
							else
								Jiahao(Point_R_x,Point_R_y,Point_R_r,1);//刷新點
						}
						break;
					}

		case 2://彈一彈
					if((B_list==1)||(mode!=mode_pre))//第一次進入當前模式
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;
						lie=4;//列表箭頭指向當前模式
						i=TL0;//獲取當前定時器的值,作爲僞隨機數
						Tantan_x=(u8)( i & 0x7f);//獲取定時器的後7位作爲圓的起始橫座標x
						Tantan_y=(u8)( i & 0x3f);//獲取定時器的後6位作爲圓的起始縱座標y
						Tantan_r=(u8)( i & 0x07);//獲取定時器的後3位作爲圓的半徑r
						Tantan_dx=(u8)( i & 0x01);//獲得起始橫座標移動方向dx
						Tantan_dy=(u8)( (i>>1) & 0x01);//獲得起始縱座標移動方向dy
						if(!Tantan_dx)Tantan_dx=-1;//左方向-1
						if(!Tantan_dy)Tantan_dy=-1;//上方向-1
						if(Tantan_r==0) Tantan_r=1;//確保半徑最小爲1
						if(Tantan_x<=Tantan_r) Tantan_x=Tantan_r+1;//防止初始圓被邊界錯位
						else if(Tantan_x>=127-Tantan_r)Tantan_x=127-Tantan_r-1;//防止初始圓被邊界錯位
						if(Tantan_y<=Tantan_r) Tantan_y=Tantan_r+1;//防止初始圓被邊界錯位
						else if(Tantan_y>=63-Tantan_r)Tantan_y=63-Tantan_r-1;//防止初始圓被邊界錯位
						LCD12864_Clear();//清屏
						LCD12864_fill_GDRAM(0x00);//清除GDRAM
						LCD12864_Circle(Tantan_x,Tantan_y,Tantan_r,1);//顯示初始圓
						break;
					}
					else//第二次以及以後進入模式
					{
						LCD12864_Circle(Tantan_x,Tantan_y,Tantan_r,0);//清除上次的圓
						if(Tantan_x<=Tantan_r) Tantan_dx=1;//碰到邊界座標移動方向變爲相反
						else if(Tantan_x>=127-Tantan_r)Tantan_dx=-1;
						if(Tantan_y<=Tantan_r) Tantan_dy=1;
						else if(Tantan_y>=63-Tantan_r)Tantan_dy=-1;
						Tantan_x+=Tantan_dx;//更新座標
						Tantan_y+=Tantan_dy;
						LCD12864_Circle(Tantan_x,Tantan_y,Tantan_r,1);//顯示當前圓
						break;
					}
		case 3://俄羅斯方塊
					if((B_list==1)||(mode!=mode_pre))
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;
						lie=5;//列表箭頭指向當前模式
						LCD12864_Clear();//清屏
						LCD12864_fill_GDRAM(0x00);//清除GDRAM
						LCD12864_Clear();//清屏
						SysFlag=0;						
						KeyCode=0;
						Score=0;
						SysFlag^=1<<PAUSEFLAG;//開啓時暫停
						Game_Init();//遊戲初始化
						DrawBoard();//畫界面
						break;
					}
					else 
					{
						GamePlay();//遊戲進行
						break;	
					}
		case 4://動畫
					if((B_list==1)||(mode!=mode_pre))
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;
						picture_num=0;//第0張圖片
						LCD12864_Clear();//清屏
						DisplayImage(gImage1[picture_num]);//顯示第picture_num張圖片
						break;
					}
					else
					{
						picture_num++;//更新當前圖片數
						if(picture_num>=6)picture_num=0;//圖片數復位
						
						DisplayImage(gImage1[picture_num]);//顯示第picture_num張圖片
						break;
					}
		case 5://正弦,餘弦,中心水平垂直線、圓
					if((B_list==1)||(mode!=mode_pre))
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;
						LCD12864_Clear();//清屏
						LCD12864_fill_GDRAM(0x00);//清除GDRAM
						LCD12864_Circle(64,32,30,1);//畫圓
						LCD12864_Verticalline(63,0,63,1);//畫垂線
						LCD12864_Horizontalline(0,127,31,1);//畫水平線
						LCD12864_fsin();//畫正弦波
						LCD12864_fcos();//畫餘弦波
						break;
					}
					else break;	
		case 6:
					if((B_list==1)||(mode!=mode_pre))
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;
						break;
					}
					else break;
		case 7:
					if((B_list==1)||(mode!=mode_pre))
					{
						B_list=0;//清除列表標誌位
						mode_pre=mode;
						cmode=mode;

						break;
					}
					else break;
		case 8:		break;
		case 9:		break;
		default:break;	
	}
}
短動畫和波形顯示代碼

這些代碼分別在上面Mode_Switch中的case 4,case 5中。

“完成啦!慶賀吧!!”

“其餘部分在這裏哦”

綜合設計——基於STC15W5K32S4(第一部分)

綜合設計——基於STC15W5K32S4(第二部分)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章