软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 开发杂谈 -> 演示程序之打游戏 -> 正文阅读

[开发杂谈]演示程序之打游戏


上位机和协议制定我的大学舍友(他的微博: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
[img]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代码:
/**************************************************************************************
作    者: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、按键、蜂鸣器 初始化(设置蜂鸣器端口为推挽输出)
    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;
    }

}

完整工程参见资源汇总帖.
原作于 2014年10月
CSDN发表于2016年4月
weifengdq
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-03 20:46:48  
开发杂谈 最新文章
BloomFilter
大学四年编程之历程
内核分析
造人论坛——意识的本质和一个人工脑模型
OFDM信号[matlab描述]
人类还会进化吗?
HDUACM1035RobotMotion简单模拟题
树、二叉树(二)
iisphpweb.config处理404,500等,跳转友好
DatabaseAsaFortress
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年1日历
2018-1-20 7:31:33
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --