51单片机学习代码整理

代码整理

前言

本文是关于51单片机学习的相关代码整理,关联笔记可以查看下方链接:

http://t.csdnimg.cn/zkvLv

学习资源

参考资料:
【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.bilibili.com/video/BV1Mb411e7re?p=3&vd_source=c7e5b42e6c1438daf4523dc34387738c

1.预处理框架

#ifndef __NAME_H__
#define __NAME_H__

#endif

2.自定义函数

2.1 延时函数

#include <INTRINS.H>
void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

2.2 数码管位选函数

void NixieLED(unsigned char LED)
{
	switch(LED)
	{  
		case 1: P2_4=0;P2_3=0;P2_2=0;break;
		case 2: P2_4=0;P2_3=0;P2_2=1;break;
		case 3: P2_4=0;P2_3=1;P2_2=0;break;
		case 4: P2_4=0;P2_3=1;P2_2=1;break;
		case 5: P2_4=1;P2_3=0;P2_2=0;break;
		case 6: P2_4=1;P2_3=0;P2_2=1;break;
		case 7: P2_4=1;P2_3=1;P2_2=0;break;
		case 8: P2_4=1;P2_3=1;P2_2=1;break;
	}
}

2.3 数码管段选(数字)函数

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
void NixieNumber(unsigned char Number)
{
	P0=NixieTable[Number];
}	

3.相关自定义的头文件

3.1 LCD1602

LCD1602.c

#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

3.2 Delay

Delay.c

#include <INTRINS.H>
void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

3.3 Key(获取独立按键键码)

Key.c

#include <at89c51RC2.h>
#include <Delay.h>

/**
  * @brief 获取独立按键键码
  * @param 无
  * @retval 按下按键的键码,范围0~4,无按键按下时返回值为0
  */

unsigned char Key()
{
	unsigned int KeyNumber=0;
	
	if(P3_1==0){Delay(20);while(P3_1==0);Dealy(20);KeyNumber=1;}
	if(P3_0==0){Delay(20);while(P3_0==0);Dealy(20);KeyNumber=2;}
	if(P3_2==0){Delay(20);while(P3_2==0);Dealy(20);KeyNumber=3;}
	if(P3_3==0){Delay(20);while(P3_3==0);Dealy(20);KeyNumber=4;}
	
	return KeyNumber;
}

Key.h

#ifndef __Key_H__
#define __Key_H__

unsigned char Key()#endif 

3.4 MatrixKey(矩阵键盘读取键盘键码)

MatrixKey.c

#include <at89c51RC2.h>
#include <Delay.h>
/**
  * @brief 矩阵键盘读取键盘键码
  * @param 无
  * @retval  KeyNumber本人 按下按键的键码值
	如果按键按下不放,程序会停留在子函数,松手的一瞬间,返回按键的键码值,没有按键按下时,返回W
  */

unsigned char MatrixKey()
{
	unsigned char KeyNumber="W";
	
	P1=0xFF;
	P1_3=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=7;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=4;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=1;}
	
	P1=0xFF;
	P1_2=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=8;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=2;}
	if(P1_4==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=0;}
	
	P1=0xFF;
	P1_1=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=9;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=3;}
	
	return KeyNumber;
}

MatrixKey.h

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey()#endif 

3.5 Timer0(定时器0初始化,1毫秒@11.0592HZ)

Timer0.c

#include <REGX52.h>

/**
  * @brief 定时器0初始化,1毫秒@11.0592HZ
  * @param 无
  * @retval 
  */
void Timer0_Init()
{
	
	//TMOD=0x01;      //0000 0001,选中定时器1,置为计时器状态
	TMOD=TMOD&0xF0;   //把TMOD的低四位清零,高四位保持不变
	TMOD=TMOD|0x01;   //把TMOD最低位置1,高四位保持不变
	TF0=0;            //将溢出中断标志清0
	TR0=1;            //开始计时
	TL0 = 0x66;		    //设置定时初值
	TH0 = 0xFC;		    //设置定时初值   
	ET0=1;
	EA=1;             //闭合两个总开关
	PT0=0;            //设置优先级为最低
}

/*定时器中断函数模板
void Timer0_Routine() interrupt 1  //溢出时中断
{
	static int T0Count;
	TL0 = 0x66;		 
	TH0 = 0xFC;
	T0Count++;
	if(T0Count>=1000)
	{
		T0Count=0;
		
	}		
}
*/

Timer.h

#ifndef __Timer0_H__
#define __Timer0_H__

void Timer0_Init();

#endif 

3.6 UART(串口通信)

UART.c

#include <at89c51RC2.h>

/**
  * @brief 对UART初始化(单片机单向向设备传输数据),4800波特率
  * @param 无
  * @retval 无
  */
void UartInit_51(void)		//4800bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFA;		//设定定时初值
	TH1 = 0xFA;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

void UartInit_Device(void)		//4800bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFA;		//设定定时初值
	TH1 = 0xFA;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	EA=1;
	ES=1;       //设置串口开放中断
}

/**
  * @brief 单片机向设备传输数据
  * @param Byte 要单片机向设备传输的内容
  * @retval 无
  */
void Uart_SendByte(unsigned char Byte)
{
	SBUF=Byte;
	while(TI==0);
	TI=0;
}

//串口中断函数模板
//void UART_Routine(void) interrupt 4
//{
//	if(RI==1)      //单片机接收中断
//  {
//		P2=SBUF;
//		Uart_SendByte(SBUF);
//		RI=0;
//	}
//}

