重力感应贪吃蛇(C51 MPU6050 8*8LED点阵)
重力感应贪吃蛇(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点阵)相关推荐
- 贪吃蛇php源代码,GitHub - fusijie/Snake: CocoaChina Cocos2d-x编程大战:贪吃蛇源码汇总...
##CocoaChina 编程大战 贪吃蛇源码汇总 ###活动地址: ###获奖地址: ###感谢他们的分享(以下排名不分先后) 1.fireblackill First blood!第一个参与的活动 ...
- 基于51单片机的贪吃蛇小程序(8*8LED点阵实现)by_jy
** 基于51单片机的贪吃蛇小程序(8*8LED点阵实现)by_jy ** 一直很想写一个贪吃蛇的小程序,这两天终于抽空完成了,这里把我的思路分享给大家,仅供参考! 代码如下: 先放段主函数压压惊 v ...
- C51 贪吃蛇 基于 Proteus V1.0
文章目录 0. 效果演示 1. 开发环境 2. 项目地址 3. 项目目录 4. 设计与开发 4.1 整体原理图 4.2 方向键模块 4.3 点阵模块 4.4 整体逻辑说明 4.4.1 点阵怎么刷新 4 ...
- STM32F407基于陀螺仪的贪吃蛇小游戏(全网最详细)
一.前言 本次设计我用MPU6050在KEIL 5的环境下改进了贪吃蛇小游戏,用的开发板是STM32F407,本次设计综合利用多种ARM外设接口实现对外部设备信息的采集.处理及显示,实现了贪吃蛇游戏实 ...
- Unity3D_(游戏)贪吃蛇
Unity制作贪吃蛇小游戏 玩家通过"WASD"控制小蛇上下左右移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体交叉蛇头撞倒自 ...
- 基于单片机的贪吃蛇游戏
绪论 1.1 研究背景与意义 随着社会的发展,人们生活的步调日益加快,越来越多的人加入了全球化的世界. 人们不再拘泥于--,J,块天地,加班,出差成了现代人不可避免的公务.而此时一款可以 随时随地娱乐 ...
- 利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第一篇“显示贪吃蛇”
利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第一篇"显示贪吃蛇" 完整的项目链接: https://github.com/linxinloningg/51_chip_ ...
- Unity制作贪吃蛇
效果图: 思路:贪吃蛇的玩法核心是玩家控制一个方块 去吃另一个方块,吃掉的方块变成自己的身体跟随上一个方块移动,吃的越多速度越快,游戏结束判断是否撞到墙壁或者撞到自己的身体 一.场景布局 1.相机设置 ...
- ART-PI调试记录---重力感应无线智能小车第一弹之扩展板设计
ART-PI重力感应无线智能小车第一弹-----ART-PI扩展板设计 雷德斯 and枕头们,小飞哥又又叒好久没更新文章啦,最近实在是太忙啦,大家久等啦,这次是系列文章,一步步教你如何在ART-PI上 ...
最新文章
- 怎么修复手机服务器,新手机怎么恢复旧手机上的所有数据?
- C++中使用Json的方法
- 一文搞懂Raft算法
- 仿真RM码,及在高斯信道下的译码性能,对RM采用大数逻辑译码算法
- linux打印mysql堆栈_第25问:MySQL 崩溃了,打印了一些堆栈信息,怎么读?
- 科创板注册获批,优刻得将成为“公有云第一股”
- mysql 2008数据库配置文件_SQL Server 2008数据库的配置及连接
- 那些从小不干活的人,不做家务,不做饭的人后来怎么样了呀?
- mysql 统计 1的数量_利用MySQL统计一列中不同值的数量方法示例
- 微芯片TWIZ5200: W5200 以太网 PICtail Plus 板
- ajax post提交到SpringMVC的Controller并将处理结果传递到前台输出总结(1)
- 显示桌面图标不见了的解决方法
- 使命召唤为啥显示新服务器玩家,《使命召唤8》建立服务器和加入自己、别人服务器方法...
- spring注入bean的三种方法
- 软件项目开发过程中应编写的十三类文档
- 重庆北大青鸟【学员心声】任何一次的考试,都是一次珍贵的蜕变机会
- icepak计算机机箱热仿真,基于ANSYSIcepak的密闭机箱散热仿真分析.PDF
- 【转载文章】原 DOS命令学习(从入门到精通)_____附加自己学习笔记
- 不会拼音怎么学计算机,不会拼音打字怎么办
- FMI飞马网 | AI人工智能/大数据/Database/Linear Algebra/Python/机器学习/Hadoop 有哪些书籍?福利可下载!