大学时积累的51库函数,包含常用外设及传感器的操作

 

一、前言

记得那是刚上大一的时候,学校电子设计创新实验室的学长们自发的组织单片机技能培训,每次周末都会安排几个小时的培训,那时候自学了C语言,开始了自己的单片机之旅,记得那时候拿着个51单片机控制LED跑流水灯、做个避障小车什么的还挺好玩的,大一下学期加入了实验室,在学长的建议下积累下来了当时的一些模块代码,做成了一套属于自己的库函数,整套代码注释非常详细,都是自己当时用心一个字一个字手敲上去的,通过那段时间对51单片机的学习,接触到了各种各样的常用传感器模块和单片机技术,受益良多。现在很难用到51单片机了,最近又找到了这套代码,于是分享出来,大家觉得有帮助的可以自己下载。

 

二、工程涉及到的模块

1、较为精确的软件延时函数

2、定时器

3、中断

4、I2C协议

5、SPI协议

6、LCD1602液晶

7、LCD12864液晶

8、PCF8591 AD和DA模块

9、DS18B20温度传感器

10、DS1302时钟

11、IR红外解码

12、RS232串口通信

13、AT24C02 存储模块

14、数码管显示

15、PWM产生

16、超声波模块

17、TFT点阵屏显示

18、GUI绘图函数

19、ASCII字库显示、中文显示

20、图片显示。

21、NRF24L01 2.4G无线通信模块

22、TFT点阵屏贪吃蛇游戏

 

 

三、代码一览

这里贴上来一些代码预览一下:

外部中断

#include "interrupt.h"

/****************************************************
  函数名称: Interrupt_Falling
  函数简介: 配置外部中断下降沿触发函数
  入口参数: Interrupt_Num 外部中断号
						 Interrupt_NVIC 中断优先级(NVIC_Low或NVIC_High)
  出口参数: 无
  其他:    下降沿触发是通常外部中断的用法,中断后要处
						理的数据自己在exti.c中编写。
*****************************************************/
void Interrupt_Falling(u8 Interrupt_Num,NVIC_Select Interrupt_NVIC)
{
	if(Interrupt_Num==0)
	{
		IT0=1;  //下降沿触发
		EX0=1;  //开中断0
		EA=1;  //开总中断
		PX0=Interrupt_NVIC;  //外部中断0优先级 1高优先级,0低优先级
	}
	else
	{
		IT1=1;  //下降沿触发
		EX1=1;  //开中断1
		EA=1;  //开总中断
		PX1=Interrupt_NVIC;  //外部中断1优先级 1高优先级,0低优先级
	}
}

/****************************************************
  函数名称: Interrupt_Stop
  函数简介: 禁止中断函数
  入口参数: Interrupt_Num 外部中断号
  出口参数: 无
  其他:    无
*****************************************************/
void Interrupt_Stop(u8 Interrupt_Num)
{
	if(Interrupt_Num==0)
	{
		EX0=0;  //关中断0
	}
	else
	{
		EX1=0;  //关中断1
	}
}

LCD1602

#ifndef _LCD1602_H
#define _LCD1602_H
#include "public.h"

/***********管脚定义**********************************************/
sbit LCD1602_E=P2^7;
sbit LCD1602_RS=P2^6;
sbit LCD1602_RW=P2^5;
#define LCD1602_Dataport P0

/**********宏定义命令控制*****************************************/
#define Com_ClearScreen           0x01  //清显示
#define Com_CursorReturn          0x02  //光标返回
#define Com_CursorAndDisplayMode  0x40  //置输入模式
#define Com_DisplayOnOff          0x80  //显示开/关控制
#define Com_CursorOrDisplayMove   0x10  //光标或字符移位
#define Com_SetFuntion            0x20  //置功能
#define Com_SetRamAdd             0x40  //置字符发生存贮器地址
#define Com_SetDDRamAddr          0x80  //置数据存贮器地址

/***********函数声明*****************************************/  
void LCD1602_CheckBusy(void);														//判忙函数
void LCD1602_WriteCom(uchar com);                       //写命令函数
void LCD1602_WriteDat(uchar dat);                       //写数据函数
void LCD1602_WriteAddress(uchar x,uchar y);             //写地址函数
void LCD1602_WriteString(uchar x,uchar y,uchar *str);   //写字符串函数
void LCD1602_Init(void);                                //初始化函数

