单片机STC12C5A60S2_RFID_RC522_OLED_门禁系统_菜单设计

门禁系统

视频演示
Keil源代码包

系统流程图

  • 系统框图
    单片机STC12C5A60S2_RFID_RC522_OLED_门禁系统_菜单设计_第1张图片

  • 系统流程图
    单片机STC12C5A60S2_RFID_RC522_OLED_门禁系统_菜单设计_第2张图片

  • 系统引脚配置

/*************************************************
*
*				
*	
*	P0^0 -------  步进电机1
*	P0^1 -------  步进电机2
*	P0^2 -------  步进电机3
*	P0^3 -------  步进电机4
*
*	P1^1 -------  OLED的SDA
*	P1^2 -------  OLED的SCL
*
*	P1^3 -------  RFID的SDA
*	P1^4 -------  RFID的SCK
*	P1^5 -------  RFID的MOSI
*	P1^6 -------  RFID的MISO
*	P1^7 -------  RFID的RQ
*
*	P2^0 -------  AT24C02的SCL
*	P2^1 -------  AT24C02的SDA
*
*	P2^3 -------  BUZZER
*	P2^5 -------  Error LED
*	P2^6 -------  OK LED
*	
*	P3^0 -------  矩阵键盘引脚0
*	P3^1 -------  矩阵键盘引脚1
*	P3^2 -------  矩阵键盘引脚2
*	P3^3 -------  矩阵键盘引脚3
*	P3^4 -------  矩阵键盘引脚4
*	P3^5 -------  矩阵键盘引脚5
*	P3^6 -------  矩阵键盘引脚6
*	P3^7 -------  矩阵键盘引脚7
* 
* 
*
**************************************************/

代码分析

  • 代码结构构成

单片机STC12C5A60S2_RFID_RC522_OLED_门禁系统_菜单设计_第3张图片


main.h

#ifndef __MAIN_H__
#define __MAIN_H__
#include "common.h"
#include "user_passwd.h"
#include "keyboard.h"
#include "iic.h"
#include "oled.h"
#include "rc522.h"
#include
#endif

/*************************************************
*
*				引脚配置信息
*	
*	P0^0 -------  步进电机1
*	P0^1 -------  步进电机2
*	P0^2 -------  步进电机3
*	P0^3 -------  步进电机4
*
*	P1^1 -------  OLED的SDA
*	P1^2 -------  OLED的SCL
*
*	P1^3 -------  RFID的SDA
*	P1^4 -------  RFID的SCK
*	P1^5 -------  RFID的MOSI
*	P1^6 -------  RFID的MISO
*	P1^7 -------  RFID的RQ
*
*	P2^0 -------  AT24C02的SCL
*	P2^1 -------  AT24C02的SDA
*
*	P2^3 -------  BUZZER
*	P2^5 -------  Error LED
*	P2^6 -------  OK LED
*	
*	P3^0 -------  矩阵键盘引脚0
*	P3^1 -------  矩阵键盘引脚1
*	P3^2 -------  矩阵键盘引脚2
*	P3^3 -------  矩阵键盘引脚3
*	P3^4 -------  矩阵键盘引脚4
*	P3^5 -------  矩阵键盘引脚5
*	P3^6 -------  矩阵键盘引脚6
*	P3^7 -------  矩阵键盘引脚7
* 
* 
*
**************************************************/

main.c


#include "main.h"
#define NO_TIMER2	//RFID.c中,STC12系列无定时器2
/*******************
* 引用全局变量
********************/
extern uchar key_flag;	//按键标志位
extern uchar admin_passwd[];	//存储管理员密码
extern uchar passwd[];			//存储用户密码
extern uchar key_num;			//矩阵按键返回值
extern UGroup G[];				//UGroup结构体变量,定义与rc522.h头文件中
extern Tips code lines[];		//Tips结构体类型OLED.h头文件中,用于存储显示信息
extern key_table  code  table[];//key_table结构体类型,定义与OLED.h头文件中,用于定义跳转函数
extern uchar code BMP1[];	//存储的图片
extern uchar func_index;	//func函数下标变量
extern uchar UID_S50[];		//存储S50卡卡号,4字节
extern uchar Temp_S50[];	//临时存储S50卡卡号变量


