0%

基于stm32+rc522的门禁系统

基于stm32+rc522的门禁系统

元器件:stm32f103c8t6,RC522,MG90S舵机

所有的代码放在这里了:https://gitee.com/armgpio/access-control-system

首先,配置LED以及MG90S初始化

​ MG90S的OUT口接的是PB6,也就是stm32f103c8t6定时器TIM4的通道1。通过TIM4产生周期为20ms的PWM波,当高电平所占时间为1ms时,舵机转到中点位置。

mg90s.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void TIM4_PWM_Init(u16 arr,u16 psc)
{
//**结构体声明**//
GPIO_InitTypeDef GPIO_InitStructure; //声明GPIO
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //声明定时器
TIM_OCInitTypeDef TIM_OCInitStructure; //声明PWM通道

//**时钟使能**//
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器TIM4时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟

//配置GPIO//
GPIO_InitStructure.GPIO_Pin = PWM_GPIO_PIN; //PWM 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(MOTO_GPIO_PORT, &GPIO_InitStructure); //根据设定参数初始化GPIOB6
GPIO_SetBits(MOTO_GPIO_PORT,PWM_GPIO_PIN);

//初始化TIM4
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

//初始化TIM4 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM4, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM4 OC1

TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); //让oc1能重装载

TIM_Cmd(TIM4, ENABLE); //使能TIM4

}

RC522的配置

​ 对于RC522来说,使用的是单片机的硬件SPI。在SPI通信中,需要用到微秒的延时,所以这里还要用到嘀嗒定时器。配置好嘀嗒定时器后,就是RC522的初始化。

RC522的初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
void RC522_Init ( void )
{
RC522_SPI_Config ();
RC522_Reset_Disable();
RC522_CS_Disable();
}

/**
* @brief R522 SPI配置
* @param 无
* @retval 无
*/
static void RC522_SPI_Config ( void )
{
/* SPI_InitTypeDef SPI_InitStructure */
GPIO_InitTypeDef GPIO_InitStructure;

/*!< Configure SPI_RC522_SPI pins: CS */
RC522_GPIO_CS_CLK_FUN ( RC522_GPIO_CS_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = RC522_GPIO_CS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = RC522_GPIO_CS_Mode;
GPIO_Init(RC522_GPIO_CS_PORT, &GPIO_InitStructure);

/*!< Configure SPI_RC522_SPI pins: SCK */
RC522_GPIO_SCK_CLK_FUN ( RC522_GPIO_SCK_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = RC522_GPIO_SCK_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = RC522_GPIO_SCK_Mode;
GPIO_Init(RC522_GPIO_SCK_PORT, &GPIO_InitStructure);

/*!< Configure SPI_RC522_SPI pins: MOSI */
RC522_GPIO_MOSI_CLK_FUN ( RC522_GPIO_MOSI_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = RC522_GPIO_MOSI_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = RC522_GPIO_MOSI_Mode;
GPIO_Init(RC522_GPIO_MOSI_PORT, &GPIO_InitStructure);

/*!< Configure SPI_RC522_SPI pins: MISO */
RC522_GPIO_MISO_CLK_FUN ( RC522_GPIO_MISO_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = RC522_GPIO_MISO_PIN;
GPIO_InitStructure.GPIO_Mode = RC522_GPIO_MISO_Mode;
GPIO_Init(RC522_GPIO_MISO_PORT, &GPIO_InitStructure);

/*!< Configure SPI_RC522_SPI pins: RST */
RC522_GPIO_RST_CLK_FUN ( RC522_GPIO_RST_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = RC522_GPIO_RST_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = RC522_GPIO_RST_Mode;
GPIO_Init(RC522_GPIO_RST_PORT, &GPIO_InitStructure);
}

main函数的配置

​ 在main.c里面包含两个函数,一个是寻卡函数,一个是main函数。首先定义的是卡A的密匙,基本上都是6个0xff。在寻卡函数里面,讲预先设定好的IC卡序列号存储在数组中,再将读取到的序列号和数组进行比对,这样就能正确识别到已经保存的卡片信息。

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
uint8_t KeyValue[]={0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF};   // 卡A密钥

void IC_test ( void )
{
//uint32_t writeValue = 100;
//uint32_t readValue;
//char cStr [ 30 ];
uint8_t ucArray_ID [ 4 ]; /*先后存放IC卡的类型和UID(IC卡序列号)*/
uint8_t ucStatusReturn; /*返回状态*/
u8 ID1[]={0xA9,0x37,0x71,0xe4};
while ( 1 )
{
/*寻卡*/
if ( ( ucStatusReturn = PcdRequest ( PICC_REQIDL, ucArray_ID ) ) != MI_OK ) //ucArray_ID是卡片类型
/*若失败再次寻卡*/
ucStatusReturn = PcdRequest ( PICC_REQIDL, ucArray_ID );
if ( ucStatusReturn == MI_OK )
{
/*防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
if ( PcdAnticoll ( ucArray_ID ) == MI_OK )
{
PcdSelect(ucArray_ID); //选定卡片
PcdAuthState( PICC_AUTHENT1A, 0x11, KeyValue, ucArray_ID );//校验密码 (密码验证模式,块地址,密码,卡片序列号)
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
if(ID1[0]==ucArray_ID[0])
{
TIM_SetCompare1(TIM4,75);
Delay_ms(1000);
TIM_SetCompare1(TIM4,50);
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
}
else
{
TIM_SetCompare1(TIM4,50);
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
Delay_ms(1000);
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
Delay_ms(1000);
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
Delay_ms(1000);
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
Delay_ms(1000);
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
Delay_ms(1000);
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
Delay_ms(1000);
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
Delay_ms(1000);
GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
Delay_ms(1000);
}
PcdHalt();//令卡片进入休眠状态
}
}
}
}

int main(void)
{
SysTick_Init ();
RC522_Init ();

TIM4_PWM_Init(999,1439);
TIM_SetCompare1(TIM4,50);

LED_GPIO_Config();
GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);//先关灯

PcdReset();
M500PcdConfigISOType ( 'A' );
while(1)
{
IC_test();
}
}

​ 对于密码的存储是放在了代码中来进行实现的,没有添加记忆功能。