⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f31xsr176.c

📁 利用C8051F31x的SMBus总线实现对射频读写芯片的基本读写
💻 C
📖 第 1 页 / 共 2 页
字号:
			else{
				if(SMB_data_index==SMB_data_len-1){
					SMB_state=0x01;
					RX_buf[SMB_data_index]=SMB0DAT;
					ACK=0;			/* 不响应ACK */
					STO=1;			/* 发停止 */	
				}
			}
			SMB_BUSY=0;
			break;
					
		default:
        	FAIL = 1;				/* 传送失败,跳到中断服务程序的最后进行失败处理 */
			break;
	}
   if(FAIL){						/* 如果传送失败 */
		SMB0CN &= ~0x40;			/* 复位通信 */
		SMB0CN |= 0x40;
		SMB_BUSY = 0;  				/* 释放SMBus */
		SMB_state=0x00;
	}
	SI=0;							/* 清中断旗标 */
}


/***************************************************************************************
函数名称:	void SMBus_Init(void)
功能描述:	初始化SMBus总线
			- SMBus使能
			- 无效辅模式
			- 定时器0作为时钟源,SCL的频率大约是定时器0溢出率的1/3
			- 建立和保持时间加长使能
			- SCL低电平超时检测
输入:		无
输出:		无
全局变量:	SMB0CF -> SMBus时钟/配置寄存器
调用模块:	无
***************************************************************************************/
void SMBus_Init (void)
{
	SMB0CF = 0x5C;				/* 用定时器0的溢出率作为SMBus的时钟源,无效SMBus的辅模式 */
                                /* 建立和保持时间增长使能 */
                                /* 使能SCL低电平超时检测 */
	SMB0CF |= 0x80;				/* 使能SMBus */ 
}


/***************************************************************************************
函数名称:	void Timer3_Init(void)
功能描述:	初始化定时器3(用于SMBus低电平超时检测)
			- 定时器3工作在16位重载模式
			- SYSCLK/12作为定时器3的时钟源
			- 定时器3重载寄存器是25ms溢出周期的值
			- 定时器3的预装载值是25ms后溢出
			- 定时器3使能
输入:		无
输出:		无
全局变量:	TMR3CN -> 定时器3控制寄存器
   			CKCON  -> 时钟控制寄存器 
			TMR3RL -> 定时器3 重载寄存器
			TMR3   -> 定时器3计时寄存器
			TR3    -> 定时器3使能位
调用模块:	无
***************************************************************************************/
void Timer3_Init (void)
{                                         
	TMR3CN = 0x00;				/* 定时器3工作于16位重载模式,定时器低字节中断无效 */
	TMR3   = -(SYSCLK/12/40);	/* 定时器3在25ms后溢出(SMBus低电平超时检测)*/
	TMR3RL = -(SYSCLK/12/40);
	CKCON  &= ~0x40;			/* 定时器3用SYSCLK/12作为时钟源 */
	TMR3 |= 0x04;				/* 使能定时器3 */
}


/***************************************************************************************
函数名称:	void Timer0_Init(void)
功能描述:	定时器0初始化(用于SMBus总线的时钟源)
			- 定时器0工作在8位重载模式
			- SYSCLK/12作为定时器0的时钟源
			- SCL时钟率是定时器0溢出率的三分之一
			- 使能定时0
输入:		无
输出:		无
全局变量:	CKCON -> 时钟控制寄存器
   			TMOD  -> 定时器模式寄存器
			TH0   -> 定时器0寄存器高字节
			TL0   -> 定时器0寄存器低字节
			TR0   -> 定时器0使能位
调用模块:	无
***************************************************************************************/
void Timer0_Init(void)
{
	CKCON &= ~0x07;						/* 定时器0的时钟源是SYSCLK / 12 */
	TMOD = 0x02;						/* 定时器0工作在8位自动重载模式 */
	TH0 = -(SYSCLK/SMB_FREQUENCY/12/3);	/* 定时器0的溢出率是SMB_FREQUENCY的1/3 */
	TL0 = TH0;
	TR0 = 1;							/* 使能定时器0 */
}


