重力感应贪吃蛇(C51 MPU6050 8*8LED点阵)

本文讲述如何从无到有用C51做一个重力感应的贪吃蛇,包括元件选型、原理图PCB绘制和代码编写。

  • 重力感应贪吃蛇(C51 MPU6050 8*8LED点阵)

    • 所需元件及其选型
    • 原理图绘制
      • C51外围电路
      • 复位晶振电路
      • USB下载电路/电源电路
      • MPU6050插座电路
    • 代码部分
      • 驱动程序
      • 贪吃蛇算法部分

所需元件及其选型

元件 封装 数量
89C52 双列直插DIP40 1
MPU6050 8引脚(实际只用到4个) 1
8*8LED点阵屏 18引脚(2个起固定作用) 1
74HC595 贴片SOP16 1
CH340 贴片SOP16 1
12M晶振 HC-49S 2
USB母座 6脚(USB-A) 1
排阻10k 0603 8P4R 4
电阻10k 贴片0603 2
电阻33R 贴片0603 2
电阻47k 贴片0603 1
电阻4.7k 贴片0603 1
电容22P 贴片0603 3
电容33P 贴片0603 2
电容103 贴片0603 1
电容104 贴片0603 2
电解电容10u 插件 1
电解电容470u 插件 1
SS14肖特基二极管 SMA 1
A1SHB SOT-23 1
贴片LED 0603 1
轻触开关 6*6*5 1
按钮开关 8*8 1

原理图绘制

C51外围电路


//上拉电阻画得比较丑,大家意会一下。。。

复位晶振电路

USB下载电路/电源电路


实不相瞒,最难的这部分电路是从网上抄的- -

MPU6050插座电路

代码部分

驱动程序

  • IIC&MPU6050

这个比较简单的,网上有很多资料,不赘述。
拿P1的0和1做IIC通信的时钟线和数据线,配置一下MPU6050的寄存器:

sbit SCL=P1^0;
sbit SDA=P1^1;#define SMPLRT_DIV      0x19
#define CONFIG          0x1A
#define GYRO_CONFIG     0x1B
#define ACCEL_CONFIG    0x1C
#define ACCEL_XOUT_H    0x3B
#define ACCEL_XOUT_L    0x3C
#define ACCEL_YOUT_H    0x3D
#define ACCEL_YOUT_L    0x3E
#define ACCEL_ZOUT_H    0x3F
#define ACCEL_ZOUT_L    0x40
#define TEMP_OUT_H      0x41
#define TEMP_OUT_L      0x42
#define GYRO_XOUT_H     0x43
#define GYRO_XOUT_L     0x44
#define GYRO_YOUT_H     0x45
#define GYRO_YOUT_L     0x46
#define GYRO_ZOUT_H     0x47
#define GYRO_ZOUT_L     0x48
#define PWR_MGMT_1      0x6B
#define WHO_AM_I        0x75
#define SlaveAddress    0xD0

延时5秒IIC要用,写得精确点:

void Delay5us()
{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}

IIC通信的相关函数:

void I2C_Start()
{ SDA = 1; SCL = 1;Delay5us(); SDA = 0;Delay5us(); SCL = 0;
}void I2C_Stop()
{ SDA = 0; SCL = 1;Delay5us(); SDA = 1;Delay5us();
}void I2C_SendACK(bit ack)
{ SDA = ack; SCL = 1;  Delay5us(); SCL = 0;   Delay5us();
}bit I2C_RecvACK()
{ SCL = 1;                    Delay5us();                  CY = SDA;                    SCL = 0;                    Delay5us();                 return CY;
}void I2C_SendByte(uchar dat)
{uchar i;for (i=0; i<8; i++)         {dat <<= 1;               SDA = CY;                SCL = 1;                Delay5us();              SCL = 0;                Delay5us();             }I2C_RecvACK();
}uchar I2C_RecvByte()
{uchar i;uchar dat = 0; SDA = 1;                    for (i=0; i<8; i++)         {dat <<= 1; SCL = 1;                Delay5us();             dat |= SDA;                             SCL = 0;                Delay5us();             }return dat;
}void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{I2C_Start();                  I2C_SendByte(SlaveAddress);   I2C_SendByte(REG_Address);    I2C_SendByte(REG_data);       I2C_Stop();
}uchar Single_ReadI2C(uchar REG_Address)
{uchar REG_data;I2C_Start();                   I2C_SendByte(SlaveAddress);    I2C_SendByte(REG_Address);      I2C_Start();                   I2C_SendByte(SlaveAddress+1);  REG_data=I2C_RecvByte();       I2C_SendACK(1);                I2C_Stop();                    return REG_data;
}

MPU6050相关函数:

void InitMPU6050()
{Single_WriteI2C(PWR_MGMT_1, 0x00);Single_WriteI2C(SMPLRT_DIV, 0x07);Single_WriteI2C(CONFIG, 0x06);Single_WriteI2C(GYRO_CONFIG, 0x18);Single_WriteI2C(ACCEL_CONFIG, 0x01);
}int GetData(uchar REG_Address)
{uchar H,L;H=Single_ReadI2C(REG_Address);L=Single_ReadI2C(REG_Address+1);return (H<<8)+L;
}
  • 74HC595&LED点阵