UART.h

#ifndef __UART_H__
#define __UART_H__

void UartInit_51(void);
void UartInit_Device(void)void Uart_SendByte(unsigned char Byte);

#endif 

3.7 MatrixLED(8*8点阵屏)

MatrixLED.c

#include <at89c51RC2.h>
#include <Delay.h>

/**
  * @brief 点阵屏初始化
  * @param 无
  * @retval 无
  */
void MatrixLED_Init()
{
	P3_6=0;
	P3_5=0;
}


/**
  * @brief 74CH595写入八位数据
  * @param Byte 要写入的数据
  * @retval 无
  */
void _74HC595_WriteByte(unsigned char Byte) //写入数据
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		P3_4=Byte&(0x80>>i);   //依次取Byte各位值赋给SER
		P3_6=1;                //一横SRCLR,实现数据下行
		P3_6=0;
	}
	P3_5=1;        //SRCLK,实现输出
	P3_5=0;
}


/**
  * @brief LED点阵屏显示一列数据
	* @param Column 要选择的列,范围0~7,0为最左列
	* @param Data 选择列显示数据,高位在上,1为亮,0为灭
  * @retval 
  */
void MatrixLED_ShowColumn(unsigned char Column,Data)  //选中行,列
{
	_74HC595_WriteByte(Data);
	P0=~(0x80>>Column);
	Delay(1);
	P0=0xFF;
}

MatrixLED.h

#ifndef __MatrixLED_H__
#define __MatrixLED_H__

void MatrixLED_Init();
void _74HC595_WriteByte(unsigned char Byte);
void MatrixLED_ShowColumn(unsigned char Column,Data);

#endif 

3.8 DS1302

DS1302.c

#include <at89c51RC2.h>

//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;

//寄存器写入地址/指令定义
#define  DS1302_SECOND     0x80
#define  DS1302_MINUTE     0x82
#define  DS1302_HOUR       0x84
#define  DS1302_DATE       0x86
#define  DS1302_MONTH      0x88
#define  DS1302_DAY        0x8A
#define  DS1302_YEAR       0x8C
#define  DS1302_WP         0x8E

unsigned char DS1302_Time[]={24,7,25,17,14,50,6}; //年月日时分秒星期


/**
  * @brief 初始化
  * @param 无
  * @retval 无
  */
void DS1302_Init(void)
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}


/**
  * @brief  写入字节
  * @param  Command 命令字/地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void DS1302_WriteByte(unsigned char Command,Data)
{
	unsigned char i;
	DS1302_CE=1;
	
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	for(i=0;i<8;i++)
	{
		DS1302_IO=Data&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;
}


/**
  * @brief  DS1302读一个字节
  * @param  Command 命令字/地址
  * @retval 读出的数据
  */
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00;
	Command|=0x01;
	DS1302_CE=1;
	
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}
	}
	DS1302_CE=0;
	DS1302_IO=0;
	return Data;
}

/**
  * @brief  DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
  * @param  无
  * @retval 无
  */
void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);  //关闭读写保护
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_WP,0x80);   //打开写保护
}

/**
  * @brief  DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
  * @param  无
  * @retval 无
  */
void DS1302_ReadTime(void)
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[6]=Temp/16*10+Temp%16;
}

DS1302.h

#ifndef __DS1302_H__
#define __DS1302_H__

extern unsigned char DS1302_Time[];

void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_SetTime(void);
void DS1302_ReadTime(void);

#endif 

3.9 AT23C02

AT23C02.c

#include <at89c51RC2.h>
#include <I2C.h>

#define AT24C02_ADDRESS_W 0xA0 
#define AT24C02_ADDRESS_R 0xA1 

/**
  * @brief AT24C02写入一个字节
  * @param WordAddress 字节写入的地址
  * @param Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS_W);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}	

	
/**
  * @brief AT24C02读取一个字节
  * @param WordAdress 要读出的字节的地址
  * @retval Data 读出的数据
	*/
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS_W);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS_R);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	
	return Data;
}

AT23C02.h

#ifndef __AT24C02_H__
#define __AT24C02_H__

void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);

#endif 

3.10 I2C(I2C总线)

I2C.c

#include <REGX52.H>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

/**
  * @brief  I2C接收一个字节
  * @param  无
  * @retval 接收到的一个字节数据
  */
unsigned char I2C_ReceiveByte(void)
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA){Byte|=(0x80>>i);}
		I2C_SCL=0;
	}
	return Byte;
}

/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char AckBit;
	I2C_SDA=1;
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;
}

I2C.h

#ifndef __I2C_H__
#define __I2C_H__

void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte(void);
void I2C_SendAck(unsigned char Ackbit);
unsigned char I2C_ReceiveAck(void);

#endif 

3.11 Nixie(数码管)

Nixie.c

#include <at89c51RC2.h>

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};

/**
  * @brief 数码管的静态显示
  * @param LED,哪个数码管亮
  * @param Number,要显示的数字
  * @retval 无
  */
