大學時積累的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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章