#endif

#include "LCD1602.h"

/****************************************************
  函数名称: LCD1602_CheckBusy
  函数简介: 判忙函数
  入口参数: 无
  出口参数: 无
  其他:    无
*****************************************************/
void LCD1602_CheckBusy(void)
{
	LCD1602_Dataport=0x00;
	LCD1602_E=0;
	LCD1602_RS=0;
	LCD1602_RW=1;
	LCD1602_E=1;
	while(LCD1602_Dataport&0x80);
	LCD1602_E=0;
}

/****************************************************
  函数名称: LCD1602_WriteCom
  函数简介: 写命令函数
  入口参数: com,待写入命令
  出口参数: 无
  其他:    无
*****************************************************/
void LCD1602_WriteCom(uchar com)
{
	LCD1602_CheckBusy();
	LCD1602_E=0;
	LCD1602_RS=0;
	LCD1602_RW=0;
	LCD1602_Dataport=com;
	LCD1602_E=1;
	delay_ms(5);
	LCD1602_E=0;
}

/****************************************************
  函数名称: LCD1602_WriteDat
  函数简介: 写数据函数
  入口参数: dat,待写入数据
  出口参数: 无
  其他:    无
*****************************************************/
void LCD1602_WriteDat(uchar dat)
{
	LCD1602_CheckBusy();
	LCD1602_E=0;
	LCD1602_RS=1;
	LCD1602_RW=0;
	LCD1602_Dataport=dat;
	LCD1602_E=1;
	delay_ms(5);
	LCD1602_E=0;
}

/****************************************************
  函数名称: LCD1602_WriteAddress
  函数简介: 写地址函数
  入口参数: x列地址0~15,y行地址0~1
  出口参数: 无
  其他:    无
*****************************************************/
void LCD1602_WriteAddress(uchar x,uchar y)
{
	if(y==0)
		x+=0x80;
	else
		x+=0xc0;
	LCD1602_WriteCom(x);
}

/****************************************************
  函数名称: LCD1602_WriteString
  函数简介: 写字符串函数
  入口参数: x列地址0~15,y行地址0~1,str待写入字符
						 串地址指针
  出口参数: 无
  其他:    注意计算好对应的显示位数,避免字符写入错
						误的地址
*****************************************************/
void LCD1602_WriteString(uchar x,uchar y,uchar *str)
{
	LCD1602_WriteAddress(x,y);
	while(*str!=0)
	{
	LCD1602_WriteDat(*str);
	str++;
	}
}

/****************************************************
  函数名称: LCD1602_Init
  函数简介: 初始化函数
  入口参数: 无
  出口参数: 无
  其他:    无
*****************************************************/
void LCD1602_Init(void)
{
  LCD1602_WriteCom(0x38);  //开显示
	LCD1602_WriteCom(0x0c);  //开显示不显示光标
	LCD1602_WriteCom(0x06);  //写一个指针加1
	LCD1602_WriteCom(0x01);  //清屏
	LCD1602_WriteCom(0x80);  //设置数据指针起点

}

IR红外解码

#ifndef _IR_H
#define _IR_H
#include "public.h"

/*************管脚定义***************************************/
sbit IR_DP=P3^2;  //红外传感器数据线

/*************变量定义***************************************/
extern u8 IR_OK;              //红外信号接收完成标志
extern u8 IR_Dat[4];  //存储红外解码的数据(用户码,用户反码,数据码,数据反码)

/*************函数声明***************************************/
void delay800us(void);  //延时函数
void IR_Init(void);                  //红外接收初始化函数
//void IR_Interrupt0() interrupt 0;  //外部中断0中断服务函数

#endif


#include "IR.h"

/****************************************************
  注意:红外接收头信号线发出的电平信号和接收的是相反的
				即接收到的红外信号编码其实和遥控发出来的红外信
				号是各位取反的关系。
*****************************************************/