void Nixie(unsigned char LED,Number)
{
	switch(LED)
	{  
		case 8: P2_4=0;P2_3=0;P2_2=0;break;
		case 7: P2_4=0;P2_3=0;P2_2=1;break;
		case 6: P2_4=0;P2_3=1;P2_2=0;break;
		case 5: P2_4=0;P2_3=1;P2_2=1;break;
		case 4: P2_4=1;P2_3=0;P2_2=0;break;
		case 3: P2_4=1;P2_3=0;P2_2=1;break;
		case 2: P2_4=1;P2_3=1;P2_2=0;break;
		case 1: P2_4=1;P2_3=1;P2_2=1;break;
	}
	P0=NixieTable[Number];
	P0=0x00; //消影
}

Nixie.h

#ifndef __Nixie_H__
#define __Nixie_H__

void Nixie(unsigned char LED,Number);

#endif 

3.12 OneWire(单总线)

OneWire.c

#include <at89c51RC2.h>

sbit OneWire_DQ=P3^7; 

/**
  * @brief 单总线初始化
  * @param 
  * @retval 
  */
unsigned char OneWire_Init(void)
{
	unsigned char i;
	unsigned char AckBit;
	
	OneWire_DQ=1;
	OneWire_DQ=0;
	i = 227;while (--i);  //Delay 500us
	
	OneWire_DQ=1;
	
	i = 29;while (--i);   //Delay 70us
	AckBit=OneWire_DQ;
	i = 227;while (--i);  //Delay 500us
	
	return AckBit;
	
}

/**
  * @brief 发送一位
  * @param Bit 发送的位数据
  * @retval 无
  */
void OneWire_SendBit(unsigned char Bit)
{
	unsigned char i;
	
	OneWire_DQ=0;
	i = 4;while (--i);   //Delay 10us
	OneWire_DQ=Bit;
	i = 22;while (--i);  //Delay 50us
	OneWire_DQ=1;
}

/**
  * @brief 接收一位
  * @param 无
  * @retval Bit 接收的位
  */
unsigned char OneWire_ReciveBit(void)
{
	unsigned char i;
	unsigned char Bit;
	
	OneWire_DQ=0;
	i = 2;while (--i);  //Delay 5us
	OneWire_DQ=1;
	i = 2;while (--i);  //Delay 5us
	Bit=OneWire_DQ;
	i = 22;while (--i);  //Delay 50us
	
	return Bit;
}

/**
  * @brief 发送一个字节
  * @param Byte 要发送的字节
  * @retval 无
  */
void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	
	for(i=0;i<8;i++)
	{
		OneWire_SendBit(Byte&(0x01<<i));
	}
}

/**
  * @brief 接收一个字节
  * @param 无
  * @retval Byte 接收到的字节
  */
unsigned char OneWire_ReceiveByte(void)
{
	unsigned char i;
	unsigned char Byte;
	
	for(i=0;i<8;i++)
	{
		if(OneWire_ReciveBit()){Byte|=(0x01<<i);}
	}
	
	return Byte;
}

OneWire.h

#ifndef __OneWire_H__
#define __OneWire_H__

unsigned char OneWire_Init(void);
void OneWire_SendBit(unsigned char Bit);
unsigned char OneWire_ReciveBit(void);
void OneWire_SendByte(unsigned char Byte);
unsigned char OneWire_ReceiveByte(void);

#endif 

3.13 DS18B20

DS18B20.c

#include <at89c51RC2.h>
#include <OneWire.h>

#define DS18B02_SKIP_ROM   0xCC
#define DS18B02_CONVERT_T   0x44
#define DS18B02_READ_SCRATCHPAD   0xBE

/**
  * @brief 温度变换
  * @param 无
  * @retval 无
  */
void DS18B20_ConvertT(void)
{
	OneWire_Init();
	OneWire_SendByte(DS18B02_SKIP_ROM);
	OneWire_SendByte(DS18B02_CONVERT_T);
}

/**
  * @brief 温度读取
  * @param 无
  * @retval T 当前温度
  */
float DS18B20_ReadT(void)
{
	unsigned char TLSB,TMSB;
	int Temp;
	float T;
	
	OneWire_Init();
	OneWire_SendByte(DS18B02_SKIP_ROM);
	OneWire_SendByte(DS18B02_READ_SCRATCHPAD);
	TLSB=OneWire_ReceiveByte();
	TMSB=OneWire_ReceiveByte();
	Temp=(TMSB<<8)|TLSB;
	T=Temp/16.0;
	
	return T;
}

3.14 XPT2046

3.14 XPT2046.h

#ifndef __XPT2046_H__
#define __XPT2046_H__

#define XPT2046_XP     0x9C  //0x8c
#define XPT2046_YP      0xDC
#define XPT2046_VBAT    0xAC
#define XPT2046_AUX     0xEC

unsigned int XPT2046_ReadAD(unsigned char Command);

#endif 

3.14 XPT2046.c

#include <at89c51RC2.h>
#include <LCD1602.h>
#include <XPT2046.h>
#include <Delay.h>

unsigned int ADValue;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"ADJ  NTC  RG");
	while(1)
	{
		ADValue=XPT2046_ReadAD(XPT2046_XP);
		LCD_ShowNum(2,1,ADValue,4);
		ADValue=XPT2046_ReadAD(XPT2046_YP);
		LCD_ShowNum(2,6,ADValue,4);
		ADValue=XPT2046_ReadAD(XPT2046_VBAT);
		LCD_ShowNum(2,11,ADValue,4);
		Delay(10);
	}
}

DS18B20.h

#ifndef __DS18B20_H__
#define __DS18B20_H__

void DS18B20_ConvertT(void);
float DS18B20_ReadT(void);

#endif 

4.LED灯相关

4.1 点亮一个LED