/**********************
* 	系统临时变量
***********************/

uchar  TEMP;
bit OUT = 0;

/**********************
* 	函数声明
***********************/

void (*current_operation_index)();	//指针函数声明
void Timer0Init();					//定时中断0函数声明

/**********************
* 	Main主函数
***********************/
void main(){
   
	RFID_Init();		//RFID初始化
	OLED_Init();		//OLED初始化
	enterMenu();		//开机LOGO
	Delay1000ms();		//延时1秒,稳定系统
	read_UID_From_EEPROM(G);	//读取存储在AT24C02中的UID用户ID

#if 0 //调试代码,可忽略
	at24c02Write(19,0);//存储卡号的标志位
	save_passwd_EEPROM(passwd,6);//保存用户密码到AT24C02
#endif
	
	
	if(read_passwd_EEPROM(passwd,6)) showOK();	//从AT24C02中读取user passwd用户密码,必须的
	
	OLED_CLS();				//OLED显示:欢迎回家
	OLED_P16x16Ch(23,3,4);
	OLED_P16x16Ch(40,3,5);
	OLED_P16x16Ch(57,3,6);
	OLED_P16x16Ch(74,3,7);
	
	Timer0Init();			//定时器0初始化
	
	while(1)				//while大循环
	{
   
		if(key_flag == 1)	//矩阵按键标志位
		{
   
	
			if(key_num == 12)//进入菜单
			{
   	
				showOK();		//提示OK
				//第一个函数值获取下一个函数号码;第二个函数是执行获取后的函数。
				current_operation_index = table[func_index].current_operation;	(*current_operation_index)();
				while(!OUT)	//检测菜单函数的退出与否的while循环
				{
   
					TEMP = getDir();//内置while循环
					if(TEMP){
   
						current_operation_index = table[func_index].current_operation;	(*current_operation_index)();
					}
					key_flag = 0;
				}
				//第一个函数值获取下一个函数号码;第二个函数是执行获取后的函数。
				current_operation_index = table[func_index].current_operation;	(*current_operation_index)();	
				//各个标志位复位
				OUT = 0;
				TEMP = 0;
				func_index = 0;
				key_flag = 0;
			}

			if((key_num == 14)&&verif_user_passwd())//按井号键开始验证密码
			{
   
				key_flag = 0;
				showOK();
				EA = 0;		//关闭所有中断
				OLED_CLS();	
				OLED_P8x16Str(0,0,"Door Is Opening.");
				Delay500ms();
				OLED_CLS();	//显示:欢迎回家
				OLED_P16x16Ch(23,3,4);
				OLED_P16x16Ch(40,3,5);
				OLED_P16x16Ch(57,3,6);
				OLED_P16x16Ch(74,3,7);
				MotroOpenDoor();
				EA = 1;
				key_flag = 0;
			}
			else 
			{
   
				showError();	//错误提示
				key_flag = 0;
			}

			key_num = 0;
		
		}
		else
		{
   
			Auto_Reader();	//RFID扫描函数
		}
	}

}