u8 IR_OK=0;              //红外信号接收完成标志
u8 IR_Dat[4]={0,0,0,0};  //存储红外解码的数据(用户码,用户反码,数据码,数据反码)

/****************************************************
  函数名称: delay800us
  函数简介: 延时函数
  入口参数: 无
  出口参数: 无
  其他:    800us延时可以区分出信号0和1
*****************************************************/
void delay800us(void)
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=2;b>0;b--)
            for(a=197;a>0;a--);
}

/****************************************************
  函数名称: IR_Init
  函数简介: 红外接收初始化函数
  入口参数: 无
  出口参数: 无
  其他:    调用此函数对红外接收做好配置,注意每接收一
						次红外数据都要初始化一次(调用一次该函数)
*****************************************************/
void IR_Init(void)
{
	u8 i;
	IR_DP=1;    //先把红外传感器数据线拉高
	IT0=1;      //中断0,下降沿触发
	EX0=1;      //开中断0
	EA=1;       //开总中断
	for(i=0;i<4;i++)
	{
			IR_Dat[i]=0;  //清除红外数据,注意一定要清除,否则中断中用移位的方式接收数据时会出错。
	}
	IR_OK=0;    //接收完成标志置0(未接收)
}

/****************************************************
  函数名称: IR_Interrupt0
  函数简介: 外部中断0中断服务函数
  入口参数: 无
  出口参数: 无
  其他:    调用此函数进行红外解码,注意使用红外解码时
							在exti.c中注释掉相应的外部中断0,避免冲突
*****************************************************/
void IR_Interrupt0() interrupt 0
{
	u8 i;
	u16 temp;  //等待时间控制变量
	if(IR_DP==0&&IR_OK==0)  //如果红外接收头数据线确实是低电平且红外数据未接收
	{
		EX0=0;  //关外部中断0,防止中断不断进入
		while(!IR_DP)    //等待9ms的低电平过去
		{
			temp++;
			if(temp>10000)  //如果等待时间超出正常范围,直接退出中断,避免程序死在这里
			{
				EX0=1;  //接收到错误信号后要重新打开中断,否则下次接收不了红外信号
				return;
			}
		}
		temp=0;
		while(IR_DP)     //等待4.5ms的高电平过去
		{
			temp++;
				if(temp>10000)  //如果等待时间超出正常范围,直接退出中断,避免程序死在这里
				{
					EX0=1;  //接收到错误信号后要重新打开中断,否则下次接收不了红外信号
					return;
				}
		}
		temp=0;
		for(i=0;i<32;i++)
		{
			IR_Dat[i/8]>>=1;  //数据是从低位开始发送的,所以向右移位
			while(!IR_DP)  //等待0.56ms低电平过去,因为数据0和1前部分都是0.56ms低电平,无区分度
			{
				temp++;
				if(temp>10000)  //如果等待时间超出正常范围,直接退出中断,避免程序死在这里
				{
					EX0=1;  //接收到错误信号后要重新打开中断,否则下次接收不了红外信号
					return;
				}
			}
			temp=0;
			delay800us();
			if(IR_DP==1)  //800us过去,IR_DP为1则是信号1,为0则是信号0
			{
				IR_Dat[i/8]|=0x80;  //读取计数次数,存入数组中
				while(IR_DP)
				{
					temp++;
					if(temp>10000)  //如果等待时间超出正常范围,直接退出中断,避免程序死在这里
					{
						EX0=1;  //接收到错误信号后要重新打开中断,否则下次接收不了红外信号
						return;
					}
				}
				temp=0;
			}
		}
		if(i==32)  //如果接收数据是32位完整的,表明是红外信号
		{
			for(i=0;i<4;i++)
			{
				IR_Dat[i]=~IR_Dat[i];  //数据取反,因为直接从红外接收头读到的信号与遥控的信号是各位取反的
			}
			IR_OK=1;                    //数据接收完成
		}
	}
}

RS232串口通信

#ifndef _RS232_H
#define _RS232_H
#include "public.h"

void RS232_Init(u16 Baudrate);  //串口通信初始化函数

#endif


#include "RS232.h"

