STC8H1K08单片机控制的门禁系统

         代码基于嘉立创开源项目的硬件,板子直接白嫖的嘉立创打样,硬件链接如下ic卡、饭卡、手机NFC的门禁 - 嘉立创EDA开源硬件平台 (oshwhub.com)

         硬件外设使用了RC522,SG90,LED灯,蜂鸣器还有三个按键。代码是基于STC官方24年的H库开发,使用内部晶振22.1184Mhz,是在公司摸鱼写的加密工程所以只有代码以下是核心代码代码请按自身需求修改:

main.c

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/

#include "config.h"
#include "STC8G_H_GPIO.h"
#include "STC8G_H_Timer.h"
#include "STC8G_H_Delay.h"
#include "STC8G_H_UART.h"
#include "STC8G_H_SPI.h"
#include "STC8G_H_NVIC.h"
#include "STC8G_H_Switch.h"
#include "STC8G_H_Exti.h"
#include "STC8H_PWM.h"
#include "RAM.h"
#include "Touch.H"
#include "rc522.h"

/*************	功能说明	**************

本例程基于STC8H8K64U为主控芯片的实验箱8进行编写测试,STC8G、STC8H系列芯片可通用参考.

通过串口发送数据给MCU1,MCU1将接收到的数据由SPI发送给MCU2,MCU2再通过串口发送出去.

设置方法 2:
两个设备初始化时都设置 SSIG 为 0,MSTR 设置为0,此时两个设备都是不忽略 SS 的从机模式。
当其中一个设备需要启动传输时,先检测 SS 管脚的电平,如果时候高电平,
就将自己设置成忽略 SS 的主模式,自己的 SS 脚输出低电平,拉低对方的 SS 脚,即可进行数据传输。

         MCU1                          MCU2
  |-----------------|           |-----------------|
  |            MISO |-----------| MISO            |
--| TX         MOSI |-----------| MOSI         TX |--
  |            SCLK |-----------| SCLK            |
--| RX           SS |-----------| SS           RX |--
  |-----------------|           |-----------------|


下载时, 选择时钟 22.1184MHz (可以在配置文件"config.h"中修改).

******************************************/

/*************	本地常量声明	**************/

/*************	本地变量声明	**************/

bit UartReceived=0;

/*************	本地函数声明	**************/


/*************  外部函数和变量声明 *****************/


/******************** IO口配置 ********************/
void	GPIO_config(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义

	GPIO_InitStructure.Pin  = GPIO_Pin_All;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);	//初始化
  
 	GPIO_InitStructure.Pin  = GPIO_Pin_All;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);	//初始化
  
  GPIO_InitStructure.Pin  = GPIO_Pin_LOW | GPIO_Pin_5 | GPIO_Pin_6;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);	//初始化
  
  GPIO_InitStructure.Pin  = GPIO_Pin_4 | GPIO_Pin_7;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);	//初始化
}

/************************ 定时器配置 ****************************/
void	Timer_config(void)
{
    TIM_InitTypeDef		TIM_InitStructure;						//结构定义

    //定时器0做16位自动重装, 中断频率为1000HZ,中断函数从P6.7取反输出50KHZ方波信号.
    TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	//指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
    TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;		//指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
    TIM_InitStructure.TIM_ClkOut    = DISABLE;				//是否输出高速脉冲, ENABLE或DISABLE
    TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1000UL);		//初值, 100000UL
    TIM_InitStructure.TIM_Run       = ENABLE;				//是否初始化后启动定时器, ENABLE或DISABLE
    Timer_Inilize(Timer0,&TIM_InitStructure);				//初始化Timer0	  Timer0,Timer1,Timer2,Timer3,Timer4
    NVIC_Timer0_Init(ENABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}