/***************************************************************************************
函数名称:	void PORT_Init(void)
功能描述:	I/O初始化
输入:		无
输出:		无
全局变量:	XBR0 -> 端口I/O交叉开关控制0
   			XBR1 -> 端口I/O交叉开关控制1
			P0MDIN ->P0口输入模式控制 
			P0MDOUT->P0口输出模式控制
调用模块:	无
***************************************************************************************/
void PORT_Init(void)
{
	XBR0 = 0x05;					/* 使能SMBus和UART引脚 */
	XBR1 = 0x40;                    /* 使能交叉开关和弱上拉 */
	P0MDIN = 0xFF;                  /* P0口工作在数字模式 */
	P0MDOUT = 0x00;                 /* P0口是开漏模式 */
	P0 = 0xff;
	P1MDOUT |= 0x03;                 /* P1.0和P1.1是推挽模式 */
}


/***************************************************************************************
函数名称:	void UART_Init(void)
功能描述:	初始化串行口
输入:		无
输出:		无
全局变量:	SCON0 ->串行口0控制寄存器
   			TMOD  ->定时器模式寄存器
			TH1   ->定时器1高字节
			TL1   ->定时器1低字节
			CKCON ->时钟控制寄存器
调用模块:	无
***************************************************************************************/
void UART_Init(void)
{
	SCON0   = 0x50;                 /* 工作模式1,8位数据位,使能RX */
	TMOD    = 0x22; 
	TH1 = 0x95;						//C8051F300和C8051F310
	//TH1 = 0xB0;					//C8051F305(0xA9)
	TR1    = 1;                     /* 使能定时器1 */
	CKCON |= 0x00;                  /* 定时器1用SYSCLK作时基 */
}


/***************************************************************************************
函数名称:	void  Timer3_ISR(void) interrupt 14
功能描述:	定时器3中断指示SMBus的SCL低电平超时,SMBus无效并且重新使能
输入:		无
输出:		无
全局变量:	SMB0CN ->SMBus控制寄存器
   			TF3H   ->定时器3中断旗标
调用模块:	无
***************************************************************************************/
void Timer3_ISR (void) interrupt 14
{
   SMB0CN &= ~0x40;                 /* 无效SMBus */    
   SMB0CN |= 0x40;                  /* 使能SMBus */
   TMR3CN &= ~0x80;					/* 清除定时器3高字节中断旗标 */			
}


/***************************************************************************************
函数名称:	BYTE Initiate(void)
功能描述:	初始化射频卡命令
输入:		无
输出:		运行结果返回码
全局变量:	Tx_buf 	 ->发送缓冲区
   			read_Len ->射频卡返回字节长度
调用模块:	BYTE Send_Receive_Data(void)
***************************************************************************************/
BYTE Initiate (void)
{
	BYTE rei;
    read_len=0x02;
	TX_buf[0] = 0x01;				/* I/O口寄存器地址 */
	TX_buf[1] = 0x02;				/* 帧长度 */
	TX_buf[2] = 0x06;
	TX_buf[3] = 0x00;
	rei = Send_Receive_Data();
	return rei;
}


/***************************************************************************************
函数名称:	BYTE Select(BYTE CHIP_ID)
功能描述:	选择射频卡命令
输入:		BYTE CHIP_ID(射频卡的识别号)
输出:		运行结果返回码
全局变量:	read_len ->射频卡返回字节长度
   			Tx_buf   ->发送缓冲区
调用模块:	BYTE Send_Receive_Data(void)
***************************************************************************************/
BYTE Select(BYTE CHIP_ID)
{
	read_len=2;
	TX_buf[0] = 0x01;
	TX_buf[1] = 0x02;
	TX_buf[2] = 0x0E;
	TX_buf[3] = CHIP_ID;
	return Send_Receive_Data();
}