#include <at89c51RC2.h>

void main()
{
	P2 = 0xFE; //1111 1110
}

改变0x后的数值,即可改变LED的点亮状态。

4.2 LED闪烁

#include <at89c51RC2.h>
#include <INTRINS.H>
void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	while(1)
	{
		P2 = 0xAA;  //1010 1010
		Delay500ms();
		P2 = 0x55;  //0101 0101
		Delay500ms();
	}
}

4.3 LED流水灯

#include <at89c51RC2.h>
#include <INTRINS.H>
void Delay(xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void main()
{
	while(1)
	{
		P2 = 0x7F;  //0111 1111
		Delay(100);
		P2 = 0xBF;  //1011 1111
		Delay(100);
		P2 = 0xDF;  //1101 1111
		Delay(100);
		P2 = 0xEF;  //1110 1111
		Delay(100);
		P2 = 0xF7;  //1111 0111
		Delay(100);
		P2 = 0xFB;  //1111 1011
		Delay(100);
		P2 = 0xFD;  //1111 1101
		Delay(100);
		P2 = 0xFE;  //1111 1110
		Delay(100);
	}
}

5.独立按键相关

5.1 独立按键控制LED的亮灭(松开就灭版)

#include <at89c51RC2.h>
void main()
{
	if(P3_0==0) P2_0=0;
	else P2_0=1;
}

5.2 独立按键控制LED的亮灭(松开不灭版)

#include <at89c51RC2.h>
#include <INTRINS.H>
void Delay(xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
void main()
{
	while(1)
	{
		if(P3_0==0) 
		{
			Delay(20);
			while(P3_0==0); 
			Delay(20);
			P2_0=~P2_0;
		}
	}
}

5.3 独立按键控制LED显示二进制(亮着的灯表示二进制版)

#include <at89c51RC2.h>
#include <INTRINS.H>
void Delay(xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
void main()
{
	unsigned char LEDNum=0;
	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			LEDNum++;
			P2=~LEDNum;  
		}
	}
}

5.4 独立按键控制LED移位

#include <at89c51RC2.h>
#include <INTRINS.H>
void Delay(xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
void main()
{
	unsigned char LEDNum=0;
	P2=~0x01;
	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			if(LEDNum==0) LEDNum=7;
			else LEDNum--;
			P2 =~ (0x01<<LEDNum);
		}
		if(P3_0==0)
		{
			Delay(20);
			while(P3_0==0);
			Delay(20);
			LEDNum++;
			if(LEDNum>=8) LEDNum=0;
			P2 =~ (0x01<<LEDNum);
		}
	}
}

6.数码管

6.1 数码管的静态显示

#include <at89c51RC2.h>
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
void Nixie(unsigned char LED,Number)
{
	switch(LED)
	{  
		case 1: P2_4=0;P2_3=0;P2_2=0;break;
		case 2: P2_4=0;P2_3=0;P2_2=1;break;
		case 3: P2_4=0;P2_3=1;P2_2=0;break;
		case 4: P2_4=0;P2_3=1;P2_2=1;break;
		case 5: P2_4=1;P2_3=0;P2_2=0;break;
		case 6: P2_4=1;P2_3=0;P2_2=1;break;
		case 7: P2_4=1;P2_3=1;P2_2=0;break;
		case 8: P2_4=1;P2_3=1;P2_2=1;break;
	}
	P0=NixieTable[Number];
}	
void main()
{
	while(1)
	{
		Nixie(1,5);
	}
}

6.2 数码管动态显示(正常亮度版)

#include <at89c51RC2.h>
#include <INTRINS.H>
void Delay(xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
void Nixie(unsigned char LED,Number)
{
	switch(LED)
	{  
		case 1: P2_4=0;P2_3=0;P2_2=0;break;
		case 2: P2_4=0;P2_3=0;P2_2=1;break;
		case 3: P2_4=0;P2_3=1;P2_2=0;break;
		case 4: P2_4=0;P2_3=1;P2_2=1;break;
		case 5: P2_4=1;P2_3=0;P2_2=0;break;
		case 6: P2_4=1;P2_3=0;P2_2=1;break;
		case 7: P2_4=1;P2_3=1;P2_2=0;break;
		case 8: P2_4=1;P2_3=1;P2_2=1;break;
	}
	P0=NixieTable[Number];
	Delay(1);
	P0=0x00;
}	
void main()
{
	while(1)
	{
		Nixie(8,1);
		Nixie(7,2);
		Nixie(6,3);
	}
}

6.3 数码管动态显示(低亮度版)

#include <at89c51RC2.h>
#include <INTRINS.H>
void Delay(xms)		//@11.0592MHz
{
	unsigned char i, j;
	_nop_();
	while(xms)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
void Nixie(unsigned char LED,Number)
{
	switch(LED)
	{  
		case 1: P2_4=0;P2_3=0;P2_2=0;break;
		case 2: P2_4=0;P2_3=0;P2_2=1;break;
		case 3: P2_4=0;P2_3=1;P2_2=0;break;
		case 4: P2_4=0;P2_3=1;P2_2=1;break;
		case 5: P2_4=1;P2_3=0;P2_2=0;break;
		case 6: P2_4=1;P2_3=0;P2_2=1;break;
		case 7: P2_4=1;P2_3=1;P2_2=0;break;
		case 8: P2_4=1;P2_3=1;P2_2=1;break;
	}
	P0=NixieTable[Number];
	P0=0x00;
}	
void main()
{
	while(1)
	{
		Nixie(8,1);
		Nixie(7,2);
		Nixie(6,3);
	}
}

7.LCD1602

7.1 写命令函数

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

7.2 设置光标位置函数

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

7.3 初始化函数

void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

7.4 显示单个字符函数

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

7.5 显示单个字符函数(调用LCD1602头文件版)

#include <at89c51RC2.h>
#include <LCD1602.h>
void main()
{
	LCD_Init();
	LCD_ShowChar(1,1,"A");
	while(1)
	{
		
	}
}

7.6 显示多个字符函数

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

7.7 显示多个字符函数(调用LCD1602头文件版)

#include <at89c51RC2.h>
#include <LCD1602.h>
void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Hello");
	while(1)
	{
		
	}
}

7.8 显示十进制数字函数

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

7.9 显示十进制数字

#include <at89c51RC2.h>
#include <LCD1602.h>
void main()
{
	LCD_Init();
	LCD_ShowNum(1,9,123,3); 
	while(1)
	{
		
	}
}

7.10 显示有符号十进制数字函数

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

7.11 显示有符号十进制数字

#include <at89c51RC2.h>
#include <LCD1602.h>
void main()
{
	LCD_Init();
	LCD_ShowSignedNum(1,9,-123,2);
	while(1)
	{
		
	}
}

7.12 显示十六进制数字函数

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

7.13 显示十六进制数字

#include <at89c51RC2.h>
#include <LCD1602.h>
void main()
{
	LCD_Init();
	LCD_ShowHexNum(1,1,0xA6,2);
	while(1)
	{
		
	}
}

7.14 显示二进制数字函数

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}