/****************  串口初始化函数 *****************/
void	UART_config(void)
{
	COMx_InitDefine		COMx_InitStructure;					//结构定义

	COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
	COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
	COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
	COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
	COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
	UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4
	NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

	UART1_SW(UART1_SW_P30_P31);		//UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}

/****************  SPI初始化函数 *****************/
void	SPI_config(void)
{
	SPI_InitTypeDef		SPI_InitStructure;

	SPI_InitStructure.SPI_Enable    = ENABLE;				//SPI启动    ENABLE, DISABLE
	SPI_InitStructure.SPI_SSIG      = DISABLE;				//片选位     ENABLE, DISABLE
	SPI_InitStructure.SPI_FirstBit  = SPI_MSB;				//移位方向   SPI_MSB, SPI_LSB
	SPI_InitStructure.SPI_Mode      = SPI_Mode_Slave;		//主从选择   SPI_Mode_Master, SPI_Mode_Slave
	SPI_InitStructure.SPI_CPOL      = SPI_CPOL_Low;			//时钟相位   SPI_CPOL_High,   SPI_CPOL_Low
	SPI_InitStructure.SPI_CPHA      = SPI_CPHA_2Edge;		//数据边沿   SPI_CPHA_1Edge,  SPI_CPHA_2Edge
	SPI_InitStructure.SPI_Speed     = SPI_Speed_4;			//SPI速度    SPI_Speed_4,SPI_Speed_16,SPI_Speed_64,SPI_Speed_2/SPI_Speed_32
	SPI_Init(&SPI_InitStructure);
	NVIC_SPI_Init(ENABLE,Priority_3);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
	
	SPI_SW(SPI_P12_P13_P14_P15);	//SPI_P12_P13_P14_P15,SPI_P22_P23_P24_P25,SPI_P54_P40_P41_P43,SPI_P35_P34_P33_P32
	SPI_SS = 1;
}

/***************  串口初始化函数 *****************/
void	PWM_config(void)
{
	PWMx_InitDefine		PWMx_InitStructure;
	PWMA_Prescaler(15);//预分频 22118400 / 16 = 1382400
	PWMx_InitStructure.PWM_Mode    =	CCMRn_PWM_MODE1;	//模式,		CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
	PWMx_InitStructure.PWM_Duty    = PWMA_Duty.PWM1_Duty;	//PWM占空比时间, 0~Period
	PWMx_InitStructure.PWM_EnoSelect   = ENO1P ;	//输出通道选择,	ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
	PWM_Configuration(PWM1, &PWMx_InitStructure);			//初始化PWM,  PWMA,PWMB
  /* 频率 = 1382400 / (27647 + 1) = 50 hz */
	PWMx_InitStructure.PWM_Period   = 27647;				//周期时间,   0~65535
	PWMx_InitStructure.PWM_DeadTime = 0;					//死区发生器设置, 0~255
	PWMx_InitStructure.PWM_MainOutEnable= ENABLE;			//主输出使能, ENABLE,DISABLE
	PWMx_InitStructure.PWM_CEN_Enable   = ENABLE;			//使能计数器, ENABLE,DISABLE
	PWM_Configuration(PWMA, &PWMx_InitStructure);			//初始化PWM通用寄存器,  PWMA,PWMB

	PWM1_SW(PWM1_SW_P10_P11);			//PWM1_SW_P10_P11,PWM1_SW_P20_P21,PWM1_SW_P60_P61

	NVIC_PWM_Init(PWMA,DISABLE,Priority_0);
}

/******************** INT配置 ********************/
//void	Exti_config(void)
//{
//	EXTI_InitTypeDef	Exti_InitStructure;							//结构定义

//	Exti_InitStructure.EXTI_Mode      = EXT_MODE_Fall;//中断模式,   EXT_MODE_RiseFall,EXT_MODE_Fall
//	Ext_Inilize(EXT_INT0,&Exti_InitStructure);				//初始化
//	NVIC_INT0_Init(ENABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

//}

/******************** task A **************************/
void main(void)
{
	u8	i;

	EAXSFR();		/* 扩展寄存器访问使能 */
	GPIO_config();
  Timer_config();
	UART_config();
	SPI_config();
  PWM_config();
//  Exti_config();
  RC522_Init();
  
	EA = 1;
  
  gMCUREAL.BEEP_RUN = 1;
  PWMA_Duty.PWM1_Duty = DOOR_OFF; //PWM的高电平时间 = 0.5ms +(转动角度/180°)*2ms 周期20ms
  LED1 = 1;
  UpdatePwm(PWMA, &PWMA_Duty);
	PrintString1("STC8 UART1与SPI透传程序\r\n");		//UART1发送一个字符串

	while (1)
	{
    if(gMCUREAL.KeyCtl) //按键按下马上发送
    {
       if(gMCUREAL.KeyCtl == 1)
	      PrintString1("按键 增加\r\n");		//UART1发送一个字符串
       else if(gMCUREAL.KeyCtl == 2)
	      PrintString1("按键 删除\r\n");		//UART1发送一个字符串
       else if(gMCUREAL.KeyCtl == 3)
       {
	      PrintString1("按键 开门\r\n");		//UART1发送一个字符串  
        gMCUREAL.MOTOR_RUN = 1;

       }         
        gMCUREAL.BEEP_RUN = 1;       
        gMCUREAL.KeyCtl = 0;
    }
				
		if(COM1.RX_TimeOut > 0)
		{
			if(--COM1.RX_TimeOut == 0)
			{
				if(COM1.RX_Cnt > 0)
				{
					UartReceived = 1;   //设置串口接收标志
				}
			}
		}
    if(!gMCUREAL.MOTOR_RUN)
     	CardHanding();
    if(Task200ms) //200ms
    {

        Task200ms = 0;
        LED1 = !LED1;
    }
    if(Task2ms)
    {
        Task2ms = 0;
        KEY_task(); //按键扫描
    }
	}
}



touch.c

#include "Touch.H"

/************************************************************************/
/* 函数: void KEY_task(void)        									*/
/* 描述: 触摸按键任务										            */
/* 参数: None.															*/
/* 返回: None.															*/
/* 版本: V1.0  2023-07-11												*/
/************************************************************************/
void KEY_task(void)
{
    if(CardADD == 0) //低电平按下  增加
    {
        if(TK_cnt[0] < KeyTim)
            TK_cnt[0]++;
    }
    else
    {
        if(TK_cnt[0] >= KeyTim)
        {
            gMCUREAL.KeyCtl = 1;
        }
        TK_cnt[0] = 0;
    }

    if(CardDEL == 0) //低电平按下 删除
    {
        if(TK_cnt[1] < KeyTim)
            TK_cnt[1]++;
    }
    else
    {
        if(TK_cnt[1] >= KeyTim) //50ms
        {
            gMCUREAL.KeyCtl = 2;
        }
        TK_cnt[1] = 0;
    }

    if(CardOPE == 0) //低电平按下 开门
    {
        if(TK_cnt[2] < KeyTim)
            TK_cnt[2]++;
    }
    else
    {
        if(TK_cnt[2] >= KeyTim)
        {
            gMCUREAL.KeyCtl = 3;
        }
        TK_cnt[2] = 0;
    }
}


/****************************************   END ****************************************************/

touch.h

#ifndef		__Touch_H
#define		__Touch_H

#include	"config.h"
#include	"RAM.h"

#define KeyTim   15 //50ms 按下

void KEY_task(void);

#endif

RAM.c

#include "RAM.H"

/*************	本地变量声明	**************/

TYP_MCUREAL gMCUREAL;

/*************	本地变量声明	**************/
u16	xdata TK_cnt[3] = {0};		// 按键计数值, 16位
u16	xdata RC_cnt[2] = {0};		// 卡号计数
u16 xdata MOTOR_cnt = 0; //锁复位计数

u16 xdata ms_timer = 0;

bit Task2ms = 0;
//bit Task10ms = 0;
bit Task200ms = 0;

u8 xdata ID_ASC[8] = {0};//ascii显示卡号
u8 xdata g_ucTempbuf[4] = {0};

/**************************************  END **************************************/

RAM.h

#ifndef	__RAM_H
#define	__RAM_H

#include "config.h"

// 宏定义
#define PWMA_PERIOD  27647
#define DOOR_ON    PWMA_PERIOD*0.1f
#define DOOR_OFF   PWMA_PERIOD*0.05f

typedef struct
{
    u8 KeyCtl;        //按键控制 0 无 1 增加 2 删除 3 开门
    u8 BEEP_RUN: 1;   //蜂鸣器运行 1 运行 0停止
    u8 MOTOR_RUN: 1;   //马达运行 1 运行 0停止
//    u8 RC;   //卡号核对标志位 

} TYP_MCUREAL;	// gMCUREAL;


extern TYP_MCUREAL gMCUREAL;

extern u16 xdata TK_cnt[3];			// 按键计数值, 16位
extern u16 xdata RC_cnt[2];		// 卡号计数
extern u16 xdata MOTOR_cnt; //锁复位计数

extern u16 xdata ms_timer;

extern bit Task2ms;
//extern bit Task10ms;
extern bit Task200ms;


extern u8 xdata ID_ASC[8];//ascii显示卡号
extern u8 xdata g_ucTempbuf[4];

sbit CardADD = P3^6;  //增加 SW2
sbit CardDEL = P3^5;  //删除 SW1
sbit CardOPE = P3^2;  //开门 SW3
sbit BEEP    = P3^7; //蜂鸣器
sbit LED1    = P3^4; //LED1

#endif

/**************************************  END **************************************/

RC522.c

#include "rc522.h"

#define MAXRLEN 18
extern uint8 xdata g_ucTempbuf[4];
extern uint8  xdata ID_ASC[8];
u8 xdata UI0[4]= {0x83,0xAF,0x4A,0x29};	  //	此处为6张卡的信息,UI0到UI5
u8 xdata UI1[4]= {0xF3,0xB5,0x6E,0x14};

void delay2(unsigned int z)
{
    unsigned int x,y;
    for(x=z; x>0; x--)
        for(y=110; y>0; y--);
}

/***************************************************************************
 * 描  述 : 寻卡
 * 参  数 : req_code[IN]:寻卡方式
 *            0x52 = 寻感应区内所有符合14443A标准的卡
 *            0x26 = 寻未进入休眠状态的卡
 *            pTagType[OUT]:卡片类型代码
 *            0x4400 = Mifare_UltraLight
 *            0x0400 = Mifare_One(S50)
 *            0x0200 = Mifare_One(S70)
 *            0x0800 = Mifare_Pro(X)
 *            0x4403 = Mifare_DESFire
 * 返回值 : 成功返回MI_OK
 **************************************************************************/
char RC522_Request(uint8 req_code,uint8 *pTagType)
{
    char status;
    uint16  unLen;
    xdata uint8 ucComMF522Buf[MAXRLEN];

    ClearBitMask(Status2Reg,0x08);
    WriteRawRC(BitFramingReg,0x07);
    SetBitMask(TxControlReg,0x03);

    ucComMF522Buf[0] = req_code;

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);

    if ((status == MI_OK) && (unLen == 0x10))
    {
        *pTagType     = ucComMF522Buf[0];
        *(pTagType+1) = ucComMF522Buf[1];
    }
    else
    {
        status = MI_ERR;
    }

    return status;
}