/***************************************************************************************
函数名称:	BYTE ReadBlock(BYTE Addr)
功能描述:	读射频卡一块命令(4 bytes),读到的数据放在全局变量Rx_buf中
输入:		BYTE Addr(块地址)
输出:		运行结果返回码
全局变量:	read_len ->射频卡返回字节长度
   			Tx_buf	 ->发送缓冲区
调用模块:	BYTE Send_Receive_Data(void)
***************************************************************************************/
BYTE ReadBlock (BYTE Addr)
{
	read_len=3;
	TX_buf[0] = 0x01;
	TX_buf[1] = 0x02;
	TX_buf[2] = 0x08;
	TX_buf[3] = Addr;
	return Send_Receive_Data();
}


/***************************************************************************************
函数名称:	BYTE WriteBlock_4k(BYTE Addr, BYTE DATA_WR0,BYTE DATA_WR1,BYTE DATA_WR2,BYTE DATA_WR3)
功能描述:	写射频卡一块命令(4 bytes)
输入:		BYTE Addr(块地址)
			BYTE DATA_WR0(待写的第一字节)
			BYTE DATA_WR1(待写的第二字节)
			BYTE DATA_WR2(待写的第三字节)
			BYTE DATA_WR3(待写的第四字节)
输出:		运行结果返回码
全局变量:	read_len ->射频卡返回字节长度
			Tx_buf   ->发送缓冲区
调用模块:	BYTE Send_Receive_Data(void)
***************************************************************************************/
//BYTE WriteBlock_4K(BYTE Addr,BYTE DATA_WR0,BYTE DATA_WR1,BYTE DATA_WR2,BYTE DATA_WR3)
BYTE WriteBlock_4K(BYTE Addr,BYTE DATA_WR0,BYTE DATA_WR1)
{
    read_len=0;
	TX_buf[0] = 0x01;
    TX_buf[1]=0x04;
    TX_buf[2]=0x09;
    TX_buf[3]=Addr;
	TX_buf[4]=DATA_WR0;
	TX_buf[5]=DATA_WR1;
	return Send_Receive_Data ();
}


/***************************************************************************************
函数名称:	BYTE Get_Uid(void)
功能描述:	读取射频卡的识别号	
输入:		无
输出:		运行结果返回码
全局变量:	read_len ->射频卡返回字节长度
   			Tx_buf	 ->发送缓冲区
调用模块:	BYTE Send_Receive_Data(void)
***************************************************************************************/
/*
BYTE Get_Uid(void)
{	   
	BYTE regu;  
	read_len=9;
	TX_buf[0]= 0x01;
    TX_buf[1]= 0x01;
	TX_buf[2]= 0x0B;
	regu = Send_Receive_Data();
	return regu;
}
*/