7.15 显示二进制数字

#include <at89c51RC2.h>
#include <LCD1602.h>
void main()
{
	LCD_Init();
	LCD_ShowBinNum(1,3,0xAA,8);
	while(1)
	{
		
	}
}

8.矩阵键盘

8.1 矩阵键盘读取键盘键码

#include <Delay.h>为调用自定义的延时函数,可参考3.2。

#include <at89c51RC2.h>
#include <Delay.h>
/**
  * @brief 矩阵键盘读取键盘键码
  * @param 无
  * @retval  KeyNumber本人 按下按键的键码值
	如果按键按下不放,程序会停留在子函数,松手的一瞬间,返回按键的键码值,没有按键按下时,返回W
  */

unsigned char MatrixKey()
{
	unsigned char KeyNumber="W";
	
	P1=0xFF;
	P1_3=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=4;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=7;}
	
	P1=0xFF;
	P1_2=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=8;}
	if(P1_4==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=0;}
	
	P1=0xFF;
	P1_1=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
	
	return KeyNumber;
}

8.2 矩阵键盘

#include <Delay.h>为调用自定义的延时函数,可参考3.2。
#include <LCD1602.h>为调用自定义的LCD1602相关操作的函数,可参考3.1。
#include <MatriKey.h>为调用自定义的矩阵键盘读取键盘键码,可参考3.4。

以下为main.c文件中的

#include <at89c51RC2.h>
#include <Delay.h>
#include <LCD1602.h>
#include <MatriKey.h>

unsigned char KeyNum;
void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"MatrixKey:");
	while(1)
	{
		KeyNum=MatrixKey();
		if(KeyNum>=0 && KeyNum<=9)
		{
			LCD_ShowNum(2,1,KeyNum,1);
		}
	}
}

8.3 密码锁

#include <Delay.h>为调用自定义的延时函数,可参考3.2。
#include <LCD1602.h>为调用自定义的LCD1602相关操作的函数,可参考3.1。
#include <MatriKey.h>为调用自定义的矩阵键盘读取键盘键码,可参考3.4。

//MatriKey.h文件修改后
#include <at89c51RC2.h>
#include <Delay.h>
/**
  * @brief 矩阵键盘读取键盘键码
  * @param 无
  * @retval  KeyNumber本人 按下按键的键码值
	如果按键按下不放,程序会停留在子函数,松手的一瞬间,返回按键的键码值,没有按键按下时,返回W
  */

unsigned char MatrixKey()
{
	unsigned char KeyNumber="W";
	
	P1=0xFF;
	P1_3=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=4;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=7;}
	if(P1_4==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
	
	P1=0xFF;
	P1_2=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=8;}
	if(P1_4==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=0;}
	
	P1=0xFF;
	P1_1=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
	if(P1_4==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=1;}
	
	return KeyNumber;
}
//main.c文件
#include <at89c51RC2.h>
#include <Delay.h>
#include <LCD1602.h>
#include <MatriKey.h>

unsigned char KeyNum;
unsigned int True_Password=2470,Password=0,Count=0;
void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Password:");
	while(1)
	{
		KeyNum=MatrixKey();
		if(KeyNum>=0 && KeyNum<=9 && Count<4)
		{
			Password*=10;                 //密码左移一位
			Password+=KeyNum%10;			//获取一位密码
			Count++;
			LCD_ShowNum(2,1,Password,4);  //设置四位密码
		}
		if(KeyNum==10)
		{
			if(Password==True_Password) LCD_ShowString(1,11,"RIGHT");
			else 
			{
				LCD_ShowString(1,11,"ERROR");
				Delay(1000);
				Password=0;                     //密码清零
				Count=0;                        //计次清零
				LCD_ShowNum(2,1,Password,4);
				LCD_ShowString(1,11,"AGAIN");   //清空显示ERROR
			}
		}
		if(KeyNum==11)
		{
				Password=0;                     //密码清零
				Count=0;                        //计次清零
				LCD_ShowNum(2,1,Password,4);
		}
	}
}