/
//功    能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/
char RC522_Anticoll(uint8 *pSnr)
{
    char status;
    uint8 i,snr_check=0;
    unsigned int  unLen;
    xdata uint8 ucComMF522Buf[MAXRLEN];


    ClearBitMask(Status2Reg,0x08);
    WriteRawRC(BitFramingReg,0x00);
    ClearBitMask(CollReg,0x80);

    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x20;

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

    if (status == MI_OK)
    {
        for (i=0; i<4; i++)
        {
            *(pSnr+i)  = ucComMF522Buf[i];
            snr_check ^= ucComMF522Buf[i];
        }
        if (snr_check != ucComMF522Buf[i])
        {
            status = MI_ERR;
        }
    }

    SetBitMask(CollReg,0x80);
    return status;
}
/
//功    能:选定卡片
//参数说明: pSnr[IN]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/
char PcdSelect(unsigned char *pSnr)
{
    char status;
    unsigned char i;
    unsigned int  unLen;
    xdata unsigned char ucComMF522Buf[MAXRLEN];

    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
        ucComMF522Buf[i+2] = *(pSnr+i);
        ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);

    ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);

    if ((status == MI_OK) && (unLen == 0x18))
    {
        status = MI_OK;
    }
    else
    {
        status = MI_ERR;
    }

    return status;
}