定义接口:

sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^4;

595串转并函数:

void HC595SendByte(unsigned char dat)
{unsigned char a;SRCLK=0;RCLK=0;for(a=0;a<8;a++){SER=dat>>7;dat<<=1;SRCLK=1;_nop_();_nop_();SRCLK=0;    }RCLK=1;_nop_();_nop_();RCLK=0;
}

贪吃蛇算法部分

  • 数据结构
    由于51内存很有限,LED点阵还需要时刻进行扫描,MPU6050还要进行通信,要尽量节约时间和空间。本文并没有使用二维数组,而是使用一个一维数组表示蛇的信息,每个元素从头至尾,前半个字节表示横坐标,后半个字节表示纵坐标。实物也是这样存储,只需要一个uchar。

宏定义如下:

#define COMMONPORTS P0
#define UP    0x00
#define DOWN  0x01
#define LEFT  0x02
#define RIGHT 0x03

全局变量如下:

unsigned char code TAB[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//scan 8*8 LED columnunsigned char snake[40] = {0x34}; //initial position
unsigned char food = 0x33;
unsigned char refresh = 0; //determine whether to refresh
unsigned char len = 1; //the length of snake
unsigned char dir = DOWN; // direction
unsigned char map[8] = {0,0,0,0,0,0,0,0}; //scan 8*8 LED row
unsigned char isalive = 1; // determine game over or not
static int ts; // timer

其中TAB是8*8LED点阵屏的列扫描,map是一个长度为8的数组,记录每一列上8个LED的亮灭。

  • 整体思路:

先放个主函数压压惊:

void main()
{unsigned char tab;InitMPU6050();Timer0Init();while(1){while(!refresh){for(tab=0;tab<8;tab++){HC595SendByte(0x00);COMMONPORTS = TAB[tab];HC595SendByte(map[tab]);}}refresh = 0;get_dir();snake_move();if(!isalive){ET0 = 0;continue;}print_game();}
}

思路很简单,根本不需要解释。

  • 工具函数tran()
void tran(unsigned char num,unsigned char *x, unsigned char *y)
{*x = num >> 4;*y = (unsigned char)(num << 4) >> 4;
}

这个函数就是用来把一个字节拆成两半,分别代表横坐标和纵坐标。

  • 定时器:1s刷新一次屏幕
void Timer0Init()
{TMOD|=0X01;TH0=0XFC;TL0=0X18;   ET0=1;EA=1;TR0=1;
}void Timer0() interrupt 1
{TH0=0XFC;TL0=0X18;ts++;if(ts==1000){ts=0;refresh = 1;    }
}
  • 更新map
void print_game()
{unsigned char i;unsigned char x,y;memset(map,0,sizeof(unsigned char)*8);for(i=0;i<len;i++){tran(snake[i],&x,&y);map[x] += (1<<y);}tran(food,&x,&y);map[x] += (1<<y);
}
  • 产生食物
unsigned char generate_food()
{unsigned char food_,fx,fy;unsigned char in_snake = 0,i;int rd;do {rd = (unsigned char)(GetData(ACCEL_ZOUT_H));fx = rd & 0x07;fy = (rd & 0x38) >> 3;in_snake = 0;food_ = ((fx^0) << 4) ^ fy;for (i = 0; i < len; ++i){if (food_ == snake[i])in_snake = 1;}} while(in_snake);return food_;
}

这里本来打算用rand生成随机数的,后来一想,MPU在手里,为何不直接取位数取余做随机数呢,岂不是更好。

  • 蛇移动
void snake_move()
{unsigned char grow = 0,i,tmp,x_snake_head,y_snake_head;unsigned char last = snake[0];tran(snake[0],&x_snake_head,&y_snake_head);switch (dir){case UP:    y_snake_head++; break;case DOWN:  y_snake_head--; break;case LEFT:  x_snake_head--; break;case RIGHT: x_snake_head++; break;}snake[0] = ((x_snake_head^0) << 4) ^ y_snake_head;if(x_snake_head>7 || y_snake_head>7)isalive = 0;if(snake[0] == food){grow = 1;food = generate_food();}for(i=1;i<len;i++){if(snake[0] == snake[i])isalive = 0;tmp = snake[i];snake[i] = last;last = tmp;}if(grow){snake[len] = last;len++;}
}
  • 用MPU获得方向
void get_dir()
{int ax = GetData(ACCEL_XOUT_H);int ay = GetData(ACCEL_YOUT_H);if(ax < -8000)dir = LEFT;else if(ax > 8000)dir = RIGHT;else if(ay < -8000)dir = UP;else if(ay > 8000)dir = DOWN;
}

OK大功告成。
可以下载源码试一试,亲测有效
C51贪吃蛇(MPU6050控制方向,LED点阵显示)

重力感应贪吃蛇(C51 MPU6050 8*8LED点阵)相关推荐

  1. 贪吃蛇php源代码,GitHub - fusijie/Snake: CocoaChina Cocos2d-x编程大战:贪吃蛇源码汇总...

    ##CocoaChina 编程大战 贪吃蛇源码汇总 ###活动地址: ###获奖地址: ###感谢他们的分享(以下排名不分先后) 1.fireblackill First blood!第一个参与的活动 ...

  2. 基于51单片机的贪吃蛇小程序(8*8LED点阵实现)by_jy

    ** 基于51单片机的贪吃蛇小程序(8*8LED点阵实现)by_jy ** 一直很想写一个贪吃蛇的小程序,这两天终于抽空完成了,这里把我的思路分享给大家,仅供参考! 代码如下: 先放段主函数压压惊 v ...

  3. C51 贪吃蛇 基于 Proteus V1.0

    文章目录 0. 效果演示 1. 开发环境 2. 项目地址 3. 项目目录 4. 设计与开发 4.1 整体原理图 4.2 方向键模块 4.3 点阵模块 4.4 整体逻辑说明 4.4.1 点阵怎么刷新 4 ...

  4. STM32F407基于陀螺仪的贪吃蛇小游戏(全网最详细)

    一.前言 本次设计我用MPU6050在KEIL 5的环境下改进了贪吃蛇小游戏,用的开发板是STM32F407,本次设计综合利用多种ARM外设接口实现对外部设备信息的采集.处理及显示,实现了贪吃蛇游戏实 ...

  5. Unity3D_(游戏)贪吃蛇

    Unity制作贪吃蛇小游戏 玩家通过"WASD"控制小蛇上下左右移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体交叉蛇头撞倒自 ...

  6. 基于单片机的贪吃蛇游戏

    绪论 1.1 研究背景与意义 随着社会的发展,人们生活的步调日益加快,越来越多的人加入了全球化的世界. 人们不再拘泥于--,J,块天地,加班,出差成了现代人不可避免的公务.而此时一款可以 随时随地娱乐 ...

  7. 利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第一篇“显示贪吃蛇”

    利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第一篇"显示贪吃蛇" 完整的项目链接: https://github.com/linxinloningg/51_chip_ ...

  8. Unity制作贪吃蛇

    效果图: 思路:贪吃蛇的玩法核心是玩家控制一个方块 去吃另一个方块,吃掉的方块变成自己的身体跟随上一个方块移动,吃的越多速度越快,游戏结束判断是否撞到墙壁或者撞到自己的身体 一.场景布局 1.相机设置 ...

  9. ART-PI调试记录---重力感应无线智能小车第一弹之扩展板设计

    ART-PI重力感应无线智能小车第一弹-----ART-PI扩展板设计 雷德斯 and枕头们,小飞哥又又叒好久没更新文章啦,最近实在是太忙啦,大家久等啦,这次是系列文章,一步步教你如何在ART-PI上 ...

最新文章

  1. 怎么修复手机服务器,新手机怎么恢复旧手机上的所有数据?
  2. C++中使用Json的方法
  3. 一文搞懂Raft算法
  4. 仿真RM码,及在高斯信道下的译码性能,对RM采用大数逻辑译码算法
  5. linux打印mysql堆栈_第25问:MySQL 崩溃了,打印了一些堆栈信息,怎么读?
  6. 科创板注册获批,优刻得将成为“公有云第一股”
  7. mysql 2008数据库配置文件_SQL Server 2008数据库的配置及连接
  8. 那些从小不干活的人,不做家务,不做饭的人后来怎么样了呀?
  9. mysql 统计 1的数量_利用MySQL统计一列中不同值的数量方法示例
  10. 微芯片TWIZ5200: W5200 以太网 PICtail Plus 板
  11. ajax post提交到SpringMVC的Controller并将处理结果传递到前台输出总结(1)
  12. 显示桌面图标不见了的解决方法
  13. 使命召唤为啥显示新服务器玩家,《使命召唤8》建立服务器和加入自己、别人服务器方法...
  14. spring注入bean的三种方法
  15. 软件项目开发过程中应编写的十三类文档
  16. 重庆北大青鸟【学员心声】任何一次的考试,都是一次珍贵的蜕变机会
  17. icepak计算机机箱热仿真,基于ANSYSIcepak的密闭机箱散热仿真分析.PDF
  18. 【转载文章】原 DOS命令学习(从入门到精通)_____附加自己学习笔记
  19. 不会拼音怎么学计算机,不会拼音打字怎么办
  20. FMI飞马网 | AI人工智能/大数据/Database/Linear Algebra/Python/机器学习/Hadoop 有哪些书籍?福利可下载!

热门文章

  1. 雨课堂刷视频Python脚本
  2. matlab把图片制作成视频
  3. 20200305沈剑阿里云MVP分享笔记
  4. MAC 升级monterey 系统后无法启动Parallels Desktop
  5. MySQL 大批量插入,如何过滤掉重复数据?
  6. Python 斐波那契数
  7. 学习 第2章:备份与恢复选项
  8. 主板有电无法启动_电脑主板通电但是开不了机是什么原因?
  9. 全国计算机二级很难得吗,全国计算机二级考试难吗?
  10. 笔记本 原因代码: 0x500ff 关机类型: 关闭电源_图吧垃圾佬关于笔记本电池更换的几项建议...