9.计时器

#include <Key.h>为调用自定义的获取独立按键键码值相关操作的函数,可参考3.3。
#include <Timer0.h>为调用自定义的定时器初始化相关操作的函数,可参考3.5。

9.1 按键控制LED流水灯模式

#include <REGX52.h>
#include <Timer0.h>
#include <Key.h>
#include <INTRINS.h>


unsigned char KeyNum,LEDMod;

void main()
{
	P2=0xFE;
	Timer0_Init();
	while(1)
	{
		KeyNum=Key();
		if(KeyNum)
		{
			LEDMod++;
			if(LEDMod>=2) LEDMod=0;
		}
		
	}
}

void Timer0_Routine() interrupt 1  //溢出时中断
{
	static int T0Count;
	TL0 = 0x66;		 
	TH0 = 0xFC;
	T0Count++;
	if(T0Count>=1000)
	{
		T0Count=0;
		if(LEDMod==1) P2=_crol_(P2,1);  //循环左移一位
		if(LEDMod==0) P2=_cror_(P2,1);  //循环右移一位
	}
}

9.2 时钟

#include <LCD1602.h>为调用自定义的LCD1602相关操作的函数,可参考3.1。
#include <Timer0.h>为调用自定义的定时器初始化相关操作的函数,可参考3.5。

#include <at89c51RC2.h>
#include <LCD1602.h>
#include <Timer0.h>

unsigned char sec,min,hour;

void main()
{
	LCD_Init();
	Timer0_Init();
	
	LCD_ShowString(1,1,"Clock:");
	LCD_ShowString(2,1,"  :  :");
	
	while(1)
	{
		LCD_ShowNum(2,1,hour,2);
		LCD_ShowNum(2,4,min,2);
		LCD_ShowNum(2,7,sec,2);
		
	}
}


void Timer0_Routine() interrupt 1  //溢出时中断
{
	static int T0Count;
	TL0 = 0x66;		 
	TH0 = 0xFC;
	T0Count++;
	if(T0Count>=1000)
	{
		T0Count=0;
		sec++;             //秒数加1
		if(sec>=60)
		{
			sec=0;
			min++;
			if(min>=60)
			{
				min=0;
				hour++;
				if(hour>=24)
				{
					hour=0;
				}
			}
		}
	}		
}

10.串口通信

10.1 串口向电脑发送数据

#include <Delay.h>为调用自定义的延时函数,可参考3.2。
#include <UART.h>为调用自定义的串口通信相关函数,可参考3.6。

#include <at89c51RC2.h>
#include <Delay.h>
#include <UART.h>

unsigned char sec;

void main()
{
	UartInit_51();
	while(1)
	{
		Uart_SendByte(sec);
		sec++;
		Delay(100);
	}
}

10.2 电脑通过串口控制LED

#include <Delay.h>为调用自定义的延时函数,可参考3.2。
#include <UART.h>为调用自定义的串口通信相关函数,可参考3.6。

#include <at89c51RC2.h>
#include <Delay.h>
#include <UART.h>

unsigned char sec;

void main()
{
	UartInit_Device();
	while(1)
	{
		
	}
}

void UART_Routine(void) interrupt 4
{
	if(RI==1)      //单片机接收中断
  {
		P2=SBUF;
		Uart_SendByte(SBUF);
		RI=0;
	}
}

11.LED点阵屏

11.1 LED点阵显示图形

#include <at89c51RC2.h>
#include <MatrixLED.h>

void main()
{
	P3_6=0;
	P3_5=0;
	while(1)
	{
		MatrixLED_ShowColumn(0,0x3C);
		MatrixLED_ShowColumn(1,0x42);
		MatrixLED_ShowColumn(2,0xA9);
		MatrixLED_ShowColumn(3,0x85);
		MatrixLED_ShowColumn(4,0x85);
		MatrixLED_ShowColumn(5,0xA9);
		MatrixLED_ShowColumn(6,0x42);
		MatrixLED_ShowColumn(7,0x3C);
	}
}

11.2 LED点阵显示动画

#include <at89c51RC2.h>
#include <MatrixLED.h>

unsigned char Animatio[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0x08,0x08,0x08,0xFF,0x00,0x5F,
0x00,0xFD,0x00,0x00,0x00,0x00,0x00
};

void main()
{
	unsigned int i,offset=0,count=0;
	
	MatrixLED_Init();
	
	while(1) 
	{
		for(i=0;i<8;i++) MatrixLED_ShowColumn(i,Animatio[i+offset]);
		count++;
		if(count==10)
		{
			offset++;
			count=0;
			if(offset>=16)
			{
				offset=0;
			}
		}
	}
}

12.DS1302

12.1 时钟显示

#include <at89c51RC2.h>
#include <LCD1602.h>
#include <DS1302.h>

	
void main()
{
	LCD_Init();
	DS1302_Init();
	LCD_ShowString(1,1,"  -  - ");
	LCD_ShowString(2,1,"  :  : ");

	DS1302_SetTime();

	while(1)
	{
		DS1302_ReadTime();
		LCD_ShowNum(1,1,DS1302_Time[0],2);
		LCD_ShowNum(1,4,DS1302_Time[1],2);
		LCD_ShowNum(1,7,DS1302_Time[2],2);
		LCD_ShowNum(2,1,DS1302_Time[3],2);
		LCD_ShowNum(2,4,DS1302_Time[4],2);
		LCD_ShowNum(2,7,DS1302_Time[5],2);
		LCD_ShowNum(1,10,DS1302_Time[6],2);
	}
}

