演示程序之打游戏 -- 慕司板IAP15
2017-08-03 08:20
218 查看
上位机和协议制定我的大学舍友(他的微博:http://weibo.com/lesshst?
topnav=1&wvr=5&topsug=1)毕业前百忙之中使用Python花了一个下午完毕的,先对他表示谢意。
演示视频例如以下:
http://v.youku.com/v_show/id_XODExMjY3ODY0.html
以下介绍演示程序的使用步骤:
①把慕司板演示程序下载进“慕司板”中,右边的摇杆拨到上面。
②打开lizhibo目录下的config.ini文件,改动串口号和波特率。
③打开浏览器的魂斗罗游戏界面:http://www.4399.com/flash/59630_2.htm
或者超级玛丽: http://www.3366.com/flash/69976.shtml
![](http://img.blog.csdn.net/20160403140909929)
慕司板打游戏事实上就是串口虚拟电脑键盘。
④打开http://www.cnblogs.com/longfan/articles/1841136.html
查看上图中WASDJKFH几个按键相应的键值
87 W 上 按键1
65 A 左 按键2
68 D 右 按键3
83 S 下(文中写错了)按键4
74 J 射击 按键6
75 K 跳跃 按键7
70 F 选择 按键5
72H 跳跃 按键10
假设须要双人游戏,再插上一个慕司板。改动config.ini的串口号,波特率。键值(上下左右?>)执行软件就可以。
附上main.c代码:
interrup.c代码:
完整project參见资源汇总帖.
原作于 2014年10月
CSDN发表于2016年4月
weifengdq
topnav=1&wvr=5&topsug=1)毕业前百忙之中使用Python花了一个下午完毕的,先对他表示谢意。
演示视频例如以下:
http://v.youku.com/v_show/id_XODExMjY3ODY0.html
以下介绍演示程序的使用步骤:
①把慕司板演示程序下载进“慕司板”中,右边的摇杆拨到上面。
②打开lizhibo目录下的config.ini文件,改动串口号和波特率。
③打开浏览器的魂斗罗游戏界面:http://www.4399.com/flash/59630_2.htm
或者超级玛丽: http://www.3366.com/flash/69976.shtml
慕司板打游戏事实上就是串口虚拟电脑键盘。
④打开http://www.cnblogs.com/longfan/articles/1841136.html
查看上图中WASDJKFH几个按键相应的键值
87 W 上 按键1
65 A 左 按键2
68 D 右 按键3
83 S 下(文中写错了)按键4
74 J 射击 按键6
75 K 跳跃 按键7
70 F 选择 按键5
72H 跳跃 按键10
假设须要双人游戏,再插上一个慕司板。改动config.ini的串口号,波特率。键值(上下左右?>)执行软件就可以。
附上main.c代码:
/************************************************************************************** 作 者:weifengdq(新浪微博:weifengdq) 注意事项:按ALT+F7 配置->Target->Memory Mode->Large:variables in XDATA,假设须要用到仿真, Debug中设置好仿真和串口号; 初始化有液晶背光调节演示。须要把P19的跳线帽插到上面,使LCD背光引脚与P26相连,使 用PWM1来调节液晶背光亮度; 使用串口1的1通道发送数据打游戏:在lkb.h中添加了KEYMSG结构体 mpu6050.c中Accel_x、Accel_y、Accel_z升为全局变量,添加; Accel_y = (float)GetData(ACCEL_YOUT_H)/286.0f; //读取Y轴加速度 ADC初始化把AD採样时间改小了 改动日期:2014/10/17 *************************************************************************************/ #include "config0.h" #include "delay.h" #include "lkb.h" #include "timer.h" #include "uart.h" #include <stdio.h> #include "lcd.h" #include "adc.h" #include "mpu6050.h" #include "image0.h" #include "pca_pwm.h" #include "hmc5883l.h" #include "nrf24l01.h" #include <math.h> #include "int.h" unsigned int adc0,adc1,adc2,adc3,adc4; float li_voltage=0; KEYMSG left; KEYMSG right; KEYMSG up; KEYMSG down; KEYMSG kb; KEYMSG a_jump; //跳跃 KEYMSG a_shoot;//射击 KEYMSG a_left; KEYMSG a_right; void Encoder_Task(); void MPU6050_Task(); void HMC5883_Task(); void KEY_Task(); void ADC_Task(); void Encoder_Task() { LCD_Show2Num(0,112,Freq,6); printf("%d\n",Cnt_Now); } void MPU6050_Task() { static unsigned int j=0; Angle_Calcu(); //倾角计算 将得到以下两个全局变量,使用了网上摘抄的卡尔曼滤波 //float Angle; //终于倾斜角度 //float Gyro_y; //Y轴角速度 if(Accel_x >=20 && Accel_x<=90) { sendMsg(&a_jump, 7, 1); } else if(Accel_x >=-90 && Accel_x<=-20) { sendMsg(&a_shoot, 6, 1); } else { if(a_jump.msg == 1) { sendMsg(&a_jump, 7, 0); } else if(a_shoot.msg == 1) { sendMsg(&a_shoot, 6, 0); } } if(Accel_y >=20 && Accel_y<=90) { sendMsg(&a_right, 3, 1); } else if(Accel_y >=-90 && Accel_y<=-20) { sendMsg(&a_left, 2, 1); } else { if(a_right.msg == 1) { sendMsg(&a_right, 3, 0); } else if(a_left.msg == 1) { sendMsg(&a_left, 2, 0); } } //printf("%.2f,%.2f\n",Angle,Gyro_y); j++; if(j>=240) { j=0; LCD_Fill(0,140,239,318,Black); POINT_COLOR = Red; BACK_COLOR=Black; LCD_DrawLine(0,229,239,229); POINT_COLOR = Green; } if((int)Angle>-90 && (int)Angle<90 ) //排除初始不稳定杂波 { LCD_DrawPoint(j,229-(int)Angle); //通过NRF24L01发送出去 if(Angle>=0) { Tx_Buf[2] = '+'; Tx_Buf[3] =(unsigned char)Angle; } else { Tx_Buf[2] = '-'; Tx_Buf[3] = (unsigned char)(Angle*(-1)); } Transmit(Tx_Buf); //24L01发送缓冲数组 sta=SPI_Read(READ_REG + STATUS); //读24L01的状态寄存器 if(TX_DS) //sbit TX_DS =sta^5;数据发送完毕中断。接收到应答信号时此位置1,写1清除中断 { //Delay_ms(5); SPI_RW_Reg(WRITE_REG + STATUS,sta); //写状态寄存器,清除中断 } if(MAX_RT) //假设是发送超时 sbit MAX_RT =sta^4; { //达到最多次重发中断,MAX_RT中断产生则必须清除后系统才干进行通讯,写1清除中断 //Delay_ms(5); SPI_RW_Reg(WRITE_REG + STATUS,sta); } } } void HMC5883_Task() { //static unsigned int m=0; static float Last_HMC5883_Angle=0; // float Avg_HMC5883_Angle=0; // float Last_Avg_HMC5883_Angle=0; // float temp_HMC5883_Angle=0; Multiple_Read_HMC5883(); //角度的变化似乎并非线性的 LCD_Show2Num(32,80,(int)HMC5883_Angle,3); POINT_COLOR=BACK_COLOR; //三角函数使用弧度而不是度! LCD_DrawLine(120,100,120+(int)(28.0*cos((Last_HMC5883_Angle-180.0)/57.3)),100+(int)(28.0*sin((Last_HMC5883_Angle-180.0)/57.3))); POINT_COLOR=Yellow; LCD_DrawLine(120,100,120+(int)(28.0*cos((HMC5883_Angle-180.0)/57.3)),100+(int)(28.0*sin((HMC5883_Angle-180.0)/57.3))); Last_HMC5883_Angle=HMC5883_Angle; // //平均值滤波 // m++; // temp_HMC5883_Angle+=HMC5883_Angle; // if(m==5) // { // m=0; // Avg_HMC5883_Angle=temp_HMC5883_Angle/5.0; //与前面四个值相关联 // //printf("\n\n%.2f\n\n",HMC5883_Angle); //HMC5883_Angle: float型。0~360 // LCD_Show2Num(32,80,(int)Avg_HMC5883_Angle,3); // POINT_COLOR=BACK_COLOR; // LCD_DrawLine(120,100,120+28*cos((Last_Avg_HMC5883_Angle-180.0)/57.3),100+28*sin((Last_Avg_HMC5883_Angle-180.0)/57.3)); // POINT_COLOR=Yellow; // LCD_DrawLine(120,100,120+28*cos((Avg_HMC5883_Angle-180.0)/57.3),100+28*sin((Avg_HMC5883_Angle-180.0)/57.3)); // Last_Avg_HMC5883_Angle=Avg_HMC5883_Angle; // } } void ADC_Task() { static unsigned int i=0; static unsigned int k=0; POINT_COLOR= Green; i++; switch(i) { case 1: adc0=(int)ADC_GetResult(0);LCD_Show2Num(48,0,adc0,3); break; case 2: adc1=(int)ADC_GetResult(1);LCD_Show2Num(48,16,adc1,3); break; case 3: adc2=(int)ADC_GetResult(2);LCD_Show2Num(168,0,adc2,3); break; case 4: adc3=(int)ADC_GetResult(3);LCD_Show2Num(168,16,adc3,3); break; case 5: li_voltage=(float)ADC_GetResult(4)*0.019f; break; //adc4*3.3/256*(6.8+3.3)/6.8=adc4*0.019 default: i=0; LCD_Show2Num(96,32,(int)li_voltage,1); //显示整数部分 LCD_Show2Num(112,32,((int)(li_voltage*100))%100,2); //显示小数部分 //printf("%d,%d,%d,%d,%.2f\n",adc0,adc1,adc2,adc3,li_voltage); }//switch 结束 k++; //printf("%d,%d,", adc1, adc0); if(k%2) { if(adc1>=0 && adc1<=80) { sendMsg(&up, 1, 1); } else if(adc1>=170 && adc1<=255) { sendMsg(&down, 4, 1); } else { if(up.msg == 1) { sendMsg(&up, 1, 0); } else if(down.msg == 1) { sendMsg(&down, 4, 0); } } } else { if(adc0>=0 && adc0<=80) { sendMsg(&left, 3, 1); } else if(adc0>=170 && adc0<=255) { sendMsg(&right, 2, 1); } else { if(left.msg == 1) { sendMsg(&left, 3, 0); } else if(right.msg == 1) { sendMsg(&right, 2, 0); } } } } //void KEY_Task() //{ // if (key_up==0) // { // sendMsg(&kb, Key_Num, 1); //sendMsg()函数里面有printf // } // else //if(key_up == 1) // { // // if (kb.msg == 1) ; // sendMsg(&kb, kb.key, 0); // } // //printf("%d\n",Key_Num); //} /*能够使用单步仿真一步步查看效果*/ void main() { unsigned int i; Delay_ms(10); Delay_us(10); PWM2=0; //电机制动。能够下拉10k设置引脚为推挽制动 /*2.2寸、320*240分辨率、SPI接口的LCD初始化,使用STC的硬件SPI,LCD驱动芯片为ILI9340C*/ LCD_LED=0; //LCD背光最亮 SPI_Init(); //IAP15硬件SPI初始化,切换到了SPI的第二通道:SS/P24、MOSI/P23、MISO/P22、SCK/P21 LCD_Init(); //LCD初始化,厂家提供 /*LCD休眠演示*/ LCD_Sleep(); //LCD进入休眠状态 Delay_ms(100); LCD_ExitSleep();//LCD退出休眠状态 /*LCD刷屏演示:红橙黄绿青蓝紫 白黑*/ LCD_Clear(Red); LCD_Clear(Orange); LCD_Clear(Yellow); LCD_Clear(Green); LCD_Clear(Cyan); LCD_Clear(Blue); LCD_Clear(Purple); LCD_Clear(White); LCD_Clear(Black); /*LCD画线、英文、汉字、数字显示測试*/ /*液晶屏左上角坐标为(0,0),右下角坐标为(239,319)*/ POINT_COLOR=Green; //全局变量 BACK_COLOR=Black; //前景色相似于在黑板写字的各种颜色的粉笔。黑板的颜色就是背景色 LCD_ShowString(0,0,"Hello,world!"); //从(0,0)坐标開始显示字符串“Hello,World!” POINT_COLOR=Blue; //能够随时更改画笔颜色,显示不同颜色的数字 LCD_DrawLine(100,0,240,15); //画一条线段。起始坐标(100,0),终点坐标(240,15) LCD_Show2Num(0,16,65535,5); //从(0,16)坐标開始显示0~65535的数字,5为数字位数,即显示5位数字 LCD_ShowNum(100,16,987654321,9); //从(100,16)坐标開始显示unsigned long型数字(0~4294967295),10为数字位数。即10位数字 POINT_COLOR=Yellow; for(i=32;i<320;i+=16) { LCD_ShowString(0,i,"abcdefghijklmnopqrstuvwxyz!"); } LCD_LED=1; //LCD背光关闭 Delay_ms(500); LCD_LED=0; //LCD背光最亮 Delay_ms(500); LCD_Clear(Black); //清屏:黑色 //LCD_Fill(120,120,160,160,Yellow); //在矩形区域填充色块。在函数处按F12能够查看函数原型 LCD_ShowImage(gImage_musi,80,120,78,80);//显示彩色图像: 慕司LOGO Delay_ms(2000); LCD_Clear(Black); POINT_COLOR=Red; LCD_DrawRectangle(0,0,239,60); //画矩形:对角坐标(左上、右下)为(0,0),(239,60) POINT_COLOR=Purple; LCD_ShowString(80,2,"慕司"); //显示16*16汉字 LCD_ShowString(16,22,"为一线微茫憧憬一意孤行,"); LCD_ShowString(8,42,"这众生芸芸谁不曾如此任性!"); POINT_COLOR=Cyan; LCD_ShowGB3232(80,160,"青春"); POINT_COLOR=Green; LCD_DrawCircle(112,176,48); Delay_ms(500); PCA_PWM_Init(); //PWM初始化。切换到PWM的第三通道P25/P26/P27,这里仅使用了PWM1(P26,即LCD_LED引脚) LCD_LED=0; //LCD背光最亮 for(i=255;i<=0;i--) //液晶背光256级亮度调节演示:由亮到暗 { CCAP1H = CCAP1L = i; //通过调节占空比来调节屏幕亮度 Delay_ms(20); } LCD_LED=1; //LCD背光关闭 for(i=0;i<255;i++) //液晶背光256级亮度调节演示:由暗到亮 { CCAP1H = CCAP1L = i; //通过调节占空比来调节屏幕亮度 Delay_ms(20); } Delay_ms(1000); LCD_Clear(Black); LKB_Init(); //LED Key Buzzer:LED、按键、蜂鸣器 初始化(设置蜂鸣器port为推挽输出) Buzzer_Func(500,1000); //蜂鸣器500Hz@1000ms ADC_Init(); //AD初始化:设置P1的0 1 2 3(摇杆)4(锂电池电压)口为AD口。 POINT_COLOR = Green; //液晶屏画笔颜色 BACK_COLOR=Black; //背景色 LCD_ShowString(0,0 ,"adc0: "); LCD_ShowString(0,16,"adc1: "); LCD_ShowString(120,0,"adc2: "); LCD_ShowString(120,16,"adc3: "); LCD_ShowString(0,32,"li_voltage: V"); LCD_ShowString(104,32,"."); NRF24L01_Init(); TX_Mode(); //发送模式 LCD_ShowString(0,48,"NRF24L01_State: Tx_Mode"); MPU6050_Init(); Delay_ms(100); POINT_COLOR = Red; LCD_DrawLine(0,319,239,319); LCD_DrawLine(0,139,239,139); LCD_DrawLine(0,229,239,229); HMC5883_Init(); Delay_ms(100); POINT_COLOR = Green; LCD_DrawCircle(120,100,31); LCD_ShowString(0,64,"direction:"); LCD_ShowString(0,96,"speed:"); Timer_Init(100); //每10ms中断一次,參数为百us:100*100us = 10ms UART_Init(115200); //串口初始化。使用了串口1的第一通道,设置波特率115200。用于仿真时能够切换到第二通道P36/P37 TI=1; SBUF=0; //这一句使用printf有时是必须的 INT_Init(); while(1) { if(LED_flag) //每1s切换一次LED的状态 {LED_flag=0;LED1 = ~LED1;} if(ADC_flag) {ADC_flag=0;ADC_Task();} if(adc2 >=80 && Encoder_flag) //使用adc2作开关 { Encoder_flag=0; CCAP2H = CCAP2L = (adc3 - 10)*2; //使用摇杆的ADC3调节电机转速 Encoder_Task(); } else if(adc2 <=70) { if(MPU6050_flag) //MPU6050的几个函数使用了Delay_us(5) {MPU6050_flag=0;MPU6050_Task();} if(HMC5883_flag) {HMC5883_flag=0;HMC5883_Task();} //interrupt.c中把Key_Scan()改成支持连按 //uart.c中把串口1切换回P30/P31 if(KEY_flag) { // KEY_Task(); if (key_up==0) { sendMsg(&kb, Key_Num, 1); //sendMsg()函数里面有printf } else //if(key_up == 1) { KEY_flag=0; if (kb.msg == 1) ; sendMsg(&kb, kb.key, 0); } //printf("%d\n",Key_Num); } } else {;} } }
interrup.c代码:
#include "config0.h" #include "lkb.h" bit LED_flag=0; bit BEEP_flag=0; bit KEY_flag=0; bit ADC_flag=0; bit MPU6050_flag=0; bit HMC5883_flag=0; bit Encoder_flag=0; bit Rotate_Dir=0; //用于推断编码器旋转方向 int Cnt_Last; //记录上一次的捕获值 int Cnt_Now=500; //记录本次的捕获值 unsigned int Freq=0; //仅作參考。并未使用 void exint0() interrupt 0 using 2 //INT0中断入口 { //先推断转向 if(B_Phase) //假设B相脉冲为正电压。表示正转 { Rotate_Dir=1; Cnt_Now++; if(Cnt_Now>=1000) Cnt_Now=0; Cnt_Last=Cnt_Now; } else { Rotate_Dir=0; Cnt_Now--; if(Cnt_Now<=0) Cnt_Now=1000; } } //外部中断2服务程序 //void exint2() interrupt 10 //INT2中断入口 (下降沿) //{ // //先推断转向 // if(B_Phase) //假设B相脉冲为正电压,表示正转 // { // Rotate_Dir=1; // Cnt_Now++; // if(Cnt_Now>=1000) Cnt_Now=0; // Cnt_Last=Cnt_Now; // } // else // { // Rotate_Dir=0; // Cnt_Now--; // if(Cnt_Now<=0) Cnt_Now=1000; // } // //// INT_CLKO &= 0xEF; //若须要手动清除中断标志,可先关闭中断,此时系统会自己主动清除内部的中断标志 //// INT_CLKO |= 0x10; //然后再开中断就可以 //} /********************************************* * Timer0中断服务程序 *********************************************/ void tm0_isr() interrupt 1 using 1 //10ms中断一次 { static unsigned int i=0; //用于LED static unsigned int j=0; //用于蜂鸣器 static unsigned int k=0; //用于MPU6050 // static unsigned int m=0; //用于HMC5883L static unsigned int n=0; //用于ADC static unsigned int p=0; //用于编码器 //使用Aslong的JGA25-371直流减速电机:334线编码器,减速比为 21.3,12V额定电压。额定转速201rpm //那么额定转速下10ms输出脉冲数:201*21.3*334/60/100=238.3257个脉冲 unsigned char ch,cl; static unsigned int temp=0; static unsigned int temp_1=0; //上次的值 cl=TL1; //先读低位(高位变得没那么快) ch=TH1; temp_1=temp; temp=ch*256+cl; //用左移怎么实现? ch<<8+cl //if(temp>=temp_1) Freq=(temp-temp_1)/5; // *200/1000 kHz //20kHz 每5ms 计100个数 //else Freq=(65536-temp_1 + temp)/5; if(temp>=temp_1) Freq=(temp-temp_1)*100; //1s的脉冲数,即频率 else Freq=(65536-temp_1 + temp)*100; p++; if(p>=1) { p=0; Encoder_flag=1; } i++; if(i>=100) { i=0; LED_flag=1; } Key_Scan(1,1); //支持连按;按键消抖时间,10ms if(Key_Num) { //if(Key_Num==10) BEEP_flag=1; //按键10按下。蜂鸣器鸣响 KEY_flag=1; } if(BEEP_flag) { j++; BEEP=~BEEP; //10ms翻转一次,50Hz if(j>10) //响100ms { j=0; BEEP_flag=0; BEEP=0; //关闭蜂鸣器 } } k++; if(k%2) //10ms採样一次 { //k=0; MPU6050_flag=1; } else HMC5883_flag=1; // m++; // if(m>=1) // { // m=0; // HMC5883_flag=1; // } n++; if(n>=1) //ad: 10ms採样一次 { n=0; ADC_flag=1; } }
完整project參见资源汇总帖.
原作于 2014年10月
CSDN发表于2016年4月
weifengdq
相关文章推荐
- 演示程序之打游戏 -- 慕司板IAP15
- 例程3. 串口 -- 慕司板IAP15
- 2维游戏图像处理基类演示程序的制作。
- 序 -- 慕司板IAP15
- 例程5. ADC -- 慕司板IAP15
- 例程6. MPU6050工程变量超出data区的解决办法 -- 慕司板IAP15
- 软件安装与仿真设置 -- 慕司板IAP15
- 例程7. HMC5883工程说明 -- 慕司板IAP15
- 游戏.灯光演示程序
- 例程8. PCA_PWM -- 慕司板IAP15
- 例程9. NRF24L01工程说明 -- 慕司板IAP15
- 慕司板编程说明 -- 慕司板IAP15
- Struts Flow 的猜数字游戏演示程序
- 例程1. LKB -- 慕司板IAP15
- [OpenGL - 游戏开发] 仿制《Minecraft/我的世界》 - 总结及演示程序
- 源码 -- Cocoachina游戏特效大赛 – cocos2d/cocos2dx 演示程序
- Java多区域部署时能自动升级的一个小演示程序
- 摄像头游戏引擎测试程序下载
- Python程序,辅助微信跳一跳游戏介绍
- IAP(程序内购买): 完全攻略