目录
LCD1602
LCD1602液晶显示屏
直流电机驱动(PWM)
LED呼吸灯
直流电机调速
AD/DA(SPI通信)
AD模数转换
DA数模转换
红外遥控(外部中断)
红外遥控
红外遥控电机调速
LCD1602











LCD1602液晶显示屏
LCD1602.c
#include <REGX52.H>
#include "intrins.h"
sbit LCD_RS = P2^6;//引脚定义
sbit LCD_WR = P2^5;
sbit LCD_EN = P2^7;
#define LCD_DataPort 	P0//寄存器定义,define不要使用分号
void LCD_Delay()		//@11.0592MHz,2ms
{
	unsigned char i, j;
	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j) ;
	} while (--i);
}
/**
  * @brief  写指令
  * @param  Command	指令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)//写指令
{
	LCD_RS = 0;//1为数据,0为指令
	LCD_WR = 0;//1为读,0为写
	LCD_DataPort = Command;//放入指令
	LCD_EN = 1;//使能
	LCD_Delay();//延时一毫秒
	LCD_EN = 0;//结束使能
	LCD_Delay();
}
/**
  * @brief  写数据
  * @param  Data	数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)//写数据
{
	LCD_RS = 1;//1为数据,0为指令
	LCD_WR = 0;//1为读,0为写
	LCD_DataPort = Data;//放入数据
	LCD_EN = 1;//使能
	LCD_Delay();//延时一毫秒
	LCD_EN = 0;//结束使能
	LCD_Delay();
}
/**
  * @brief  初始化显示屏
  * @param  无
  * @retval 无
  */