/
//功    能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
//                 0x60 = 验证A密钥
//                 0x61 = 验证B密钥
//          addr[IN]:块地址
//          pKey[IN]:密码
//          pSnr[IN]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/

//char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
//{
//    char status;
//    unsigned int  unLen;
//    unsigned char i;
//	  xdata uint8 ucComMF522Buf[MAXRLEN];

//    ucComMF522Buf[0] = auth_mode;
//    ucComMF522Buf[1] = addr;
//    for (i=0; i<6; i++)
//    {    ucComMF522Buf[i+2] = *(pKey+i);   }
//    for (i=0; i<6; i++)
//    {    ucComMF522Buf[i+8] = *(pSnr+i);   }
// //   memcpy(&ucComMF522Buf[2], pKey, 6);
// //   memcpy(&ucComMF522Buf[8], pSnr, 4);
//
//    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
//    if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
//    {   status = MI_ERR;   }
//
//    return status;
//}

/
//功    能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
//          pData[OUT]:读出的数据,16字节
//返    回: 成功返回MI_OK
/
//char PcdRead(unsigned char addr,unsigned char *pData)
//{
//    char status;
//    unsigned int  unLen;
//    unsigned char i;
//	  xdata uint8 ucComMF522Buf[MAXRLEN];

//    ucComMF522Buf[0] = PICC_READ;
//    ucComMF522Buf[1] = addr;
//    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
//
//    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
//    if ((status == MI_OK) && (unLen == 0x90))
// //   {   memcpy(pData, ucComMF522Buf, 16);   }
//    {
//        for (i=0; i<16; i++)
//        {    *(pData+i) = ucComMF522Buf[i];   }
//    }
//    else
//    {   status = MI_ERR;   }
//
//    return status;
//}

/
//功    能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
//          pData[IN]:写入的数据,16字节
//返    回: 成功返回MI_OK
/
//char PcdWrite(unsigned char addr,unsigned char *pData)
//{
//    char status;
//    unsigned int  unLen;
//    unsigned char i;
//	  xdata uint8 ucComMF522Buf[MAXRLEN];
//
//    ucComMF522Buf[0] = PICC_WRITE;
//    ucComMF522Buf[1] = addr;
//    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
//
//    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

//    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
//    {   status = MI_ERR;   }
//
//    if (status == MI_OK)
//    {
//        //memcpy(ucComMF522Buf, pData, 16);
//        for (i=0; i<16; i++)
//        {    ucComMF522Buf[i] = *(pData+i);   }
//        CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);

//        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
//        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
//        {   status = MI_ERR;   }
//    }
//
//    return status;
//}



/
//功    能:命令卡片进入休眠状态
//返    回: 成功返回MI_OK
/
void PcdHalt(void)
{
    xdata uint8 ucComMF522Buf[MAXRLEN];

    ucComMF522Buf[0] = PICC_HALT;
    ucComMF522Buf[1] = 0;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
}

/
//用MF522计算CRC16函数
/
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
{
    unsigned char i,n;
    ClearBitMask(DivIrqReg,0x04);
    WriteRawRC(CommandReg,PCD_IDLE);
    SetBitMask(FIFOLevelReg,0x80);
    for (i=0; i<len; i++)
    {
        WriteRawRC(FIFODataReg, *(pIndata+i));
    }
    WriteRawRC(CommandReg, PCD_CALCCRC);
    i = 0xFF;
    do
    {
        n = ReadRawRC(DivIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x04));
    pOutData[0] = ReadRawRC(CRCResultRegL);
    pOutData[1] = ReadRawRC(CRCResultRegM);
}

/
//功    能:复位RC522
//返    回: 成功返回MI_OK
/
char RC522_Reset(void)
{
    MF522_RST=1;

    _nop_();

    MF522_RST=0;

    _nop_();

    MF522_RST=1;

    delay2(20);

    WriteRawRC(CommandReg,PCD_RESETPHASE);

    _nop_();


    WriteRawRC(ModeReg,0x3D);            //和Mifare卡通讯,CRC初始值0x6363
    WriteRawRC(TReloadRegL,30);
    WriteRawRC(TReloadRegH,0);
    WriteRawRC(TModeReg,0x8D);
    WriteRawRC(TPrescalerReg,0x3E);
    WriteRawRC(TxAutoReg,0x40);
    return MI_OK;
}

/
//功    能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返    回:读出的值
/
unsigned char ReadRawRC(unsigned char Address)
{
    unsigned char i, ucAddr;
    unsigned char ucResult=0;

    MF522_SCK = 0;
    MF522_SDA = 0;
    ucAddr = ((Address<<1)&0x7E)|0x80;

    for(i=8; i>0; i--)
    {
        MF522_MOSI = ((ucAddr&0x80)==0x80);
        MF522_SCK = 1;
        ucAddr <<= 1;
        MF522_SCK = 0;
    }

    for(i=8; i>0; i--)
    {
        MF522_SCK = 1;
        ucResult <<= 1;
        ucResult|=(bit)MF522_MISO;
        MF522_SCK = 0;
    }

    MF522_SDA = 1;
    MF522_SCK = 1;
    return ucResult;
}

/***************************************************************************
 * 描  述 : 写RC632寄存器
 * 参  数 : Address[IN]:寄存器地址  value[IN]:写入的值
 * 返回值 : 无
 **************************************************************************/
void WriteRawRC(unsigned char Address, unsigned char value)
{
    unsigned char i, ucAddr;

    MF522_SCK = 0;
    MF522_SDA = 0;
    ucAddr = ((Address<<1)&0x7E);

    for(i=8; i>0; i--)
    {
        MF522_MOSI = ((ucAddr&0x80)==0x80);
        MF522_SCK = 1;
        ucAddr <<= 1;
        MF522_SCK = 0;
    }

    for(i=8; i>0; i--)
    {
        MF522_MOSI = ((value&0x80)==0x80);
        MF522_SCK = 1;
        value <<= 1;
        MF522_SCK = 0;
    }
    MF522_SDA = 1;
    MF522_SCK = 1;
}