13.蜂鸣器

13.1 蜂鸣器播放提示音

#include <at89c51RC2.h>
#include <Key.h>
#include <Nixie.h>
#include <Delay.h>

sbit BEEP=P2^5;

unsigned char KeyNum,i;

void main()
{
	Nixie(1,0);
	while(1)
	{
		KeyNum=Key();
		if(KeyNum)
		{
			for(i=0;i<100;i++)
			{
				BEEP=!BEEP;
				Delay(1);
			}
			Nixie(1,KeyNum);
		}
	}
}

13.2 蜂鸣器播放音乐

#include <at89c51RC2.h>
#include <Timer0.h>
#include <Delay.h>

sbit BEEP=P2^5;

//三组 1 1# 2 2# 3 4 4# 5 5# 6 6# 7 一行12个
unsigned int FreqTable[]={
	63777,63872,63969,64054,64140,61216,64291,64360,64426,64489,64547,64607,
	64655,64704,64751,64795,64837,64876,64913,64948,64981,65012,65042,65070,
  65095,65120,65144,65166,65186,65206,65255,65242,65259,65274,65289,65303
}  ;

unsigned int Music[]={12,12,19,19,21,21,19,17,17,16,16,14,14,12};
unsigned char Music_Time[]={500,500,500,500,500,500,1000,500,500,500,500,500,500,1000};

unsigned int FreqSelect,MusicSelect,Music_TimeSelect;

void main()
{
	Timer0_Init();
	while(1)
	{
		if(Music[MusicSelect]!=0xFF && Music_Time[Music_TimeSelect]!=0xFF)
		{
		FreqSelect=Music[MusicSelect];
		MusicSelect++;
		Delay(Music_Time[Music_TimeSelect]);
		Music_TimeSelect++;
		TR0=0;
		Delay(5);
		TR0=1;
		}
		else
		{
			TR0=0;
			while(1);
		}
	}
}

void Timer0_Routine() interrupt 1  //溢出时中断
{
	TL0 = FreqTable[FreqSelect]%256;		 
	TH0 = FreqTable[FreqSelect]/256;
	BEEP=!BEEP;
}

14.AT24C02

14.1 AT24C02显示

#include <at89c51RC2.h>
#include <LCD1602.h>
#include <Key.h>
#include <AT24C02.h>
#include <Delay.h>

unsigned char KeyNum;
unsigned int Num;


void main()
{
	LCD_Init();
	LCD_ShowNum(1,1,Num,5);
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			Num++;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==2)
		{
			Num--;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==3)
		{
			AT24C02_WriteByte(0,Num%256);  //取出Num的低八位
			Delay(5);
			AT24C02_WriteByte(1,Num/256);  //取出Num的高八位
			Delay(5);
			LCD_ShowString(2,1,"Write success!");
			Delay(1000);
			LCD_ShowString(2,1,"              ");
		}
		if(KeyNum==4)
		{
			Num=AT24C02_ReadByte(0);        //获取低八位
			Num|=AT24C02_ReadByte(1)<<8;    //获取高八位
			LCD_ShowNum(1,1,Num,5);
			LCD_ShowString(2,1,"Read success!");
			Delay(1000);
			LCD_ShowString(2,1,"              ");
		}
	}
}

14.2 秒表(定时器扫描按键数码管)

#include <at89c51RC2.h>
#include <Timer0.h>
#include <Key.h>
#include <Nixie.h>
#include <Delay.h>

unsigned char KeyNum;
unsigned char Min,Sec,MiniSec;
unsigned char RunFlag;

void main()
{
	Timer0_Init();
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			
		}
		if(KeyNum==2)
		{
			Min=0;
			Sec=0;
			MiniSec=0;
		}
		if(KeyNum==3)
		{
			AT24C02_WriteByte(0,Min);
			Delay(5);
			AT24C02_WriteByte(1,Sec);
			Delay(5);
			AT24C02_WriteByte(2,MiniSec);
			Delay(5);
		}
		if(KeyNum==4)
		{
			Min=AT24C02_ReadByte(0);
			sec=AT24C02_ReadByte(1);
			MiniSec=AT24C02_ReadByte(2);
		}
		Nixie_SetBuf(1,Min/10);
		Nixie_SetBuf(2,Min%10);
		Nixie_SetBuf(3,17);
		Nixie_SetBuf(4,Sec/10);
		Nixie_SetBuf(5,Sec%10);
		Nixie_SetBuf(6,17);
		Nixie_SetBuf(7,MiniSec/10);
		Nixie_SetBuf(8,MiniSec%10);
	}
}

void Sec_Loop(void)
{
	MiniSec++;
	if(MiniSec>=100)
	{
		MiniSec=0;
		Sec++;
		if(Sec>=60)
		{
			Sec=0;
			Min++;
			if(Min>=60)
			{
				Min=0;
			}
		}
	}
}
void Timer0_Routine() interrupt 1  //溢出时中断
{
	static int T0Count1,T0Count2,T0Count3;
	TL0 = 0x66;		 
	TH0 = 0xFC;
	T0Count1++;
	if(T0Count1>=20)
	{
		T0Count1=0;
		Key_Loop();
	}		
	T0Count2++;
	if(T0Count2>=3)
	{
		T0Count2=0;
		Nixie_Loop();
	}	
	T0Count3++;
	if(T0Count3>=10)
	{
		T0Count3=0;
		Sec_Loop();
	}	
}