void LCD_Init(void) 
{
	LCD_WriteCommand(0x38);//八位数据,两行显示,5*7点阵
	LCD_WriteCommand(0x0C);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//清屏
}
/**
  * @brief  移动光标到目标位置
  * @param  Line行	Column列
  * @retval	无 
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)//设置光标位置
{
	if(Line == 1)
	{
		LCD_WriteCommand(0x80|(Column - 1));//如果是第一行,那么实际地址即为列-1,
		//并设置光标位置,为什么是0x80,地址设置DDRAM
	}
	else
	{
		LCD_WriteCommand(0x80|(Column - 1) + 0x40);//如果是第二行,则进行偏移0x40即为实际地址
		//并设置光标位置
	}
}
/**
  * @brief  显示字符
  * @param  Line	行	
	* @param 	Column	列	
	* @param	Char	显示的字符	
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);//写入数据
}
/**
  * @brief  显示字符串
  * @param  Line	行	
	* @param 	Column	列	
	* @param	String	显示的字符串	
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column, unsigned char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i = 0;String[i] != '\0';i++)//遍历字符串String
	{
		LCD_WriteData(String[i]);//写入数据
	}
}
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result = 1;
	for( i=0;i<Y;i++)
	{
		Result *= X;//X^Y
	}
	return Result;
}
/**
  * @brief  显示无符号数字
  * @param  Line	行	
	* @param 	Column	列	
	* @param	Num	显示的无符号数字	
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Num,unsigned char Len)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Len ; i>0 ;i--)
	{
		//LCD_WriteData(0x30 + Num / LCD_Pow(10,i-1)%10);	//获取各位数值并写入显示屏
		LCD_WriteData('0' + Num / LCD_Pow(10,i-1)%10);
		//或者转化为ascii码
	}
}
/**
  * @brief  显示有符号数字
  * @param  Line	行	
	* @param 	Column	列	
	* @param	Num	显示的有符号数字	
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Num,unsigned char Len)
{
	unsigned char i;
	unsigned int Num1;
	LCD_SetCursor(Line,Column);
	if(Num >= 0 )
	{
		LCD_WriteData('+');
		Num1 = Num;
	}
	else{
		LCD_WriteData('-');
		Num1 = -Num;
	}
	for(i=Len ; i>0 ;i--)
	{
		//LCD_WriteData(0x30 + Num / LCD_Pow(10,i-1)%10);	//获取各位数值并写入显示屏
		LCD_WriteData('0' + Num1 / LCD_Pow(10,i-1)%10);
		//或者转化为ascii码
	}
}
/**
  * @brief  显示十六进制数字
  * @param  Line	行	
	* @param 	Column	列	
	* @param	Num	显示的十六进制数字	
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Num,unsigned char Len)
{
	unsigned char i;
	unsigned char SingleNum;
	LCD_SetCursor(Line,Column);
	for(i=Len ; i>0 ;i--)
	{
		SingleNum = Num / LCD_Pow(16,i-1)%16;
		if(SingleNum < 10){
				LCD_WriteData('0' + SingleNum);
			//获取各位数值并写入显示屏
		}
		else
		{
				LCD_WriteData('A' + SingleNum - 10);//修改偏移量
		}
	}
}
/**
  * @brief  显示二进制数字
  * @param  Line	行	
	* @param 	Column	列	
	* @param	Num	显示的二进制数字	
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Num,unsigned char Len)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Len ; i>0 ;i--)
	{
		LCD_WriteData('0' + Num / LCD_Pow(2,i-1)%2);
	} 
} 
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
void main(){
		LCD_Init();
	LCD_ShowChar(1,1,'A');//显示字符A
	LCD_ShowString(1,3,"Hello");//显示字符串
	LCD_ShowNum(1,9,66,2);//显示无符号数字
	LCD_ShowSignedNum(1,12,-66,2);//显示有符号数字
	LCD_ShowHexNum(2,1,0xA5,2);//显示十六进制
	LCD_ShowBinNum(2,4,0xA5,8);//显示二进制
	LCD_ShowChar(2,13,0xDF);//显示度数符号
	LCD_ShowChar(2,14,'C');//显示字符C
	
	LCD_ShowString(1,16,"Welcome to China!");
	while( 1 ){
		LCD_WriteCommand(0x18);//流动字幕(指令集)
		Delay(500);
	}
} 
直流电机驱动(PWM)




LED呼吸灯
main.c
#include <REGX52.H>
sbit LED = P2^0;
void Delay(unsigned int t)
{
	while(t--);
}
void main(){
	unsigned char Time,i;
	while( 1 ){
		
		for(Time = 0; Time < 100;Time++)
		{
			for(i = 0; i < 20;i++)
			{
				LED = 0;
				Delay(Time);
				LED = 1;
				Delay(100 - Time);
			}
			
		}
		for(Time = 100; Time > 0;Time--)
		{
			for(i = 0; i < 20;i++)
			{
				LED = 0;
				Delay(Time);
				LED = 1;
				Delay(100 - Time);
			}
			
		}
		
		
	}
} 
直流电机调速
main.c
#include <REGX52.H>
#include "Delay.h"
#include "Nixie.h"
#include "Key.h"
#include "Timer0.h"
unsigned char Counter,Compare;
unsigned char KeyNum,Speed;
sbit Motor = P1^0;//ULN2003D
void main(){
	Timer0Init();
	//Compare值看自己如何设置,主要看与之比较后你想输出高/低电平,
    //这里是小于输出高电平
	while( 1 ){
		KeyNum = Key();
		if(KeyNum == 1)
		{
			Speed++;
			Speed %= 4;//重置为0
			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 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
//100us定时器
	Counter++;
	Counter %= 100;//将Counter刷新为0
	
	if(Counter < Compare)
	{
		Motor = 1;//高电平转
	}else
	{
		Motor = 0;
	}
} 
AD/DA(SPI通信)












AD模数转换
ET2046.c
#include <REGX52.H>
#include "Delay.h"
sbit ET2046_CS = P3^5;
sbit ET2046_DCLK = P3^6;
sbit ET2046_DIN = P3^4;
sbit ET2046_DOUT = P3^7;
/**
  * @brief  相当于当过电阻变化,来输出一些数据
  * @param  Command	控制字
  * @retval ADValue	读取到的数据
  */