/**************************************************************************************/
void main(void)
{						
	BYTE startflag=0;
	BYTE *ptr;	
   	BYTE data i;
	BYTE m,DataType,CommandLen;
	BYTE CardID1,CardID2,temp[2],Uid[8];
	FirstTime=1;
	Read_Bit=0;
	PCA0MD &= ~0x40;				/* 关闭看门狗 */
	OSCICN |= 0x03;					/* 用内部24.5MHz时钟 */
	Port_Init();					/* 初始化交叉开关和GPIO */
	OneBuzzer(40);					/* 蜂鸣器响一次 */
	Timer0_Init ();					/* 配置定时器0作为SMBus时钟源 */
	Timer3_Init (); 				/* 配置定时器3作为SMBus的低电平超时检测 */
	SMBus_Init ();					/* 配置和使能SMBus */
	OpenComm();						/* 初始化串口 */
	M485 = 0;
	EIE1 |= 1;						/* SMBus中断使能 */
	IE |= 0x20;						/* 使能定时器2 */						
	//EIE1 |= 0x80;					/* 使能定时器3 */
	EA = 1;							/* 所有中断使能 */
			RF_ON();				/* 打开载频输出*/
			sleep_ms(1000);
NewCard:	startflag=Initiate();	/* 初始化读卡器工作范围内的射频卡*/
			startflag=RX_buf[1];
			RX_buf[1]=0x44;
			Select(startflag);		/* 选择卡*/
ReadID:		//Get_Uid();				/* 读卡识别号码*/
			ReadBlock(0x00);		
			Uid[0]=RX_buf[1];
			Uid[1]=RX_buf[2];
			if(RX_buf[0]!=0x02){	/* 读识别号码是否正确*/
		 		ES0 = 0;
				_nop_();
				FirstTime = 1;
				goto NewCard;		/* 不正确重新开始 */
			}
			else{
				if(FirstTime==1){	/* 是否是首次读到该卡的识别号码 */
					CardID1=RX_buf[1];		/* 保存识别号码 */
					CardID2=RX_buf[2];
				}
				if((CardID1!=RX_buf[1])||(CardID2!=RX_buf[2])){
					ES0=0;
					FirstTime=1;
					goto NewCard;			/* 识别号码不相同重新开始 */
				}
				else{
					if(FirstTime==1){		/* 首次读到卡的识别号码 */
						FirstTime=0;
						ReadBlock(0x01);
						Uid[2]=RX_buf[1];
						Uid[3]=RX_buf[2];
						//ReadBlock(0x02);		
						//Uid[4]=RX_buf[1];
						//Uid[5]=RX_buf[2];
						//ReadBlock(0x03);		
						//Uid[6]=RX_buf[1];
						//Uid[7]=RX_buf[2];
						RI0=1;
						TI0=0;
						ES0=1;
						//ptr = RX_buf;		/* 指针指到卡的识别号 */
						//ptr++;
						ptr = Uid;
						for(m=0;m<4;m++){	/* 送射频卡的识别号 */
							SendCommChar(HEXToASC((*ptr)/16));
							SendCommChar(HEXToASC((*ptr)%16)); 
							 ptr++;
						}
						SendCommBuffer("\r\n",2);
						_nop_();
						OneBuzzer(40);		/* 蜂鸣器响一声 */
						OpenComm();			/* 打开串行口准备串行通信 */
					}
					while(1){
Err1:				if(!IsEmtpyRecComm()){	/* 是否接收到上位机命令?*/
						i=GetCommChar();
						if(i==':'){			/* 命令头是否正确?*/
					  		if(GetCommCharWait(&i,200)){
								DataType=ASCToHEX(i);	/* 得到命令类型 */							
					  		}	
					  		else goto Err;
							CommandLen = 0;
							for(m=100;m>=1;m=m/10){		/* 得到卡的块地址 */
								if(GetCommCharWait(&i,200)){
									CommandLen += ASCToHEX(i)*m;
								}
								else goto Err;
							}
							ptr=TX_buf;
							for(startflag=0;startflag<2;startflag++){	/* 得到待写块的数据字节 */
								if(GetCommCharWait(&i,200)){
									m=ASCToHEX(i)*0x10;
								}
								else goto Err;
								if(GetCommCharWait(&i,200)){
									m+=ASCToHEX(i);
									*ptr=m;
									temp[startflag]=m;
									ptr++;
								}
								else goto Err;
							}
					  		goto dd;
Err:				  		CommRecBufferHead=CommRecBufferTail=0;
					      	goto Err1;
dd:					  		CommRecBufferHead=CommRecBufferTail=0;
				 			switch(DataType){			/* 判定命令字 */
								case 0:					/* 写块数据 */
									m=WriteBlock_4K(CommandLen,temp[0],temp[1]);				
							 		SendCommBuffer("OK",2); 						
									OneBuzzer(40);		/* 蜂鸣器响一声 */
									break;
								case 1: 				/* 读块数据 */    
									m=ReadBlock(CommandLen);		
									ptr = RX_buf;
									ptr++;
									for(m=0;m<2;m++){	/* 从串行口送出块数据(4 bytes) */	
										SendCommChar(HEXToASC((*ptr)/16));
										SendCommChar(HEXToASC((*ptr)%16)); 
										ptr++;
									}
									SendCommBuffer("\r\n",2);
 									OneBuzzer(40);		/* 蜂鸣器响一声 */
									break;
								case 2:
									RF_OFF();			/* 关闭载频输出 */
									break;
								default:
								_nop_();
							}	//switch
							//RF_OFF();
						}	//if ':'
					}	/* 接收数据 */
					ReadBlock(0x00);		
					if(RX_buf[0]!=0x02) break;
					
				}	//while(1)
				goto ReadID;
			}	/* 如果识别号相同 */
		}		/* 读射频卡识别号正确 */
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -