📄 f31xsr176.c
字号:
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 + -