📄 cfk.c
字号:
/*****************************************************
Project : 3310俄罗斯方块
Chip type : ATmega16
Program type : Application
Clock frequency : 4.000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega16.h>
#include <delay.h>
#include <stdlib.h>
#define BIT(x) (1 << (x))
#define SPI2X 0
#define SPE 6
#define MSTR 4
/*------------------------------------------------------------------------------
信息栏NEXT字模
------------------------------------------------------------------------------*/
flash char top[30]=
{
0x80,0x80,0xA2,0xB2,0xAA,0xAA,0xA6,0xA2,0x80,0xBE,0xA0,0xA0,0xBC,0xA0,0xA0,
0xBE,0x80,0xA2,0x94,0x94,0x88,0x94,0x94,0xA2,0x80,0xBE,0x88,0x88,0x88,0x88
};
/*------------------------------------------------------------------------------
结束图案字模
图像大小: 宽度x高度=32x48
------------------------------------------------------------------------------*/
flash unsigned char gameover[192]=
{
0x06,0xF2,0x02,0x00,0x00,0x02,0x02,0xE2,0x02,0x00,0x00,0x02,0x02,0xF2,0x02,0xC0,
0x60,0x32,0x32,0x32,0x62,0xC0,0x80,0xC2,0xC2,0x62,0x62,0x30,0x00,0x02,0xB2,0x36,
0x00,0xDF,0xD8,0xD8,0xD8,0xD8,0xD8,0xDF,0xD8,0xD8,0xD8,0xD8,0xD8,0xDF,0x00,0xDF,
0x18,0x18,0x18,0x18,0x18,0x9F,0x19,0x18,0x18,0x18,0x18,0xD8,0x00,0x00,0x39,0x93,
0x00,0x60,0x60,0x60,0x71,0x71,0x71,0x7B,0x7B,0x7B,0x7B,0x6E,0x6E,0x6E,0x00,0x7F,
0x60,0x60,0x60,0x60,0x60,0x7F,0x60,0x60,0x60,0x60,0x60,0x7F,0x00,0x00,0xA3,0xB9,
0x00,0x30,0x30,0x78,0x78,0x78,0xCC,0xCC,0xCC,0xFE,0x86,0x86,0x03,0x03,0x00,0x03,
0x03,0x86,0x86,0x86,0xCC,0xCC,0xCC,0x78,0x78,0x78,0x30,0x30,0x00,0x00,0xC5,0x9D,
0x00,0xE0,0x30,0x18,0x18,0x18,0x00,0xF8,0x18,0x19,0x19,0x19,0x3B,0xFB,0x00,0xE3,
0x33,0x31,0x19,0x19,0x18,0x18,0x18,0x18,0x18,0x30,0x30,0xE0,0x00,0x00,0x9C,0xC9,
0x60,0x43,0x46,0x06,0x0C,0x4C,0x4C,0x4C,0x4C,0x0C,0x0C,0x46,0x47,0x43,0x40,0x03,
0x06,0x46,0x4C,0x4C,0x4C,0x0C,0x0C,0x4C,0x4C,0x46,0x46,0x03,0x00,0x40,0x4D,0x6C
};
/*------------------------------------------------------------------------------
数字字模
------------------------------------------------------------------------------*/
flash char number[10][8]=
{
{0x80,0xBC,0xA4,0xA4,0xA4,0xA4,0xA4,0xBC}, //0
{0x80,0x88,0x98,0x88,0x88,0x88,0xBE,0x80}, //1
{0x80,0xBC,0x84,0x84,0xBC,0xA0,0xA0,0xBC}, //2
{0x80,0xBC,0x84,0x84,0xBC,0x84,0x84,0xBC}, //3
{0x80,0xA4,0xA4,0xA4,0xBC,0x84,0x84,0x84}, //4
{0x80,0xBC,0xA0,0xA0,0xBC,0x84,0x84,0xBC}, //5
{0x80,0xBC,0xA0,0xA0,0xBC,0xA4,0xA4,0xBC}, //6
{0x80,0xBC,0x84,0x84,0x84,0x84,0x84,0x84}, //7
{0x80,0xBC,0xA4,0xA4,0xBC,0xA4,0xA4,0xBC}, //8
{0x80,0xBC,0xA4,0xA4,0xBC,0x84,0x84,0xBC} //9
};
/*------------------------------------------------------------------------------
预览方块字模
注:
方向为顺时针
------------------------------------------------------------------------------*/
flash char smfk[7][4][4] =
{
//_|_
{
{0x80,0x88,0x9C,0x80},
{0x80,0x88,0x8C,0x88},
{0x80,0x9C,0x88,0x80},
{0x80,0x88,0x98,0x88}
},
//_|-
{
{0x80,0x90,0x98,0x88},
{0x80,0x8C,0x98,0x80},
{0x80,0x90,0x98,0x88},
{0x80,0x8C,0x98,0x80}
},
//-|_
{
{0x80,0x88,0x98,0x90},
{0x80,0x98,0x8C,0x80},
{0x80,0x88,0x98,0x90},
{0x80,0x98,0x8C,0x80}
},
//|___
{
{0x80,0x98,0x90,0x90},
{0x80,0x9C,0x84,0x80},
{0x80,0x88,0x88,0x98},
{0x80,0x90,0x9C,0x80}
},
//___|
{
{0x80,0x90,0x90,0x98},
{0x80,0x9C,0x90,0x80},
{0x80,0x98,0x88,0x88},
{0x80,0x84,0x9C,0x80}
},
//____
{
{0x88,0x88,0x88,0x88},
{0x80,0x9E,0x80,0x80},
{0x88,0x88,0x88,0x88},
{0x80,0x9E,0x80,0x80}
},
//□
{
{0x80,0x98,0x98,0x80},
{0x80,0x98,0x98,0x80},
{0x80,0x98,0x98,0x80},
{0x80,0x98,0x98,0x80}
}
};
/*------------------------------------------------------------------------------
汉字字模
------------------------------------------------------------------------------*/
flash char Hzk[5][32]=
{
//俄
{0x20,0xA8,0x24,0x24,0xFE,0x20,0x24,0xA6,0x2C,0x28,0x10,0x30,0x4A,0x8A,0x04,0x00,
0x10,0x19,0x16,0x22,0x3F,0x62,0xA2,0x22,0x23,0x26,0x2A,0x22,0x22,0x2E,0x24,0x00},
//罗
{0x00,0xFC,0x44,0x44,0x44,0xFC,0x00,0xFC,0x08,0x08,0x10,0x20,0xC0,0x00,0x00,0x00,
0x00,0x3F,0x22,0x22,0x22,0x3F,0x22,0x03,0x06,0x0C,0x12,0x61,0x00,0x03,0x0C,0xF0},
//斯
{0x0C,0x70,0x40,0x40,0x40,0x7E,0x48,0x48,0x48,0x48,0x48,0x48,0x88,0x88,0x08,0x08,
0x22,0x22,0xFF,0x22,0x3E,0x22,0x22,0x3E,0x22,0x22,0xFF,0x00,0x24,0x62,0x83,0x00},
//方
{0x00,0x00,0x80,0xFE,0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00,
0x02,0x01,0x00,0xFF,0x02,0x02,0x03,0x02,0x04,0x04,0x08,0x08,0x10,0x20,0xC0,0x00},
//块
{0x80,0x80,0x80,0xF8,0x88,0x88,0x88,0x88,0xFE,0x80,0x40,0x20,0x18,0x0E,0x04,0x00,
0x20,0x20,0x20,0x23,0xF8,0x20,0x20,0x20,0x2F,0x20,0x39,0xE1,0x42,0x02,0x04,0x08}
};
/*------------------------------------------------------------------------------
背景阵列
10×21,用于查看是否有无方块,1:有 0:无
------------------------------------------------------------------------------*/
static char scr[11][25];
/*------------------------------------------------------------------------------
显示一个方块
注:
1上有下有,2上无下有,3上有下无
------------------------------------------------------------------------------*/
flash char fk[12]=
{
0xFF,0x99,0x99,0xFF,
0xF0,0x90,0x90,0xF0,
0x0F,0x09,0x09,0x0F
};
//----------------------------3310头函数-----------------------------------//
#define LCD_DC 0x08 // LCD第4脚, Mega16:PB3 第4脚
#define LCD_CE 0x10 // LCD第5脚, Mega16:PB4 第5脚
#define SPI_MOSI 0x20 // LCD第3脚, Mega16:PB5(MOSI) 第6脚
#define LCD_RST 0x40 // LCD第8脚, Mega16:PB6(MISO) 第7脚
#define SPI_CLK 0x80 // LCD第2脚, Mega16:PB7(SCK) 第8脚
void LCD_init(void);
void LCD_clear(void);
void LCD_set_XY(unsigned char X, unsigned char Y);
void LCD_write_byte(unsigned char data, unsigned char command);
void LCD_draw_bmp_pixel(unsigned char X,unsigned char Y,
unsigned char Pix_x,unsigned char Pix_y);
//-------------------------------------------------------------------------//
/*-----------------------------------------------------------------------
函 数 名: LCD_init
功 能: 3310LCD初始化
输入参数:
注:
-----------------------------------------------------------------------*/
void LCD_init(void)
{
PORTB &= ~LCD_RST; // 产生一个让LCD复位的低电平脉冲
delay_us(1);
PORTB |= LCD_RST;
PORTB &= ~LCD_CE ; // 关闭LCD
delay_us(1);
PORTB |= LCD_CE; // 使能LCD
delay_us(1);
LCD_write_byte(0x21, 0); // 使用扩展命令设置LCD模式
LCD_write_byte(0xc8, 0); // 设置偏置电压
LCD_write_byte(0x06, 0); // 温度校正
LCD_write_byte(0x13, 0); // 1:48
LCD_write_byte(0x20, 0); // 使用基本命令
LCD_clear(); // 清屏
LCD_write_byte(0x0c, 0); // 设定显示模式,正常显示
PORTB &= ~LCD_CE ; // 关闭LCD
}
/*-----------------------------------------------------------------------
函 数 名: LCD_clear
功 能: LCD清屏函数
输入参数:
注:
-----------------------------------------------------------------------*/
void LCD_clear(void)
{
unsigned int i;
LCD_write_byte(0x0c, 0);
LCD_write_byte(0x80, 0);
for (i=0; i<504; i++)
LCD_write_byte(0, 1);
}
/*-----------------------------------------------------------------------
函 数 名: LCD_set_XY
功 能: 设置LCD坐标函数
输入参数:X 0-83
Y 0-5
注:
-----------------------------------------------------------------------*/
void LCD_set_XY(unsigned char X, unsigned char Y)
{
LCD_write_byte(0x40 | Y, 0); // column
LCD_write_byte(0x80 | X, 0); // row
}
/*-----------------------------------------------------------------------
函 数 名: LCD_write_byte
功 能: 使用SPI接口写数据到LCD
输入参数:data 写入的数据;
command 写数据/命令选择;
注:
-----------------------------------------------------------------------*/
void LCD_write_byte(unsigned char data, unsigned char command)
{
PORTB &= ~LCD_CE ; // 使能LCD
if (command == 0)
PORTB &= ~LCD_DC ; // 传送命令
else
PORTB |= LCD_DC ; // 传送数据
SPDR = data; // 传送数据到SPI寄存器
while ((SPSR & 0x80) == 0); // 等待数据传送完毕
PORTB |= LCD_CE ; // 关闭LCD
}
/*-----------------------------------------------------------------------
函 数 名: LCD_write_chinese_string
功 能: 在LCD上显示汉字
输入参数:X、Y 显示汉字的起始X、Y坐标;
ch_with 汉字点阵的宽度
num 显示汉字的个数;
line 汉字点阵数组中的起始行数
row 汉字显示的行间距
注:
-----------------------------------------------------------------------*/
void LCD_write_chinese_string(unsigned char X, unsigned char Y,
unsigned char ch_with,unsigned char num,
unsigned char line,unsigned char row)
{
unsigned char i,n;
LCD_set_XY(X,Y); //设置初始位置
for (i=0;i<num;)
{
for (n=0; n<ch_with*2; n++) //写一个汉字
{
if (n==ch_with) //写汉字的下半部分
{
if (i==0) LCD_set_XY(X,Y+1);
else
LCD_set_XY((X+(ch_with+row)*i),Y+1);
}
LCD_write_byte(Hzk[line+i][n],1);
}
i++;
LCD_set_XY((X+(ch_with+row)*i),Y);
}
}
/*-----------------------------------------------------------------------
函 数 名: LCD_draw_map
功 能: 位图绘制函数
输入参数:X、Y 位图绘制的起始X、Y坐标;
*map 位图点阵数据;
Pix_x 位图像素(长)
Pix_y 位图像素(宽)
注:
-----------------------------------------------------------------------*/
void LCD_draw_bmp_pixel(unsigned char X,unsigned char Y,
unsigned char Pix_x,unsigned char Pix_y)
{
unsigned int i,n;
unsigned char row;
if (Pix_y%8==0) row=Pix_y/8; //计算位图所占行数
else
row=Pix_y/8+1;
for (n=0;n<row;n++)
{
LCD_set_XY(X,Y);
for(i=0; i<Pix_x; i++)
{
LCD_write_byte(gameover[i+n*Pix_x], 1);
}
Y++; //换行
}
}
/*-----------------------------------------------------------------------
函 数 名: LCD_draw_top
功 能: 信息栏初始化
输入参数:*map 信息栏点阵数组
注:
-----------------------------------------------------------------------*/
void LCD_draw_top()
{
unsigned int i,n;
LCD_set_XY(0,0);
for (n=0;n<=30;n++)
{
LCD_write_byte(top[n],1);
}
LCD_set_XY(30,0);
for(i=30; i<=83; i++)
{
if ((i==32)||(i==41))
LCD_write_byte(0xff,1);
else
LCD_write_byte(0x80,1);
}
}
/*-----------------------------------------------------------------------
函 数 名: setxy
功 能: 将坐标转化为LCD坐标
输入参数: lx: 横坐标
ly: 纵坐标
-----------------------------------------------------------------------*/
void setxy(unsigned char lx,unsigned char ly)
{
LCD_set_XY(83-((ly-1)*4+3),5-lx/2);
}
/*-----------------------------------------------------------------------
函 数 名: draw
功 能: 画一个方块
输入参数: nx: 横坐标
ny: 纵坐标
-----------------------------------------------------------------------*/
void fk_dot(unsigned char nx,unsigned char ny)
{
if (ny<=21)
{
unsigned char i;
setxy(nx,ny);
if (nx%2==0)
if (scr[nx+1][ny])
for (i=0;i<4;i++)
LCD_write_byte(fk[i],1);
else
for (i=4;i<8;i++)
LCD_write_byte(fk[i],1);
else
if (scr[nx-1][ny])
for (i=0;i<4;i++)
LCD_write_byte(fk[i],1);
else
for (i=8;i<12;i++)
LCD_write_byte(fk[i],1);
scr[nx][ny] = 1;
}
}
/*-----------------------------------------------------------------------
函 数 名: fk_cldot
功 能: 削除一个方块
输入参数: nx: 横坐标
ny: 纵坐标
-----------------------------------------------------------------------*/
void fk_cldot(unsigned char nx,unsigned char ny)
{
if (ny<=21)
{
unsigned char i;
setxy(nx,ny);
if (nx%2==0)
{
if (scr[nx+1][ny])
for (i=8;i<12;i++)
LCD_write_byte(fk[i],1);
else
for (i=0;i<4;i++)
LCD_write_byte(0,1);
}
else
if (scr[nx-1][ny])
for (i=4;i<8;i++)
LCD_write_byte(fk[i],1);
else
for (i=0;i<4;i++)
LCD_write_byte(0,1);
scr[nx][ny] = 0;
}
}
//---------------------按键程序相关变量定义-------------------------//
char key_10ms_ok,key_500ms_ok;
char time_counter,key_stime_counter;
/*-----------------------------------------------------------------------
函 数 名: timer0_comp_isr
功 能: 提供程序所需要的定时中断
输入参数:
注:
Timer 0 比较匹配中断服务,2ms定时
-----------------------------------------------------------------------*/
//--------------------------------------//
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
if (++key_stime_counter >=5)
{
key_stime_counter = 0;
key_10ms_ok = 1; // 10ms 到
if (++time_counter >= 50)
{
time_counter = 0;
key_500ms_ok = 1;
}
}
}
#define key_input PINA // 按键输入口
#define key_mask 0b11110000 // 按键输入屏蔽码,使用PA4~7
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -