STC89C52に基づくヘビを食べるヘビ(74hc595とP1ポートを使用します。P1ポートは74hc138に置き換えることができます)

(コードに関しては、実際にネチズンのコードをコピーしました。)
ステートメント1:実際、単色ドットマトリックスLEDは、共通のアノードがあるか共通のカソードがあるかは関係ありません。名前のほとんどは業界によるものです。習慣。市場では、8 * 8ドットマトリックスLEDのいわゆる共通アノードまたは共通カソードは、一般に、ドットマトリックスの最初のピンの極性に従って定義され、最初のピンはアノードであり、それは共通アノードであり、逆もまた同様です。

引数2:売り手の共通の陰または共通の陽は共通の陰または共通の陽でなければなりません。
ここに画像の説明を挿入
ここに画像の説明を挿入

これらの2つの写真から、最初の足が最初の行にあることがわかります。したがって、これら2つのステートメントは実際には同じです。

ドットマトリックスの基本的な知識について話しましょう

ピンの定義:

一部のドットは最初のピンでマークされていますが、そうでないものもあります。現在、すべての人がデフォルトでICと同じピン順序になっています。読み取り方法は、通常、最初のピンが横にあり、単語が横にあることです。図に示すように、正の場合、左が最初です。ピンは1で、次に反時計回りにピン16にソートされます。

一般的な陰と一般的な陽の質問の回答と8 * 8ドットマトリックスの基本的な知識の説明

ランク定義
ここに画像の説明を挿入
ここに画像の説明を挿入

8 * 8ドットマトリックス内部構造

Xing Yin
ここに画像の説明を挿入

Xing Gongyang
ここに画像の説明を挿入

上の図は、ark sz410788kドットマトリックスの各行と列に対応するピン番号も示しています。8* 8ドットマトリックスのすべてのピンに対応する行と列がarkdotと同じかどうかはわかりません。しかし、これまでに使用した2つまたは3つのドットマトリックスの対応する順序は、上記の2つの図と同じです。

一般的な陰と一般的な陽の質問の回答と8 * 8ドットマトリックスの基本的な知識の説明

ピンの順序が本当にわからない場合は、アナログマルチメータを使用してテストできます

ピンを決定するための具体的な手順は次のとおりです(マルチメーターまたは他の電圧源を使用してテストできます。私は機械式マルチメーターを使用します)

1. [正極と負極を決定する]マルチメータを抵抗位置×10に設定し、最初に黒いプローブ(高レベル出力)を使用してピンを自由に選択し、赤いプローブが残りのピンに触れてドットかどうかを確認しますマトリックスが点灯しています。光がない場合は、黒のプローブを使用して別のピンを選択します。赤のプローブは残りのピンに接触します。ドットマトリックスが発光すると、黒のプローブが接触したピンは正であり、赤はプローブがライトに接触します71つのピンが負で、残りの6つのピンが正です。

2. [ピン番号]最初にデバイスのピンの正と負の分布を書き留めます。正極(行)は数字で表され、負極(列)は文字で表され、最初に負のピン番号を指定します。黒のプローブは正極ピンを選択し、赤のドットは負のピンを選択し、ダイオードのどの列が発光するかを確認し、最初の列にAを書き込み、2番目の列にBを書き込み、3番目の列にBを書き込みます。このようにして、ドットマトリックスのピンの半分に番号が付けられます。残りの正のピンにも同じ方法を使用します。最初の列の光はピン1にあり、2番目の列はピン2にあり、3番目の列は...というように続きます。

#include<reg51.h>//51头文件
#include<intrins.h>//使用到_nop_()延时函数要包括这个头文件
#include<stdlib.h>//使用到了rand()函数(要用这个头文件)

#define u16 unsigned int //用u16  代替unsigned int(简化)
#define u8 unsigned char //用u8  代替unsigned char(简化)

//595IO口定义
sbit SER=P3^7;
sbit RCLK=P3^6;
sbit SRCLK=P3^5;
//按键IO口定义
sbit up=P2^1;
sbit down=P2^2;
sbit lt=P2^3;
sbit rt=P2^0;