/***************************************************************************
 * 描  述 : 置RC522寄存器位
 * 参  数 : reg[IN]:寄存器地址  mask[IN]:置位值
 * 返回值 : 无
 **************************************************************************/
void SetBitMask(unsigned char reg,unsigned char mask)
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg,tmp | mask);  // set bit mask
}

/***************************************************************************
 * 描  述 : 清RC522寄存器位
 * 参  数 : reg[IN]:寄存器地址
 *          mask[IN]:清位值
 * 返回值 : 无
 **************************************************************************/
void ClearBitMask(uint8 reg,uint8 mask)
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask
}

/***************************************************************************
 * 描  述 : 通过RC522和ISO14443卡通讯
 * 参  数 : Command[IN]:RC522命令字
 *          pInData[IN]:通过RC522发送到卡片的数据
 *          InLenByte[IN]:发送数据的字节长度
 *          pOutData[OUT]:接收到的卡片返回数据
 *          *pOutLenBit[OUT]:返回数据的位长度
 * 返回值 : 无
 **************************************************************************/
char PcdComMF522(unsigned char Command,
                 unsigned char *pInData,
                 unsigned char InLenByte,
                 unsigned char *pOutData,
                 unsigned int  *pOutLenBit)
{
    char status = MI_ERR;
    unsigned char irqEn   = 0x00;
    unsigned char waitFor = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;
    switch (Command)
    {
    case PCD_AUTHENT:
        irqEn   = 0x12;
        waitFor = 0x10;
        break;
    case PCD_TRANSCEIVE:
        irqEn   = 0x77;
        waitFor = 0x30;
        break;
    default:
        break;
    }

    WriteRawRC(ComIEnReg,irqEn|0x80);
    ClearBitMask(ComIrqReg,0x80);
    WriteRawRC(CommandReg,PCD_IDLE);
    SetBitMask(FIFOLevelReg,0x80);

    for (i=0; i<InLenByte; i++)
    {
        WriteRawRC(FIFODataReg, pInData[i]);
    }
    WriteRawRC(CommandReg, Command);


    if (Command == PCD_TRANSCEIVE)
    {
        SetBitMask(BitFramingReg,0x80);
    }

    i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
    do
    {
        n = ReadRawRC(ComIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x01) && !(n&waitFor));
    ClearBitMask(BitFramingReg,0x80);

    if (i!=0)
    {
        if(!(ReadRawRC(ErrorReg)&0x1B))
        {
            status = MI_OK;
            if (n & irqEn & 0x01)
            {
                status = MI_NOTAGERR;
            }
            if (Command == PCD_TRANSCEIVE)
            {
                n = ReadRawRC(FIFOLevelReg);
                lastBits = ReadRawRC(ControlReg) & 0x07;
                if (lastBits)
                {
                    *pOutLenBit = (n-1)*8 + lastBits;
                }
                else
                {
                    *pOutLenBit = n*8;
                }
                if (n == 0)
                {
                    n = 1;
                }
                if (n > MAXRLEN)
                {
                    n = MAXRLEN;
                }
                for (i=0; i<n; i++)
                {
                    pOutData[i] = ReadRawRC(FIFODataReg);
                }
            }
        }
        else
        {
            status = MI_ERR;
        }

    }


    SetBitMask(ControlReg,0x80);           // stop timer now
    WriteRawRC(CommandReg,PCD_IDLE);
    return status;
}

/***************************************************************************
 * 描  述 : 开启天线,每次启动或关闭天线发射之间应至少有1ms的间隔
 * 参  数 : 无
 * 返回值 : 无
 **************************************************************************/
void PcdAntennaOn(void)
{
    uint8 i;
    i = ReadRawRC(TxControlReg);
    if (!(i & 0x03))
    {
        SetBitMask(TxControlReg, 0x03);
    }
}

/***************************************************************************
 * 描  述 : 关闭天线
 * 参  数 : 无
 * 返回值 : 无
 **************************************************************************/
void PcdAntennaOff(void)
{
    ClearBitMask(TxControlReg, 0x03);
}

//
//设置RC522的工作方式
//
char M500PcdConfigISOType(unsigned char type)
{
    if (type == 'A')                     //ISO14443_A
    {
        ClearBitMask(Status2Reg,0x08);
        WriteRawRC(ModeReg,0x3D);
        WriteRawRC(RxSelReg,0x86);
        WriteRawRC(RFCfgReg,0x7F);
        WriteRawRC(TReloadRegL,30);
        WriteRawRC(TReloadRegH,0);
        WriteRawRC(TModeReg,0x8D);
        WriteRawRC(TPrescalerReg,0x3E);
        delay2(400);
        PcdAntennaOn();
    }
    else {
        return -1;
    }

    return MI_OK;
}

