#include<reg51.h> #define uchar unsigned char #define uint unsigned int #define LED P1 sbit CS2=P2^1; sbit CS1=P2^0; const uchar tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; uchar data_L,data_H; uchar t,a; void delay(uint k) { uint m,n; for(m=0;m<k;m++) { for(n=0;n<120;n++); } } void display(void) { LED=tab[data_H]; CS1=1; delay(1); CS1=0; LED=tab[data_L]; CS2=1; delay(1); CS2=0; } void Timer0() interrupt 1 { t++; TH0=0x4C; TL0=0x00; } void data_tim(void) { if(t==20) { t=0; if(a==00) {a=59;} else {a--;} } } void data_in(void) { data_L=a%10; data_H=a/10; } void T0_init(void) { TMOD=0x01; TH0=0x4C; TL0=0x00; ET0=1; TR0=1; EA=1; } void main(void) { a=0; T0_init(); while(1) { data_tim(); data_in(); display(); } }工作原理
时间: 2024-03-30 19:34:58 浏览: 199
这是一段基于单片机的数字钟代码,使用了51单片机的定时器和端口控制实现数码管显示。其中,`tab`数组存储了0~9数字的编码,`display()`函数将当前需要显示的数字存储在`data_L`和`data_H`中,通过端口控制将其显示在数码管上。定时器中断每1ms触发一次,计数器`t`每次加1,当`t`等于20时,即20ms过去了,就将`t`清零,同时将`a`的值减1,实现了1秒钟倒计时的功能。`data_in()`函数将当前计时器的值转换为两个数字,分别存储在`data_L`和`data_H`中。整个程序通过不断循环实现了数字钟的显示效果。
相关问题
利用51单片机和LCD12864实现贪吃蛇游戏代码
以下是一个基于51单片机和LCD12864的简单贪吃蛇游戏代码,需要配合相应的硬件电路使用:
```c
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//定义LCD引脚
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
sbit LCD_CS1=P2^3;
sbit LCD_CS2=P2^4;
sbit LCD_RST=P2^5;
//定义按键引脚
sbit KEY_UP=P1^0;
sbit KEY_DOWN=P1^1;
sbit KEY_LEFT=P1^2;
sbit KEY_RIGHT=P1^3;
//定义贪吃蛇结构体
struct Snake
{
uchar x;
uchar y;
uchar dir;
}snake[100];
//定义食物结构体
struct Food
{
uchar x;
uchar y;
}food;
//定义游戏参数
uchar score=0;
uchar speed=10;
uchar len=3;
uchar over=0;
//初始化LCD
void InitLCD()
{
LCD_RST=0;
_nop_();
LCD_RST=1;
LCD_EN=0;
LCD_CS1=0;
LCD_CS2=0;
LCD_RW=0;
LCD_RS=0;
_nop_();
P0=0x3F;
LCD_EN=1;
_nop_();
LCD_EN=0;
_nop_();
P0=0xC0;
LCD_EN=1;
_nop_();
LCD_EN=0;
_nop_();
P0=0x40;
LCD_EN=1;
_nop_();
LCD_EN=0;
_nop_();
}
//写命令到LCD
void WriteCmd(uchar cmd)
{
LCD_RS=0;
LCD_RW=0;
_nop_();
P0=cmd;
LCD_EN=1;
_nop_();
LCD_EN=0;
_nop_();
}
//写数据到LCD
void WriteData(uchar dat)
{
LCD_RS=1;
LCD_RW=0;
_nop_();
P0=dat;
LCD_EN=1;
_nop_();
LCD_EN=0;
_nop_();
}
//清屏
void ClearScreen()
{
uchar i,j;
for(i=0;i<8;i++)
{
WriteCmd(0xB8+i);
WriteCmd(0x40);
for(j=0;j<128;j++)
{
WriteData(0x00);
}
}
}
//显示字符
void ShowChar(uchar x, uchar y, uchar ch)
{
uchar i;
WriteCmd(0xB8+y);
WriteCmd(0x40+x*8);
for(i=0;i<8;i++)
{
WriteData(font[ch-32][i]);
}
}
//显示字符串
void ShowString(uchar x, uchar y, uchar *str)
{
while(*str)
{
ShowChar(x++,y,*str++);
}
}
//绘制贪吃蛇
void DrawSnake()
{
uchar i;
for(i=0;i<len;i++)
{
WriteCmd(0xB8+snake[i].y/8);
WriteCmd(0x40+snake[i].x);
WriteData(0x01<<(snake[i].y%8));
}
}
//生成食物
void GenerateFood()
{
uchar x,y;
do
{
x=rand()%120+4;
y=rand()%8;
}while(GetPixel(x,y));
food.x=x;
food.y=y;
WriteCmd(0xB8+y);
WriteCmd(0x40+x);
WriteData(0xFF>>(7-food.y%8));
}
//获取像素点
uchar GetPixel(uchar x, uchar y)
{
WriteCmd(0xB8+y/8);
WriteCmd(0x40+x);
return (ReadData()>>(7-y%8))&0x01;
}
//读取数据
uchar ReadData()
{
uchar dat;
LCD_RS=1;
LCD_RW=1;
LCD_EN=1;
_nop_();
dat=P0;
LCD_EN=0;
_nop_();
return dat;
}
//移动贪吃蛇
void MoveSnake()
{
uchar i;
for(i=len-1;i>0;i--)
{
snake[i].x=snake[i-1].x;
snake[i].y=snake[i-1].y;
}
switch(snake[0].dir)
{
case 1: snake[0].y--; break;
case 2: snake[0].x--; break;
case 3: snake[0].x++; break;
case 4: snake[0].y++; break;
}
}
//检测游戏是否结束
void CheckOver()
{
uchar i;
if(snake[0].x<4||snake[0].x>123||snake[0].y<0||snake[0].y>7)
{
over=1;
return;
}
for(i=1;i<len;i++)
{
if(snake[0].x==snake[i].x&&snake[0].y==snake[i].y)
{
over=1;
return;
}
}
}
//检测是否吃到食物
void CheckFood()
{
if(snake[0].x==food.x&&snake[0].y==food.y)
{
len++;
score++;
GenerateFood();
}
}
//检测按键
void CheckKey()
{
if(KEY_UP==0&&snake[0].dir!=4) snake[0].dir=1;
if(KEY_DOWN==0&&snake[0].dir!=1) snake[0].dir=4;
if(KEY_LEFT==0&&snake[0].dir!=3) snake[0].dir=2;
if(KEY_RIGHT==0&&snake[0].dir!=2) snake[0].dir=3;
}
//延时函数
void Delay(uint n)
{
uint i,j;
for(i=0;i<n;i++)
{
for(j=0;j<50;j++);
}
}
//主函数
void main()
{
InitLCD();
ClearScreen();
ShowString(0,0,"Score:");
ShowString(0,1,"Speed:");
ShowString(0,2,"Snake");
ShowString(0,3,"Game");
GenerateFood();
snake[0].x=60;
snake[0].y=3;
snake[0].dir=3;
DrawSnake();
while(1)
{
CheckKey();
MoveSnake();
CheckFood();
CheckOver();
if(over) break;
DrawSnake();
ShowChar(7,0,score/10+'0');
ShowChar(8,0,score%10+'0');
ShowChar(7,1,speed/10+'0');
ShowChar(8,1,speed%10+'0');
Delay(100-speed);
}
ShowString(0,4,"Game Over!");
while(1);
}
```
注意:以上代码仅供参考,具体实现方式可能有所不同。在实际使用中,需要根据硬件电路和开发环境进行相应的修改。
生成代码用51单片机和LCD160128显示两个ADC0832采集4路光敏电阻值
### 回答1:
以下是用51单片机和LCD160128显示两个ADC0832采集4路光敏电阻值的代码:
```c
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS = P1^0; //定义LCD160128 用到的引脚
sbit RW = P1^1;
sbit EN = P1^2;
sbit CS1 = P1^3;
sbit CS2 = P1^4;
void delay(uint n); //延时函数
void Init_Lcd(); //初始化LCD160128
void Lcd_Write_Com(uchar com); //向LCD发送指令
void Lcd_Write_Data(uchar dat); //向LCD发送数据
void Lcd_Address(uchar page, uchar column); //设置LCD160128的地址
void Display(uchar page, uchar column, uchar num); //在指定位置显示数字
void Display_String(uchar page, uchar column, uchar *s); //在指定位置显示字符串
uchar Read_AD(uchar ch); //读取AD转换结果
void main()
{
uchar i, j, value[4];
Init_Lcd(); //初始化LCD160128
while(1)
{
for(i=0; i<2; i++)
{
if(i == 0) CS1 = 0; //选中第一个ADC0832
else CS2 = 0; //选中第二个ADC0832
for(j=0; j<4; j++)
{
value[j] = Read_AD(j); //读取各个通道的AD转换结果
}
if(i == 0) CS1 = 1; //取消选中第一个ADC0832
else CS2 = 1; //取消选中第二个ADC0832
for(j=0; j<4; j++)
{
Display(i*4+j, 0, j); //在LCD上显示通道号
Display(i*4+j, 2, value[j]); //在LCD上显示光敏电阻值
}
}
}
}
void delay(uint n)
{
uint i, j;
for(i=0; i<n; i++)
{
for(j=0; j<125; j++);
}
}
void Init_Lcd()
{
Lcd_Write_Com(0x40);
Lcd_Write_Com(0xA1);
Lcd_Write_Com(0xC0);
Lcd_Write_Com(0xA6);
Lcd_Write_Com(0xA2);
Lcd_Write_Com(0x2F);
Lcd_Write_Com(0xF8);
Lcd_Write_Com(0x00);
Lcd_Write_Com(0x27);
Lcd_Write_Com(0x81);
Lcd_Write_Com(0x16);
Lcd_Write_Com(0xAC);
Lcd_Write_Com(0x00);
Lcd_Write_Com(0xAF);
}
void Lcd_Write_Com(uchar com)
{
RS = 0;
RW = 0;
P2 = com;
EN = 1;
_nop_();
EN = 0;
delay(5);
}
void Lcd_Write_Data(uchar dat)
{
RS = 1;
RW = 0;
P2 = dat;
EN = 1;
_nop_();
EN = 0;
delay(5);
}
void Lcd_Address(uchar page, uchar column)
{
Lcd_Write_Com(0xB0+page);
Lcd_Write_Com(0x10+((column>>4)&0x0F));
Lcd_Write_Com(column&0x0F);
}
void Display(uchar page, uchar column, uchar num)
{
uchar i, j, k;
uchar code table[10][16] = { //数字对应的点阵编码
{0x00,0x7C,0x44,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //0
{0x00,0x48,0x74,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //1
{0x00,0x64,0x54,0x4C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //2
{0x00,0x44,0x54,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //3
{0x00,0x1C,0x10,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //4
{0x00,0x4C,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //5
{0x00,0x7C,0x54,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //6
{0x00,0x04,0x04,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //7
{0x00,0x7C,0x54,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //8
{0x00,0x5C,0x54,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} //9
};
for(i=0; i<16; i++)
{
k = table[num][i];
Lcd_Address(page, column+i);
for(j=0; j<8; j++)
{
Lcd_Write_Data(k&0x80);
k <<= 1;
}
}
}
void Display_String(uchar page, uchar column, uchar *s)
{
while(*s)
{
Display(page, column, *s-48);
s++;
column += 2;
}
}
uchar Read_AD(uchar ch)
{
uchar value;
P1 = (P1&0xF8)|ch; //设置ADC0832的通道
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //延时
P3 = 0xFF; //准备读取AD转换结果
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //延时
value = P3; //读取AD转换结果
return value;
}
```
该代码使用了两个ADC0832芯片,每个芯片可以同时采集2路模拟信号。因此,该代码可以采集4路光敏电阻的模拟信号。采集完毕后,将光敏电阻的值显示在LCD160128上。
### 回答2:
为了使用51单片机和LCD160128显示两个ADC0832采集的4路光敏电阻值,需要进行以下步骤。
首先,连接电路。将51单片机的相应引脚连接到LCD160128和两个ADC0832芯片。根据硬件连接图连接VDD和GND引脚,将时钟引脚连接到单片机的时钟输入引脚,将数据引脚连接到单片机的数据输入引脚。
然后,设置相应的端口和引脚。在单片机的程序中,需要设置两个ADC0832芯片的相应引脚为输入引脚和输出引脚,并设置LCD160128的引脚为输出引脚。
接下来,编写ADC0832的读取函数。通过单片机的GPIO控制引脚,让ADC0832开始进行模数转换,并读取转换后的模拟电压值。
然后,编写显示函数。通过单片机的GPIO控制引脚和LCD160128的通信协议,将读取到的光敏电阻值显示在LCD屏幕上。
最后,编写主程序。在主程序中,循环读取四个光敏电阻值,并调用显示函数将其显示在LCD屏幕上。可以使用定时器中断进行采样的定时。
需要注意的是,在编程过程中,要注意进行合适的初始化和配置,以及正确处理数据的转换和显示。还需要根据具体情况调试和优化程序,确保数据的准确性和界面的稳定性。
通过以上步骤,就可以使用51单片机和LCD160128显示两个ADC0832采集的4路光敏电阻值。
### 回答3:
生成代码使用51单片机和LCD160128显示两个ADC0832采集4路光敏电阻值的步骤如下:
1. 首先,将51单片机与两个ADC0832以及LCD160128连接。将ADC0832的OUT1至OUT4引脚与单片机的IO口相连,并将ADC0832的CLK引脚与单片机的时钟输出引脚相连,将ADC0832的CS引脚与两个IO口相连。将LCD160128的数据引脚(D0至D7)与单片机的IO口相连,并将RS、RW和EN引脚与IO口相连。
2. 初始化程序,设置ADC0832的工作模式和LCD160128的显示模式。首先,将两个IO口设置为输出模式,设置CLK引脚为低电平。然后,向LCD发送初始化指令,配置LCD160128的显示模式。
3. 进入主循环,循环读取ADC0832的数值并在LCD上显示。先将两个ADC0832的CS引脚拉低,选择其中一个ADC0832。然后,循环读取ADC0832采集的4路光敏电阻的数据,将数据通过IO口写入LCD160128进行显示。读取完毕后,将该ADC0832的CS引脚拉高,完成一轮采集。
4. 重复步骤3,选择另一个ADC0832进行采集,并将数据通过LCD显示出来。
5. 循环以上两个步骤,实现不断采集和显示的功能。
通过以上步骤,我们可以使用51单片机和LCD160128显示两个ADC0832采集的4路光敏电阻值。
阅读全文