u8	code Hc595_Coordx[]={
    
    0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//给0
u8	code Hc595_Coordy[]={
    
    0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//给1
u8	 foodx;//食物的X坐标
u8   foody;	//食物的y坐标
u8   snake_x[20]={
    
    0};//最大长度
u8   snake_y[20]={
    
    0};
u8 length;//储存蛇长
u8 direction;//方向	(2为向下,1位向上,3向左,4向右)

void initSnake();//初始化函数
void delay(u16 i);//延时函数
void Hc595SendByte(u8 dat);//595发送数据函数
void move();//移动
void Keypros();//按键控制函数
void creatFood();//创建食物函数
void snake_Grow(void);//长大函数
void drawsnake();//点亮食物和蛇的函数
void JudgeDeath(void);//判断是否撞到自己或者墙
void Timer0Init();//定时器0初始化函数

void initSnake()
{
    
    
  	snake_x[0]=0;//初始话蛇的位置为第0行第0列
	snake_y[0]=0;
	length=1;//初始化长度为两个点
	direction=2;//初始化运动方向为向下
}

void delay(u16 i)
{
    
    
  while(i--);
}

void Hc595SendByte(u8 dat)
{
    
    
	u8 a;
	SRCLK=0;
	RCLK=0;
	for(a=0;a<8;a++)
	{
    
    
		SER=dat>>7;//从高位开始发送(把低7位移走,以此类推)
		dat<<=1; //左移一位把最高位去掉,发送次高位(以此类推)

		SRCLK=1;//srclk一个上升沿数据进入移位寄存器
		_nop_();
		_nop_();
		SRCLK=0;	
	}

	RCLK=1;	//rclk一个上升沿将数据输出到并行串口
	_nop_();
	_nop_();
	RCLK=0;
}


void move()
{
    
    
     
    u8 len = length- 1;
	//length减一的原因(设长度为7,则len为6到1,蛇头不算)
    for(len; len > 0; len--)
    {
    
    
        snake_x[len] = snake_x[len - 1];//将蛇尾后的点移动到前一个点
        snake_y[len] = snake_y[len - 1];//一直到蛇头
    }
    switch(direction)
    {
    
    
	    case 1:
	        snake_y[0]--;//向上移动
	        break;
	    case 2:
	        snake_y[0]++;//向下移动	//再利用蛇头转变方向
	        break;
	    case 3:
	        snake_x[0]--;//向左移动
	        break;
	    case 4:
	        snake_x[0]++;//向右移动
	        break;
	    default://输入其他就跳出
	        break;
    }

}


//贪吃蛇的上下左右行动控制
void Keypros()
{
    
    
	if(up==0)
	{
    
    
		delay(1000);  //消抖处理
		if(up==0)
		{
    
    
		  if(direction==3|direction==4)//如果是向左或是向右移动的情况下
		  direction=1;             //在地址1内写入数据num
		}
		while(!up);//判断按键是否松开
	}
	if(down==0)
	{
    
    
		delay(1000);  //消抖处理
		if(down==0)
		{
    
    	if(direction==3|direction==4)//如果是向左或是向右移动的情况下
			direction=2;	  
		}
		while(!down);
	}
	if(lt==0)
	{
    
    
		delay(100);  //消抖处理
		if(lt==0)
		{
    
    
		    if(direction==1|direction==2)//如果是向下或是向上移动的情况下
			direction=3; 
		}
		while(!lt);
	}
	if(rt==0)
	{
    
    
		delay(1000);  //消抖处理
		if(rt==0)
		{
    
    
		   if(direction==1|direction==2)//如果是向下或是向上移动的情况下
		   direction=4; 
		}
		while(!rt);
	}		
}

void creatFood()	 //随机创造食物
{
    
    
    u8 i;
    foodx=rand()%8;//随机取数为0到8给食物的x的坐标
    foody=rand()%8;//随机取数为0到8给食物的y的坐标
	delay(0);//延时一会
    for(i=0; i<length; i++)//在蛇长范围内如果食物与蛇身重叠(小于等于蛇长)
    {
    
    
        if((foodx==snake_x[i])&&(foody==snake_y[i]))	
        {
    
    	//如果食物与蛇的身体重叠,要重新创建
            creatFood();
        }       
    }
}

void snake_Grow(void)
{
    
    
    if(snake_x[0] == foodx && snake_y[0] == foody)
    {
    
    	//如果蛇头碰到食物蛇长+1,然后重新创建食物
		//将蛇尾加长
        creatFood();
        snake_x[length] = snake_x[length - 1];
        snake_y[length] = snake_y[length - 1];
        length++;//长度加一
    }
}


void drawsnake()   //点亮蛇和食物
{
    
    
     u8	i;
     for(i=0;i<length;i++)
	{
    
    
	  	Hc595SendByte(Hc595_Coordy[snake_y[i]]);//595控制x坐标(发送y坐标)
		P1=Hc595_Coordx[snake_x[i]];//P0口控制x坐标(发送x坐标)
		//P0口可以改用74hc138译码器,同样有效
        delay(0);//延时一会
		P1=0xff;//消影

	    Hc595SendByte(Hc595_Coordy[foody]);   
	    P1=Hc595_Coordx[foodx];
		delay(0);//延时一会
	    P1=0xff;//消影		
	}
}

void JudgeDeath(void)
{
    
    
    u8 i;

    // 判断蛇撞墙死亡
    if((snake_x[0]>7)||(snake_y[0]>7))
    {
    
    
         Hc595SendByte(0x00);
        while(1);
    }

    // 判断蛇撞到自己身体死亡
    for(i=5; i<length; i++)//为什么i要大于4?
    {
    
    
		//当蛇的长度超过4的时候才会有可能撞到自己
        if((snake_x[0]==snake_x[i])&&(snake_y[0]==snake_y[i]))
        {
    
    
            P1=0xFF;
            while(1);
        }
    }
}


void Timer0Init()
{
    
    
	TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

	TH0=0XD8;	//给定时器赋初值,定时10ms
	TL0=0XF0;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器	
			
}

void main()
{
    
       
   
	Timer0Init();
	initSnake();	
	while(1)
	{
    
     
		drawsnake();
		JudgeDeath();
		snake_Grow();
		Keypros();
	}

}

void Timer0() interrupt 1
{
    
    
	static u16 i;
	TH0=0XD8;	//给定时器重新赋初值,定时10ms
	TL0=0XF0;
	i++;
	if(i==50)//当到达500ms时移动一下(改变这里可以改变速度)
	{
    
    
		i=0;
		move();
	}	
}

おすすめ

転載: blog.csdn.net/qq_45774073/article/details/109037075