void hexToasc(uint8 *a,uint8 *b,uint16 hlong)
{
    uint8 i;
    for(i=0; i<hlong; i++) //16进制转化成ASCII
    {
        if(a[i]/16>9)	b[i*2]=a[i]/16+'7';
        else b[i*2]=a[i]/16+'0';

        if(a[i]%16>9)	b[i*2+1]=a[i]%16+'7';
        else b[i*2+1]=a[i]%16+'0';
    }
}

void RC522_Init(void)
{
    RC522_Reset();
    PcdAntennaOff();
    M500PcdConfigISOType( 'A' );
}

uint8 CardHanding(void)
{
    uint8 status,i;

    status = RC522_Request(PICC_REQIDL, g_ucTempbuf);//寻卡,返回卡的类型:2个字节
//	if (status != MI_OK)
//	{
//		RC522_Reset();
//		PcdAntennaOff();
//		PcdAntennaOn();
//		return 0;
//	}
    status = RC522_Anticoll(g_ucTempbuf);//防冲撞,返回卡的序列号:4字节
    if(status == MI_OK)
    for(i=0; i<4; i++)	
    {
//            hexToasc(g_ucTempbuf,ID_ASC,4);    //发送卡号,4个字节  只有接收到读卡命令才发送
//            TX1_write2buff(g_ucTempbuf[i]);
        if(g_ucTempbuf[i] == UI0[i])
          RC_cnt[0]++;
        else if(g_ucTempbuf[i] == UI1[i])
          RC_cnt[1]++;
    }
    if(RC_cnt[0] == 4 || RC_cnt[1] == 4)
    {
       RC_cnt[0] = 0;
       RC_cnt[1] = 0;
//       gMCUREAL.RC = 0;
       gMCUREAL.MOTOR_RUN = 1;
       PrintString1("卡片 开门\r\n");		//UART1发送一个字符串
    }
    status = PcdSelect(g_ucTempbuf);//选定卡片
    if(status != MI_OK) return 0;
//	PcdHalt();
    return 0;
}

RC522.h

#ifndef __RC522_H_
#define __RC522_H_

#include "config.h"
#include "string.h"
#include "STC8G_H_Delay.h"
#include "STC8G_H_UART.h"
#include "RAM.H"


/**********************
引脚别名定义
***********************/
sbit     MF522_SDA  = P1^6;		  //SDA
sbit     MF522_SCK  = P1^5;     //SCK
sbit     MF522_MOSI = P1^3;     //MOSI
sbit     MF522_MISO = P1^4;     //MISO
sbit     MF522_RST  = P1^2;     //RST



char RC522_Reset(void);
void PcdAntennaOn(void);
void PcdAntennaOff(void);
char RC522_Request(unsigned char req_code,unsigned char *pTagType);
char RC522_Anticoll(unsigned char *pSnr);
char PcdSelect(unsigned char *pSnr);
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);
char PcdRead(unsigned char addr,unsigned char *pData);
char PcdWrite(unsigned char addr,unsigned char *pData);
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue);
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr);
void PcdHalt(void);
char PcdComMF522(unsigned char Command,
                 unsigned char *pInData,
                 unsigned char InLenByte,
                 unsigned char *pOutData,
                 unsigned int  *pOutLenBit);
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData);
void WriteRawRC(unsigned char Address,unsigned char value);
unsigned char ReadRawRC(unsigned char Address);
void SetBitMask(unsigned char reg,unsigned char mask);
void ClearBitMask(unsigned char reg,unsigned char mask);
char M500PcdConfigISOType(unsigned char type);
void RC522_Init(void);
uint8 CardHanding(void);
void hexToasc(uint8 *a,uint8 *b,uint16 hlong);
/
//MF522命令字
/
#define PCD_IDLE              0x00               //取消当前命令
#define PCD_AUTHENT           0x0E               //验证密钥
#define PCD_RECEIVE           0x08               //接收数据
#define PCD_TRANSMIT          0x04               //发送数据
#define PCD_TRANSCEIVE        0x0C               //发送并接收数据
#define PCD_RESETPHASE        0x0F               //复位
#define PCD_CALCCRC           0x03               //CRC计算