void Timer0Init()		//2毫秒@11.0592MHz//
{
   
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xF8;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
void time0() interrupt 1
{
   
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xF8;		//设置定时初值
	keyscanf_maxtrix();
}


keyboard.h

#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__
#include "common.h"
#include "oled.h"
void keyscanf_maxtrix();
uchar get_onece_keyboard();
#endif
/*****************************************************
*			4*4矩阵键盘按键说明:
*
* - 上键:	keyscanf_maxtrix扫描值:3 	再赋值 10
* - 下键:	keyscanf_maxtrix扫描值:15 	再赋值 15
* - 左键:	keyscanf_maxtrix扫描值:7 	再赋值 11
* - 右键:	keyscanf_maxtrix扫描值:11 	再赋值 13
* - 井号键:keyscanf_maxtrix扫描值:14 	再赋值 14
* - 星号键:keyscanf_maxtrix扫描值:12 	再赋值 12
*
* - 星号键进入菜单 值为 12
* - 井号键为确定键 值为 14
* 
****************************************************/

keyboard.c

单片机STC12C5A60S2_RFID_RC522_OLED_门禁系统_菜单设计_第4张图片

#include "keyboard.h"

uchar key_flag = 0;//标志位
uchar key_num = 16;//默认为"-"

uchar get_onece_keyboard()	//得到一个值,while循环
{
   	static uchar i = 0;
	uchar temp = 99;
	if(key_flag == 1)
	{
   
		key_flag = 0;
		while(temp == 99)
		{
   
			switch(key_num)
			{
   
				case 0: temp = 1;  break;
				case 1: temp = 2;  break;
				case 2: temp = 3;  break;
				case 3: temp = 10; break;	//上
				case 4: temp = 4;  break;
				case 5: temp = 5;  break;
				case 6: temp = 6;  break;
				case 7: temp = 11; break;	//左
				case 8: temp = 7;  break;
				case 9: temp = 8;  break;
				case 10: temp = 9;  break;
				case 11: temp = 13; break;	//右
				case 12: temp = 12; break;	//星号
				case 13: temp = 0;  break;
				case 14: temp = 14;	break;	//井号
				case 15: temp = 15; break;	//下
			}
		}
		/*************************************
		*  按键又被按下,OLED上会有提示
		*************************************/
		EA = 0;
		if(i%2==0)
		{
   
			OLED_P8x16Str(0,6,". ");
		}
		else
		{
   
			OLED_P8x16Str(0,6," .");
		}
		i++;if(i==6){
   i = 0;}
		EA = 1;		
	}
	key_flag = 0;
	return temp;
}

/**********************************
*		矩阵扫描函数
*	占用8个IO口,进行行的扫描
**********************************/
void keyscanf_maxtrix()	
{
   
	if(key_flag == 0){
   
		uchar i;
		uchar cycle = 0xfe;
		for(i=0;i<4;i++){
   
			uchar temp;
			P3 = cycle;
			temp = P3;
			temp = temp&0xf0;
			if(temp!=0xf0)
			{
   
			  if(temp!=0xf0)
			  {
   	
				temp=P3;
				switch(temp)
				{
   
				  case 0xee:
					key_num=0;
					key_flag = 1;
					break;
				  
				  case 0xde:
					key_num=1;
					key_flag = 1;
					break;

				  case 0xbe:
					key_num=2;
					key_flag = 1;
					break;

				  case 0x7e:
					key_num=3;
					key_flag = 1;
					break;
					
				  case 0xed:
					key_num=4;
					key_flag = 1;
					break;
					
				  case 0xdd:
					key_num=5;
					key_flag = 1;
					break;
					
				  case 0xbd:
					key_num=6;
					key_flag = 1;
					break;
					
				  case 0x7d:
					key_num=7;
					key_flag = 1;
					break;
					
				  case 0xeb:
					key_num=8;
					key_flag = 1;
					break;
					
				  case 0xdb:
					key_num=9;
					key_flag = 1;
					break;
		
				  case 0xbb:
					key_num=10;
					key_flag = 1;
					break;
					
				  case 0x7b:
					key_num=11;
					key_flag = 1;
					break;
				  
				   case 0xe7:
					key_num=12;
					key_flag = 1;
					break;
					
				  case 0xd7:
					key_num=13;
					key_flag = 1;
					break;

				  case 0xb7:
					key_num=14;
					key_flag = 1;
					break;
					
				  case 0x77:
					key_num=15;
					key_flag = 1;
					break;
				 }
			  }
			}
			while(temp!=0xf0)	//按键松手后,跳出循环,防止多按
			{
   
				temp=P3;
				temp=temp&0xf0;
			}
			cycle = _crol_(cycle,1);//循环左移
		}
	}
	
}

user_passwd.h

#ifndef __USER_PASSWD__
#define __USER_PASSWD__
#include "common.h"
#include "keyboard.h"
#include "iic.h"
#include "rc522.h"
#include "mfrc522.h"
void get_six_number(uchar *arr);
bit modify_admin_passwd();
bit verif_user_passwd();
bit compare_two_four_number(uchar *arr1, uchar *arr2);
bit verif_admin_passwd();
bit modify();
bit read_passwd_EEPROM(uchar *arr,uchar num);
bit save_passwd_EEPROM(uchar *arr, uchar num);
void Auto_Reader();
bit verif_CardID_from_EEPROM(uchar arr[]);
#endif

user_passwd.c

#include "user_passwd.h"

extern uchar key_flag;
extern uchar key_num;
extern uchar UID_S50[];		//S50卡,4字节
extern uchar Temp_S50[];	//S50卡,4字节
extern UGroup G[];			//S50卡组
uchar  admin_passwd[6] = {
   2,3,2,3,2,3};	//初始化,管理员密码,非缓存区
uchar  passwd[6] = {
   5,5,5,5,5,5};		//初始化用户密码,缓存区

/*****************************
* 函数功能:
* 
******************************/
/*****************************
* 函数功能:从键盘得到六位数字
* 参数:数组名
******************************/
void get_six_number(uchar *arr)	
{
   
	uchar i;
	for(i = 0; i < 6; i++){
   
		key_flag = 0;
		while(key_flag != 1);
		*arr = get_onece_keyboard();
		arr++;
	}
}

/*****************************
* 函数功能:修改超级用户密码
******************************/
bit modify_admin_passwd()		
{
   
	get_six_number(admin_passwd);
	
	return 1;
}
/*****************************
* 函数功能:修改用户密码
******************************/
bit modify_user_passwd()		
{
   
	get_six_number(passwd);
	
	return 1;
}
/*****************************
* 函数功能:比较两组六位数的数组
******************************/
bit compare_two_six_number(uchar *arr1, uchar *arr2) 
{
   
	uchar i;
	for(i = 0; i < 6; i++){
   
		if((*arr1) != (*arr2)) return 0;
		arr1++;
		arr2++;
	}
	return 1;
}
/*****************************
* 函数功能:比较两组4位数的数组
******************************/
bit compare_two_four_number(uchar *arr1, uchar *arr2) 
{
   
	uchar i;
	for(i = 0; i < 4; i++){
   
		if((*arr1) != (*arr2)) return 0;
		arr1++;
		arr2++;
	}
	return 1;
}
/*****************************
* 函数功能:验证管理员密码
******************************/
bit verif_admin_passwd()	
{
   
	uchar temp[6];
	get_six_number(temp);
	if(compare_two_six_number(temp,admin_passwd))
		return 1;
	else 
		return 0;
}
/*****************************
* 函数功能:验证用户密码
******************************/
bit verif_user_passwd()	
{
   
	uchar temp[6];
	get_six_number(temp);
	if(compare_two_six_number(temp,passwd))
		return 1;
	else 
		return 0;
}
/*****************************
* 函数功能:修改用户密码函数
******************************/
bit modify()				
{
   
	if(verif_admin_passwd())//输入并验证 管理员密码admin_passwd
	{
   
		key_flag = 0;
		showOK();
		{
   EA=0;OLED_CLS();OLED_P8x16Str(30,3,"Right!");Delay500ms();OLED_CLS();OLED_P8x16Str(30,0,"Contine,");OLED_P8x16Str(0,4,"Enter N Passwd");EA=1;}//OLED提示
		if(modify_user_passwd())	//修改用户密码user_passwd
		{
   
			save_passwd_EEPROM(passwd,6);
			{
   EA=0;OLED_CLS();OLED_P8x16Str(10,4,"Updated Passwd!");Delay500ms();EA=1;}
			showOK();
			key_flag = 0;
			return 1;
		}
		else{
   EA=0;OLED_CLS();OLED_P8x16Str(0,0,"Failed!");Delay500ms();EA=1;return 0;}
	}
	else{
   
	{
   EA=0;OLED_CLS();OLED_P8x16Str(0,0,"Failed!");Delay500ms();EA=1;return 0;}
	}
	
}

/*****************************
* 函数功能:从EEPROM中去读用户密码
* 用户密码存储地址:9-14位
******************************/
bit read_passwd_EEPROM(uchar *arr,uchar num)
{
   	uchar i = 0;
	EA = 0;	//关闭所有中断
	for(i = 0; i < num; i++)
	{
   
		*arr = at24c02Read(9+i);
		arr++;
		showOK();
		Delay20ms();//延时以稳定AT24C02芯片
	}
	EA = 1;//恢复所有中断
	return 1;
}
/*****************************
* 函数功能:将用户密码存储在EEPROM中
* 用户密码存储地址:9-14位
******************************/
bit save_passwd_EEPROM(uchar *arr, uchar num)	//保存用户密码
{
   
	uchar i = 0;
	EA = 0;
	for(i = 0; i < num; i++)
	{
   
		at24c02Write(9+i,*arr);
		Delay20ms();
		showOK();
		arr++;
		
	}
	EA = 1;
	return 1;
}

/*****************************
* 函数功能:将读取的卡号
******************************/
bit verif_CardID_from_EEPROM(uchar arr[]){
   
	uchar ii = 0;
	for(ii = 0; ii<10; ii++){
   
		if(compare_two_four_number(G[ii].UID,arr)) return 1;
		else continue;
	}
	return 0;
}

void Auto_Reader()
{
   
    if(PcdRequest(0x52,Temp_S50) == MI_OK)
	{
    	//寻卡,成功后Temp数组为卡类型
		
		if(PcdAnticoll(UID_S50)== MI_OK )
		{
   	 	//防冲突,UID数组数据为卡序列号
			showOK();
//			if(compare_two_four_number(UUID,UID_S50)) {showOK();MotroOpenDoor();}    
			if(verif_CardID_from_EEPROM(UID_S50)) {
   showOK();MotroOpenDoor();}      			
		}
    }

}


common.h

#ifndef __COMMON_H__
#define __COMMON_H__

#include "reg52.h"
#include "intrins.h"
#include "string.h"

#define OSC_FREQ          11059200L				//系统晶振选择
#define  RCAP2_50us      65536L - OSC_FREQ/40417L
#define  RCAP2_1ms       65536L - OSC_FREQ/2000L
#define  RCAP2_10ms      65536L - OSC_FREQ/1200L
#define  TIME0_500us     65536L - OSC_FREQ/8000L
#define  TIME0_10ms      65536L - OSC_FREQ/200

#define TRUE 1
#define FALSE 0

sfr AUXR = 0x8e;	//辅助寄存器


typedef unsigned int uint;
typedef unsigned char uchar;

/***************************
*	系统状态提示声明
****************************/
void showError();
void showOK();

/***************************
*	软件延时函数声明
****************************/
void delay(uint z);
void Delay1ms()	;	
void Delay2ms();
void Delay20ms();		//@11.0592MHz
void Delay100ms();
void Delay200ms();	//@11.0592MHz
void Delay500ms();	//@11.0592MHz	
void Delay1000ms();

/***************************
*	步进电机驱动函数
****************************/
void MotroOpenDoor();

#endif

common.c

#include "common.h"
#define MotorData  P0

sbit Error = P2^5;	//Red led
sbit OK = P2^6;		//Green led
sbit buzzer_ = P2^3;//蜂鸣器
/***************************
*	步进电机位置数组//这没说不太准确,详细请搜索五线四向步进电机原理
****************************/
uchar idata motor_arrA[4] = {
   0x08,0x04,0x02,0x01};
uchar idata motor_arrB[4] = {
   0x01,0x02,0x04,0x08};


void delay(uint z)
{
   
	uchar x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}
void Delay1ms()		//@11.0592MHz
{
   
	unsigned char i, j;

	_nop_();
	i = 11;
	j = 190;
	do
	{
   
		while (--j);
	} while (--i);
}

void Delay2ms()		//@11.0592MHz
{
   
	unsigned char i, j;

	i = 22;
	j = 128;
	do
	{
   
		while (--j);
	} while (--i);
}

void Delay4ms()		//@11.0592MHz
{
   
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 44;
	j = 3;
	do
	{
   
		while (--j);
	} while (--i);
}
void Delay20ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	i = 1;
	j = 216;
	k = 35;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay100ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	i = 5;
	j = 52;
	k = 195;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay200ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	i = 9;
	j = 104;
	k = 139;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay500ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	i = 22;
	j = 3;
	k = 227;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay1000ms()		//@11.0592MHz
{
   
	unsigned char i, j, k;

	i = 43;
	j = 6;
	k = 203;
	do
	{
   
		do
		{
   
			while (--k);
		} while (--j);
	} while (--i);
}

void showOK(){
   
	OK = 0;
	buzzer_ = 0;
	Delay200ms();
	OK = 1;
	buzzer_ = 1;
	Delay200ms();
}

void showError()
{
   
	Error = 0;
	buzzer_ = 0;
	Delay200ms();
	Error = 1;
	buzzer_ = 1;
	Delay200ms();
	Error = 0;
	buzzer_ = 0;
	Delay200ms();
	Error = 1;
	buzzer_ = 1;
	Delay200ms();
	
}




void MotorTurnA()	//步进电机正向
{
   
	uchar i;
	for(i = 0; i <4; i++)
	{
   
		MotorData = motor_arrA[i];
		Delay4ms();
	}
}

void MotorTurnB()	//步进电机正向
{
   
 uchar i;
 for(i=0;i<4;i++)
  {
   
   MotorData = motor_arrB[i];
   Delay4ms();//转速调节
  }
}

void MotorStop()	//步进电机停止
{
   
	MotorData=0x00;
}


void MotroOpenDoor()
{
   
	uchar i;
	for(i=0;i<200;i++)
	{
   
		dula = 0;
		wela = 0;
		MotorTurnA();   //顺时针转动
		
	}
		
	MotorStop();  //停止转动
	Delay500ms();
		
	for(i=0;i<200;i++)
	{
   
		dula = 0;
		wela = 0;
		MotorTurnB();  //逆时针转动
	} 
	MotorStop();  //停止转动 
	Delay500ms();
}

iic.h

#ifndef _IIC_H__
#define _IIC_H__

#include "common.h"
#include "rc522.h"
/***********************
*	iic基本驱动函数
***********************/
void IIC_Start(void); 
void IIC_Stop(void);  
void IIC_Ack(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
bit IIC_WaitAck(void);  
unsigned char IIC_RecByte(void); 

/***********************
*	EEPROM读写函数
***********************/
void at24c02Write(uchar addr, uchar dat);	//写
uchar at24c02Read(uchar addr);						//	读
void at24c02ReadStr(uchar addr, uchar num, uchar *getStr);
void at24c02WriteStr(uchar addr, uchar *p,uchar num);

/***********************
*	用户组G的读取和存储
***********************/
void save_UID_In_EEPROM(uchar *arr);
void read_UID_From_EEPROM(UGroup G[]);
void clearAll();//清除全部UID

#endif

iic.c

#include "iic.h"
#define somenop; _nop_();	//调节通信延时长短
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */
extern UGroup G[];

//总线启动条件
void IIC_Starts(void)
{
   
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

//总线停止条件
void IIC_Stops(void)
{
   
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}

//应答位控制
void IIC_Ack(bit ackbit)
{
   
	if(ackbit) 
	{
   	
		SDA = 0;
	}
	else 
	{
   
		SDA = 1;
	}
	somenop;
	SCL = 1;
	somenop;
	SCL = 0;
	SDA = 1; 
	somenop;
}

//等待应答
bit IIC_WaitAck(void)
{
   
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{
      
		SCL = 0;
		IIC_Stops();
		return 0;
	}
	else  
	{
    
		SCL = 0;
		return 1;
	}
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
   
	unsigned char i;
	for(i=0;i<8;i++)
	{
      
		if(byt&0x80) 
		{
   	
			SDA = 1;
		}
		else 
		{
   
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
   
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{
      
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01

你可能感兴趣的:(单片机,嵌入式,单片机)