unsigned int ET2046_ReadAD(unsigned char Command)//控制字
{
	unsigned char i;
	unsigned int ADValue = 0;
	ET2046_DCLK = 0;
	ET2046_CS = 0;//拉低进入时序
	
	for(i = 0; i<8 ; i++)//发送一个字节
	{
		ET2046_DIN = Command & (0x80 >> i);//获得最高位并将其放入DIN
		ET2046_DCLK = 1;
		ET2046_DCLK = 0;
	}
	for(i = 0; i < 16;i++)//读取两个字节长度
	{
		ET2046_DCLK = 1;
		ET2046_DCLK = 0;
		if(ET2046_DOUT)
		{
			ADValue |= (0x8000>>i);//提前给三位
		}
		Delay(50);
	}
		
	ET2046_CS = 1;//结束时序
	if(Command & 0x08)//查看为什么模式,若得出为1,则是12位。0则为8位
	{
		return ADValue>>8;
	}
	else{
		return ADValue>>4;
	}
} 
ET2046.h
#ifndef __ET2046_H__
#define __ET2046_H__
#define ET2046_XP_8				0x9C//0x8C
#define ET2046_YP_8				0xDC
#define ET2046_VBAT_8			0xAC
#define ET2046_AUX_8			0xEC
#define ET2046_XP_12				0x94//0x84
#define ET2046_YP_12				0xD4
#define ET2046_VBAT_12			0xA4
#define ET2046_AUX_12				0xE4
	unsigned int ET2046_ReadAD(unsigned char Command);
#endif 
 
main.c
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "ET2046.h"
unsigned int ADValue;
void main(){
		LCD_Init();
	LCD_ShowString(1,1,"ADJ  NTC  RG");
	
	while( 1 ){
		ADValue = ET2046_ReadAD(ET2046_XP_8);//XP
		LCD_ShowNum(2,1,ADValue,3);
		ADValue = ET2046_ReadAD(ET2046_YP_8);//YP
		LCD_ShowNum(2,6,ADValue,3);
		ADValue = ET2046_ReadAD(ET2046_VBAT_8);//
		LCD_ShowNum(2,11,ADValue,3);
		Delay(10);
	}
} 
DA数模转换
main.c
#include <REGX52.H>
#include "Delay.h"
#include "Nixie.h"
#include "Key.h"
#include "Timer0.h"
unsigned char Counter,Compare;
sbit DA = P2^1;//DA
unsigned char i;
void main(){
	Timer0Init();
	//Compare值越小LED越暗
	while( 1 ){
		
		for(i = 0;i < 100;i++)
		{
			Compare = i;
			Delay(10);
		}
		for(i = 100;i > 0;i--)
		{
			Compare = i;
			Delay(10);
		}
	}
}
void Timer0_Routine() interrupt 1{
	
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter %= 100;//将Counter刷新为0
	
	if(Counter < Compare)
	{
		DA = 1;
	}else
	{
		DA = 0;
	}
} 
红外遥控(外部中断)








红外遥控
Int0.c
#include <REGX52.H>
/**
  * @brief  外部中断0初始化
  * @param  无
  * @retval 无
  */
void Int0_Init(void)
{
	IT0 = 1;//1下降沿触发,0低电平触发
	IE0 = 0;//中断标志
	EX0 = 1;//打开中断
	EA = 1;//允许所有中断
	PX0	=	1;//中断优先级
}
	
/*外部中断0函数模板
void Int0_Routine(void) interrupt 0
{
	Num++;
	
}	
	
*/
 
Timer0.c
#include <REGX52.H>
/**
  * @brief  定时器0初始化
  * @param  无
  * @retval 无
  */
void Timer0_Init(void)		//1微秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0;		//设置定时初值
	TH0 = 0;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0开始计时
}
/**
  * @brief  定时器0设置计数器值
  * @param  Value,要设置的计数器值,范围:0~65535
  * @retval 无
  */
void Timer0_SetCounter(unsigned int Value)
{
	TH0 = Value / 256;
	TL0 = Value % 256;
}
/**
  * @brief  定时器0获取计数器值
  * @param  无
  * @retval 计数器值,范围:0~65535
  */
unsigned int Timer0_GetCounter(void)
{
	return (TH0 << 8 )| TL0;
}
/**
  * @brief  定时器0启动停止控制
  * @param  Flag 启动停止标志,1为启动,0为停止
  * @retval 无
  */