/
//Mifare_One卡片命令字
/
#define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态
#define PICC_REQALL           0x52               //寻天线区内全部卡
#define PICC_ANTICOLL1        0x93               //防冲撞
#define PICC_ANTICOLL2        0x95               //防冲撞
#define PICC_AUTHENT1A        0x60               //验证A密钥
#define PICC_AUTHENT1B        0x61               //验证B密钥
#define PICC_READ             0x30               //读块
#define PICC_WRITE            0xA0               //写块
#define PICC_DECREMENT        0xC0               //扣款
#define PICC_INCREMENT        0xC1               //充值
#define PICC_RESTORE          0xC2               //调块数据到缓冲区
#define PICC_TRANSFER         0xB0               //保存缓冲区中数据
#define PICC_HALT             0x50               //休眠

/
//MF522 FIFO长度定义
/
#define DEF_FIFO_LENGTH       64                 //FIFO size=64byte

/
//MF522寄存器定义
/
// PAGE 0
#define     RFU00                 0x00
#define     CommandReg            0x01
#define     ComIEnReg             0x02
#define     DivlEnReg             0x03
#define     ComIrqReg             0x04
#define     DivIrqReg             0x05
#define     ErrorReg              0x06
#define     Status1Reg            0x07
#define     Status2Reg            0x08
#define     FIFODataReg           0x09
#define     FIFOLevelReg          0x0A
#define     WaterLevelReg         0x0B
#define     ControlReg            0x0C
#define     BitFramingReg         0x0D
#define     CollReg               0x0E
#define     RFU0F                 0x0F
// PAGE 1
#define     RFU10                 0x10
#define     ModeReg               0x11
#define     TxModeReg             0x12
#define     RxModeReg             0x13
#define     TxControlReg          0x14
#define     TxAutoReg             0x15
#define     TxSelReg              0x16
#define     RxSelReg              0x17
#define     RxThresholdReg        0x18
#define     DemodReg              0x19
#define     RFU1A                 0x1A
#define     RFU1B                 0x1B
#define     MifareReg             0x1C
#define     RFU1D                 0x1D
#define     RFU1E                 0x1E
#define     SerialSpeedReg        0x1F
// PAGE 2
#define     RFU20                 0x20
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     RFU23                 0x23
#define     ModWidthReg           0x24
#define     RFU25                 0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsCfgReg            0x28
#define     ModGsCfgReg           0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F
// PAGE 3
#define     RFU30                 0x30
#define     TestSel1Reg           0x31
#define     TestSel2Reg           0x32
#define     TestPinEnReg          0x33
#define     TestPinValueReg       0x34
#define     TestBusReg            0x35
#define     AutoTestReg           0x36
#define     VersionReg            0x37
#define     AnalogTestReg         0x38
#define     TestDAC1Reg           0x39
#define     TestDAC2Reg           0x3A
#define     TestADCReg            0x3B
#define     RFU3C                 0x3C
#define     RFU3D                 0x3D
#define     RFU3E                 0x3E
#define     RFU3F		  0x3F

/
//和MF522通讯时返回的错误代码
/
#define MI_OK                          0
#define MI_NOTAGERR                    (-1)
#define MI_ERR                         (-2)



#endif

STC8G_H_Timer.c

//========================================================================
// 函数: Timer0_ISR_Handler
// 描述: Timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-23
//========================================================================
void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR		//进中断时已经清除标志
{
    // TODO: 在此处添加用户代码
    ms_timer++;
    if(ms_timer >= one_ms)  //one_ms
    {
        ms_timer = 0;
    }
    if(ms_timer%send_speed == 0) //200ms运行一次
    {
        Task200ms = 1;
        if(gMCUREAL.BEEP_RUN)
        {
            BEEP = 0;
            gMCUREAL.BEEP_RUN = 0;
        }
        else
            BEEP = 1;
    }
    if(ms_timer%high_speed == 0) //2ms运行一次
    {
        Task2ms = 1;
        if(gMCUREAL.MOTOR_RUN)
        {
            if(MOTOR_cnt == 0)
            {
                PWMA_Duty.PWM1_Duty = DOOR_ON; //PWM的高电平时间 = 0.5ms +(转动角度/180°)*2ms 周期20ms
                UpdatePwm(PWMA, &PWMA_Duty);
            }
            MOTOR_cnt++;
            if(MOTOR_cnt  > 5000)  //10s复位舵机
            {
                PWMA_Duty.PWM1_Duty = DOOR_OFF; //PWM的高电平时间 = 0.5ms +(转动角度/180°)*2ms 周期20ms
                UpdatePwm(PWMA, &PWMA_Duty);
                gMCUREAL.MOTOR_RUN = 0;
            }
        }
        else
            MOTOR_cnt = 0;
    }

}

       

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值