15.DS18B20

15.1 温度读数

#include <at89c51RC2.h>
#include <LCD1602.h>
#include <DS18B20.h>

float T;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Temperature:");
	while(1)
	{
		DS18B20_ConvertT();
		T=DS18B20_ReadT();
		if(T<0)
		{
			LCD_ShowChar(2,1,'-');
			T=-T;
		}
		else
		{
			LCD_ShowChar(2,1,'+');
		}
		LCD_ShowNum(2,2,T,3);
		LCD_ShowChar(2,5,'.');
		LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,3);
	}
}

15.2 温度报警

#include <at89c51RC2.h>
#include <LCD1602.h>
#include <DS18B20.h>
#include <Key.h>
#include <AT24C02.h>
#include <Delay.h>

float T,TShow;
char TLow,THigh;
unsigned char KeyNum;

void main()
{
	DS18B20_ConvertT();
	Delay(1000);
	THigh=AT24C02_ReadByte(0);
	TLow=AT24C02_ReadByte(1);
	if(THigh>125 || TLow<-55 || THigh<=TLow)
	{
		THigh=30;
		TLow=-10;
	}
	
	LCD_Init();
	
	LCD_ShowString(1,1,"T:");
	LCD_ShowString(2,1,"TH:");
	LCD_ShowString(2,9,"TL:");
	
	
	while(1)
	{
		KeyNum=Key();
		
		/*温度读取及显示*/
		DS18B20_ConvertT();
		T=DS18B20_ReadT();
		
		if(T<0)
		{
			LCD_ShowChar(1,3,'-');
			TShow=-T;
		}
		else
		{
			LCD_ShowChar(1,3,'+');
			TShow=T;
		}
		LCD_ShowNum(1,4,TShow,3);
		LCD_ShowChar(1,7,'.');
		LCD_ShowNum(1,8,(unsigned long)(TShow*10000)%10000,3);
		
		/*阈值判断及显示*/
		if(KeyNum)
		{
			if(KeyNum==1)
			{
				THigh++;
				if(THigh>125){THigh=125;}
			}
			if(KeyNum==2)
			{
				THigh--;
				if(THigh<=TLow){THigh++;}
			}
			if(KeyNum==3)
			{
				TLow++;
				if(THigh<=TLow){TLow--;}
			}
			if(KeyNum==4)
			{
				TLow--;
				if(THigh<-55){TLow=-55;}
			}
		}
		LCD_ShowSignedNum(2,4,THigh,3);
		LCD_ShowSignedNum(2,12,TLow,3);
	if(T>THigh)
	{
		LCD_ShowString(1,13,"OV:H");
	}
	else if(T<TLow)
	{
		LCD_ShowString(1,13,"OV:L");
	}
	else
	{
		LCD_ShowString(1,13,"    ");
	}
	}
	
}

16.直流电机

16.1 LED呼吸灯

#include <at89c51RC2.h>

void Delay(unsigned int i)
{
	while(i--);
}

void main()
{
	unsigned char Time,i;
	while(1)
	{
		for(Time=0;Time<100;Time++)
		{
			for(i=0;i<20;i++)
			{
				P2_0=0;
				Delay(Time);
				P2_0=1;
				Delay(100-Time);
			}
		}
		for(Time=100;Time>0;Time--)
		{
			for(i=0;i<20;i++)
			{
				P2_0=0;
				Delay(Time);
				P2_0=1;
				Delay(100-Time);
			}
		}
	}
}

16.2 直流电机调试

#include <at89c51RC2.h>
#include <Timer0.h>
#include <Key.h>
#include <Nixie.h>

sbit Motor=P1^0;

unsigned char Counter,Compare;
unsigned char KeyNum,Speed;
 
void main()
{
	Motor=0;
	Timer0_Init();
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			Speed++;
			Speed%=4;
			if(Speed==0) {Compare=0;}
			if(Speed==1) {Compare=50;}
			if(Speed==2) {Compare=75;}
			if(Speed==3) {Compare=100;}
		}
		Nixie(1,Speed);
	}
}

void Timer0_Routine() interrupt 1  //溢出时中断
{
	TL0 = 0xAE;		
	TH0 = 0xFB;
	Counter++;
	Counter%=100;    //Counter到100了
	if(Counter<Compare)
	{
		Motor=1;
	}
	else
	{
		Motor=0;
	}
}

17.AD/DA

17.1 AD转换

#include <at89c51RC2.h>
#include <LCD1602.h>
#include <XPT2046.h>
#include <Delay.h>

unsigned int ADValue;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"ADJ  NTC  RG");
	while(1)
	{
		ADValue=XPT2046_ReadAD(XPT2046_XP);
		LCD_ShowNum(2,1,ADValue,4);
		ADValue=XPT2046_ReadAD(XPT2046_YP);
		LCD_ShowNum(2,6,ADValue,4);
		ADValue=XPT2046_ReadAD(XPT2046_VBAT);
		LCD_ShowNum(2,11,ADValue,4);
		Delay(10);
	}
}
  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值