void Timer0_Run(unsigned char Flag)
{
	TR0 = Flag;
} 
main.c
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
unsigned char Num;
unsigned char Address;
unsigned char Command;
void main(){
	LCD_Init();
	LCD_ShowString(1,1,"ADDR   CMD   NUM");
	LCD_ShowString(2,1,"00     00    000");
	
	IR_Init();
	
	while( 1 ){
		if(IR_GetDataFlag() || IR_GetRepeatFlag())//如果收到数据帧或者连续发送
		{
			Address = IR_GetAddress();//获取遥控器地址码
			Command = IR_GetCommand();//获取遥控器命令码
			
			LCD_ShowHexNum(2,1,Address,2);//显示遥控器地址码
			LCD_ShowHexNum(2,8,Command,2);//显示遥控器命令码
			
			if(Command == IR_VOL_MINUS)//如果遥控器VOL-按键按下
			{
				Num --;
			}
			if(Command ==IR_VOL_ADD)//如果遥控器VOL+按键按下
			{
				Num ++;
			}
			LCD_ShowNum(2,14,Num,3);
		}
	}
}
 
红外遥控电机调速
Timer1.c
#include <REGX52.H>
/**
  * @brief  定时器1初始化,100微秒
  * @param  无
  * @retval 无
  */
void Timer1Init(void)		//100微秒@11.0592MHz
{
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;		//设置定时器模式
	TL1 = 0xA4;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	
	ET1 = 1;	
	EA = 1;
	PT1 = 0;
}
/*	定时器中断函数模板
void Timer1_Routine() interrupt 3{
	static unsigned int T1Count;
	
	TL0 = 0xA4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	T1Count ++;
	if( T1Count >= 1000 ){
		T1Count = 0;
	}
}
*/ 
Timer0.c
#include <REGX52.H>
/**
  * @brief  定时器0初始化
  * @param  无
  * @retval 无
  */
void Timer0_Init(void)		//1微秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0;		//设置定时初值
	TH0 = 0;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0开始计时
}
/**
  * @brief  定时器0设置计数器值
  * @param  Value,要设置的计数器值,范围:0~65535
  * @retval 无
  */
void Timer0_SetCounter(unsigned int Value)
{
	TH0 = Value / 256;
	TL0 = Value % 256;
}
/**
  * @brief  定时器0获取计数器值
  * @param  无
  * @retval 计数器值,范围:0~65535
  */
unsigned int Timer0_GetCounter(void)
{
	return (TH0 << 8 )| TL0;
}
/**
  * @brief  定时器0启动停止控制
  * @param  Flag 启动停止标志,1为启动,0为停止
  * @retval 无
  */
void Timer0_Run(unsigned char Flag)
{
	TR0 = Flag;
} 
Motor.c
#include <REGX52.H>
#include "Timer1.h"
sbit Motor = P1^0;//ULN2003D
unsigned char Counter,Compare;
/**
  * @brief  电机初始化
  * @param  无
  * @retval 无
  */
void Motor_Init()
{
	Timer1Init();
}
/**
  * @brief  电机设置速度
  * @param  Speed 要设置的速度,范围0~100
  * @retval 无
  */
void Motor_SetSpeed(unsigned char Speed)
{
	Compare = Speed;
}
void Timer1_Routine() interrupt 3{
	
	TL1 = 0xA4;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
	Counter++;
	Counter %= 100;//将Counter刷新为0
	
	if(Counter < Compare)
	{
		Motor = 1;//高电平转
	}else
	{
		Motor = 0;
	}
} 
main.c
#include <REGX52.H>
#include "Delay.h"
#include "Nixie.h"
#include "Key.h"
#include "Motor.h"
#include "IR.h"
unsigned char Command,Speed;
void main(){
	Motor_Init();
	IR_Init();
	while( 1 ){
		
		if(IR_GetDataFlag())//如果收到数据帧
		{
			Command = IR_GetCommand();//获取遥控器命令码
			
			if(Command == IR_0){Speed = 0;}	//根据遥控器命令码设置速度
			if(Command == IR_1){Speed = 1;}
			if(Command == IR_2){Speed = 2;}
			if(Command == IR_3){Speed = 3;}
			
			if(Speed==0){Motor_SetSpeed(0);}//速度输出
			if(Speed==1){Motor_SetSpeed(50);}
			if(Speed==2){Motor_SetSpeed(75);}
			if(Speed==3){Motor_SetSpeed(100);}
		}
		Nixie(1,Speed);
	}
}
 
                

