/****************************************************
  函数名称: RS232_Init
  函数简介: 串口通信初始化函数
  入口参数: Baudrate 通信波特率
  出口参数: 无
  其他:    注意晶振频率为11.0592MHZ使用串口通信后定
						时器1被占用,串口通信中断向量号为4。
*****************************************************/
void RS232_Init(u16 Baudrate)
{
	SCON = 0x50;   // 设定通信方式为方式1,允许接收,相当于SM1 = 1; REN = 1;(注意顺序不能颠倒!)    
  PCON = 0x00;   //SMOD=0,该语句可去掉(波特率正常),若SMOD=1则(波特率加倍)
	TMOD = 0x20;   //设置TI定时器于工作方式2
	switch (Baudrate)   //确定波特率
	{
		case 300: {TH1 = 0xA0;TL1 = 0xA0;} break;
		case 600: {TH1 = 0xD0;TL1 = 0xD0;} break;
		case 1200: {TH1 = 0xE8;TL1 = 0xE8;} break;
		case 2400: {TH1 = 0xF4;TL1 = 0xF4;} break;
		case 3600: {TH1 = 0xF8;TL1 = 0xF8;} break;
		case 4800: {TH1 = 0xFA;TL1 = 0xFA;} break;
		case 7200: {TH1 = 0xFC;TL1 = 0xFC;} break;
		case 9600: {TH1 = 0xFD;TL1 = 0xFD;} break;
		case 14400: {TH1 = 0xFE;TL1 = 0xFE;} break;
		case 28800: {TH1 = 0xFF;TL1 = 0xFF;} break;
	}
	TR1 = 1;//启动定时器1
	EA  = 1;//开总中断
	ES  = 1;//开串行口中断		
}

超声波传感器

#ifndef _ChaoShengBo_H
#define _ChaoShengBo_H
#include "public.h"

/*************管脚定义**********************************************/
sbit ChaoShengBo_TRIG=P2^0;  //触发控制信号输入
sbit ChaoShengBo_ECHO=P2^1;  //回响信号输出

/*************变量声明**********************************************/
extern u8 ChaoShengBo_Flag;  //定时器中断溢出标志

/*************函数声明**********************************************/
u16 ChaoShengBo_Measure(void);  //超声波测距函数

#endif


#include "ChaoShengBo.h"

u8 ChaoShengBo_Flag=0;  //定时器中断溢出标志

/****************************************************
  函数名称: ChaoShengBo_Measure
  函数简介: 超声波测距函数
  入口参数: 无
  出口参数: 0 测量失败 非0 测得的返回信号时间(单位us)
  其他:    测试距离=(高电平时间×声速(340M/S))/2,该函数
						测量返回值为时间(单位us),需要转换成怎样的
						精度自己转换一下就可以了。
						注意:该函数调用时占用定时器0,请在(public.h)
						中使能相关的宏定义,失能其余的宏定义。
*****************************************************/
u16 ChaoShengBo_Measure(void)  //0.17毫米每微秒
{
	u16 i=20;
	ChaoShengBo_Flag=0;  //定时器溢出标志位清0
	TR0=0;
	TMOD=0x11;  //定时器0工作方式1,16位计数器
	TH0=TL0=0;
	EA=1;
	ChaoShengBo_TRIG=1;
	while(i--);  //只要保持10us以上即可启动一次信号发送
	ChaoShengBo_TRIG=0;
	while(ChaoShengBo_ECHO==0); //等待低电平过去,加上i做判断防止程序死在这里
	TR0=1;  //高电平到来,开启定时器测量
	while(ChaoShengBo_ECHO==1);  //定时器测量期间程序一直等待,加上i做判断防止程序死在这里
	TR0=0;  //测量完成,关闭定时器
	if(ChaoShengBo_Flag!=1)  //若定时器未溢出
	{
		return TH0*256+TL0;  //返回测量值按12M晶振算,单位是us
	}
	else  //若定时器溢出按理为65536*340/2/1000000=11.14112米,超出测量范围2cm~400cm
	{
		return 0;  //定时器已经溢出,返回最大值表示测量失败
	}
}

 

四、工程下载

《51单片机外设及常用传感器库》https://download.csdn.net/download/qq_34254642/12398307

 

 

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值