代码整理
- 前言
- 1.预处理框架
- 2.自定义函数
- 3.相关自定义的头文件
- 4.LED灯相关
- 5.独立按键相关
- 6.数码管
- 7.LCD1602
- 8.矩阵键盘
- 9.计时器
- 10.串口通信
- 11.LED点阵屏
- 12.DS1302
- 13.蜂鸣器
- 14.AT24C02
- 15.DS18B20
- 16.直流电机
- 17.AD/DA
前言
本文是关于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);
}
}