目录
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);
}
}