[STM32] Stm32f103c8t6+RC522 实现读卡写卡功能(超详细,零基础,小白)

 本篇文章内容总结下来就是

  1. 读卡            使用默认密码读卡所有扇区所有块的数据
  2. 写ID            使用默认密码读取卡一的0扇区的第一块数据并写入到卡二的0扇区的第一块里
  3. 密码读卡     不同厂家的初始密码不同,整理了一些默认密码,如果有收集到新的也可以补充进去
  4. 写全卡        使用默认密码读取卡一的全部扇区全部块数据并写入到卡二的全部扇区的全部块里

感谢@Khanivore!指出寻卡方法有参数没有写定义

目录

从来不按套路出牌的我

一.前期准备

STM32f103c8t6开发板

 Keil5编译器

串口工具

我就问你们什么叫专业

二.代码

简介RC522

代码功能

代码

总结

三.源码



从来不按套路出牌的我

没用的前言,看干货跳过这段

想必看到这篇文章的人都是已经翻阅了大量的文章资料,已经厌倦了那种通篇都是百度百科,通篇都是复制官方资料,通篇都是怎样点亮led灯的没有多少营养的文章

本篇文章除了插科打诨与耐人寻味的笑点之外尽可能的把干货提供给大家学习,我在学习RC522时大量的时间都花在查找资料上了,真正的编程时间可能只有找资料的三分之一,所以为了不让同样抱有学习热情的人因为找不到合适的资料而失去耐心最终失去学习的热情,我准备把我整理的干货拿出来与大家分享

没错,不务正业的我又回来了,这回是玩一玩Stm32单片机

当然也是从基础的C语言开始学习,大概自学了小半个月的C语言就开始上手Stm32了

自学是在B站看的视频,一边写笔记一边敲代码,好在有java的基础,不然我就和这行无缘了

好了废话不多说直接干货

一.前期准备

  1. Stm32f103c8t6开发板 1块
  2. RC522 1杯
  3. 杜邦线 适量
  4. 轻触开关 3g
  5. led灯  根据个人喜好添加
  6. ST-LINK V2 一根 也可以使用 CH340替代(根据个人喜好调整)
  7. 一台计算机 低于30吨的
  8. Keil5编译器 1千克
  9. 串口烧录程序 1匙
  10. 串口调试程序 1伊普西龙
  11. M1 CUID卡 2开尔文

 

STM32f103c8t6开发板

 

RC522模块

RC522相关资料:

链接: https://pan.baidu.com/s/1Qob5o4tv0_gBXrRk6AvLSQ

提取码: fkjt 

 

接线图

每个人接线的引脚不同,我这里是因为接入了其他无关紧要的模块才分开接线,不影响单独RC522连接STM32

RC522接线
RC522_RST  ======  GPIOA_Pin_0
RC522_MISO ======  GPIOA_Pin_1
RC522_MOSI ======  GPIOA_Pin_2  
RC522_SCK  ======  GPIOA_Pin_3  
RC522_SDA(NSS) ==  GPIOA_Pin_4
       GND ======  GND  
       ACC ======  ACC

按钮接线
KEY1_ACC === GPIOB_Pin_0
KEY2_ACC === GPIOB_Pin_1
     GND === GND

灯接线(也可以使用板载灯,这里使用板载灯)

LED5_ACC === GPIOA_Pin_5 //模式灯 在选择模式时用于显示当前模式用
LED6_ACC === GPIOA_Pin_6 //确认灯 在识别到卡1时会亮起提示换卡
    GND === GND

 我用最强画图工具<画图>绘制的接线图

 

 

 Keil5编译器

Keil5编译器

链接: https://pan.baidu.com/s/10jR0g10jxdosawc49IOazQ

提取码: uizh

Keil5开发环境

自己收集整理并添加一些自己常用的方法的Stm32f103c8t6开发环境,解压即用

Keil5开发环境

链接: https://pan.baidu.com/s/1U5sOv9lvs3wwKkisiAFYAA

提取码: z1ih 

串口工具

串口调试程序 串口烧录程序

链接: https://pan.baidu.com/s/11VCAXnfmO1FCQQVjirIkrQ

提取码: h1uz

失效私信我


我就问你们什么叫专业

硬件配置,开发环境详细到这个地步,初学者能够直接上手学习

这就是专业

这就是一条龙服务,以后你们给其他人分享这篇文章时都可以说被一条龙服务过

二.代码

简介RC522

 

官方文档一共有109页接下来都是复制这个文档所以大家可以走了[dog]

我就简单总结一下白话文:

1.RC522能读卡

2.RC522能写卡

3.RC522能... 就这样,就是能读卡能写卡,我们要它的功能也就是读卡写卡,我没必要为了实现一个读卡功能把这一百多也的文档看完,也没有必要为了实现一个功能就把它的原理全部吃透

介绍完毕

代码功能

  1. 读卡            使用默认密码读卡所有扇区所有块的数据
  2. 写ID            使用默认密码读取卡一的0扇区的第一块数据并写入到卡二的0扇区的第一块里
  3. 密码读卡     不同厂家初始密码不同,整理了一些初始密码,如果有收集到新的也可以补充进去
  4. 写全卡        使用默认密码读取卡一的全部扇区全部块数据并写入到卡二的全部扇区的全部块里

怎么样,干不干,全是干货,没有废话

1.读卡效果图

这是一张CUID白卡,一会复制可以用作对比

有人会问扇区啥意思 区块啥意思,这个就百度去吧好多文章在讲RC522或者复制卡的文章都会用很大篇幅讲什么是卡什么是扇区什么是区块什么是密码段,之后文章就结束了也不说怎么读怎么写怎么复制,最后来一句未完待续或者下一篇文章再详细的写,之后尸沉东京湾留下一段佳话,在这里因为我是旱鸭子就不写了

SQ代表扇区 0~15扇区

QK代表区块 0~3区块

 

2.写ID效果图

这是一张目标卡,我们要将这张卡的0扇区的0块数据写到上面那张空白卡中

进行写操作 放上卡1=> 读取卡1=> 识别到卡1后打印卡唯一id,并提示可进行复制=> 放上卡2=> 写入卡2

1.读取卡1

 

读取卡2

 已经写到卡2中了

3.密码读卡

每个扇区的3号区块存储的就是该扇区的密码,只有读取时携带相同的密码才能看到并修改该扇区的数据,如果没有密码都不会读到该扇区

因为厂家为了卡片的数据安全各厂会定义自己的读卡密码

个人收集了一部分密码分享一下

unsigned char KEY[14][6]={
													{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
													{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
													{0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5},
													{0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5},
													{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
													{0x4D, 0x3A, 0x99, 0xC3, 0x51, 0xDD},
													{0x1A, 0x98, 0x2C, 0x7E, 0x45, 0x9A},
													{0x71, 0x4C, 0x5C, 0x88, 0x6E, 0x97},
													{0x58, 0x7E, 0xE5, 0xF9, 0x35, 0x0F},
													{0xA0, 0x47, 0x8C, 0xC3, 0x90, 0x91},
													{0x53, 0x3C, 0xB6, 0xC7, 0x23, 0xf6},
													{0x8F, 0xD0, 0xA4, 0xF2, 0x56, 0xE9},
													{0x66, 0x55, 0x44, 0x11, 0x22, 0x33},
													{0x66, 0x55, 0x44, 0x33, 0x22, 0x11}
};

 

4.写全卡效果

效果就是两张一模一样的卡

代码

磨叽了半天终于到了重点

代码里出现的 if(EN) if(CN) if(OLED) 代表是否打印对应语言,

EN 代表打印英文

CN 代表打印中文

OLED 代表在屏幕显示(因为接入一块OLED屏幕)

寻卡

要点:每次对卡进行操作时调用,两个方法一模一样,就是第二种去掉了打印

验证卡片信息,防冲撞,选卡


//感谢Khanivore!指出有连个变量没有声明
unsigned char TagType[2];
unsigned char SelectedSnr[4];



//				
//						寻卡方法
//					
	
char Pcdmain(){
		u8 status;
	  u8 ID_num[9];
		u8 *ID;	//卡号
		status= PcdRequest(REQ_ALL,TagType);//寻卡
			if(!status){
			status = PcdAnticoll(SelectedSnr);//防冲撞	
				if(!status){
				status=PcdSelect(SelectedSnr);//选卡
					if(!status){
						if(EN)printf("Read the success !! \r\n");
						if(CN)printf("寻找卡片成功 !! \r\n");
						if(OLED)GUI_ShowString(0,16,"1",16,1);
						
						ID = Card_ID(SelectedSnr,ID_num); //获取卡ID
						
						if(EN)printf("ID:%s !! \r\n",ID_num);
						if(CN)printf("卡号:%s !! \r\n",ID_num);
						if(OLED)GUI_ShowString(16,16,"ID:",16,1);
						if(OLED)GUI_ShowString(40,16,ID,16,1);
						return status;
					}else{
					if(EN)printf("The selected card \r\n");
					if(CN)printf("卡片未找到 \r\n");
					if(OLED)GUI_ShowString(0,16,"2",16,1);
					return status;
					}
				}else{
				if(EN)printf("Anti-collision \r\n");
				if(CN)printf("卡片冲突 \r\n");
				if(OLED)GUI_ShowString(0,16,"3",16,1);
				return status;
				}
			}else{
			if(EN)printf("Looking for failure \r\n");
			if(CN)printf("卡片未找到 \r\n");
			if(OLED)GUI_ShowString(0,16,"4",16,1);
			return status;
			}
		}



//				
//						寻卡方法
//					
	
char Pcdmain_3(){
		u8 status;
		status= PcdRequest(REQ_ALL,TagType);//寻卡
			if(!status){
			status = PcdAnticoll(SelectedSnr);//防冲撞	
				if(!status){
				status=PcdSelect(SelectedSnr);//选卡
					if(!status){
						return status;
					}else{
					return status;
					}
				}else{
				return status;
				}
			}else{
			return status;
			}
		}

 

读卡

要点:密码密码密码 如果密码不对那就结束了,初始密码需要在成员变量中定义


//				
//					notarize = 1 读卡
//					
		

unsigned char  DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //默认密码 	

void  notarize_type1(){
		u8 status;
		u8 section=0;
		u8 block = 0;
		unsigned char block_value[16];
	
		u8 i=0;
		status = Pcdmain();
			if(!status){
				if(EN)printf("function NO1 Read the card ...\r\n");
				if(CN)printf("功能1 读取卡片 \r\n");
				if(OLED)GUI_ShowString(48,0,"NO_1",16,1);
						for( section = 0 ; section <16 ; section++ ){
								status = PcdAuthState(KEYA, (section*4+3), DefaultKey, SelectedSnr);// 校验1扇区密码,密码位于每一扇区第3块
							if(!status)
								{		
									for(block = 0; block< 4 ; block++){
										status = PcdRead((section*4+block), block_value);  // 读卡,读取1扇区0块数据到buf[0]-buf[16] 
										if(EN)printf("SQ:%d , QK:%d     ",section,block);
											if(EN)printf("passA	");
											for (i = 0 ; i<6; i++)
											{
											if(EN)printf("%X ",block_value[i]);
											}
											if(EN)printf("		Value	");
											for (i = 6; i<10; i++)
											{
											if(EN)printf("%X ",block_value[i]);
											}
											if(EN)printf("		passB	");
											for (i = 10; i<16; i++)
											{    
											if(EN)printf("%X ",block_value[i]);
											}
											if(EN)printf("\r\n");
									}
								}else {
									if(EN)printf("wrong password \r\n");
									if(CN)printf("密码错误 \r\n");
									if(OLED)GUI_ShowString(0,16,"5",16,1);
								}
							}
							if(EN)printf("\r\n");
							if(EN)printf("\r\n");
							if(EN)printf("\r\n");
				
				
				
			}else{
				if(EN)printf("Looking for failure \r\n");
				if(CN)printf("卡片未找到 \r\n");
				if(OLED)GUI_ShowString(0,16,"4",16,1);
			}
	}

 

复制ID

ID的重要性就不用我多说了,因为通常的ID卡扇区0是出厂就定义好的ID不能再修改,所以也是唯一性的保障,大多数的系统也只会记录ID作为验证使用

而除了0扇区之外的扇区多为详细信息存储使用,如取电卡的电量值,水卡的水量值,饭卡的余额之类,因为这部分可以读写所以密码会与出厂密码不同


//				
//					notarize = 2 复制卡id
//					
		
	void  notarize_type2(){
		u8 status;
		u8 test_status = 0; //id在0扇区 , 测试使用其他扇区
		u8 block_num=0;
		u8 copy_tf = 1;
		unsigned char copy_value[16];
		status = Pcdmain_3();
			if(!status){
				if(EN)printf("function NO1 Read the card ...\r\n");
				if(CN)printf("功能2 复制卡片 \r\n");
				if(OLED)GUI_ShowString(48,0,"NO_2",16,1);
				
				//读取并复制卡1 指定扇区指定块数据
				
				status = PcdAuthState(KEYA, (test_status*4+3), DefaultKey, SelectedSnr);// 校验1扇区密码,密码位于每一扇区第3块	DefaultKey为默认密码
						if(!status)
							{	
									status = PcdRead((test_status*4+0), copy_value);  // 读卡,读取1扇区0块数据到buf[0]-buf[16]
										if(!status)
										{
											if(EN)printf("COPY: SQ:%d , QK:%d     ",test_status,0);
											if(EN)printf("passA	");
											for (block_num = 0; block_num<6; block_num++)
											{    
											if(EN)printf("%X ",copy_value[block_num]);
											}
											if(EN)printf("		Value	");
											for (block_num = 6; block_num<10; block_num++)
											{    
											if(EN)printf("%X ",copy_value[block_num]);
											}
											if(EN)printf("		passB	");
											for (block_num = 10; block_num<16; block_num++)
											{    
											if(EN)printf("%X ",copy_value[block_num]);
											}
										
											if(EN)printf("\r\n");
											}
									if(EN)printf("Read over \r\n");
									if(CN)printf("复制成功 替换目标卡片 \r\n");
									delay_ms(500);		
									if(OLED)GUI_ShowString(0,16,"COPY OK, CARD_2",16,1);				
											
											//读取第二张卡片
											do{
																LED6S;   	//PC13输出低电平
																//delay_ms(200);
																//LED6S;				//PC13输出高电平
												
												
												if(KEY1==0){
												status = Pcdmain_3();
													if(!status){
														if(EN)printf("Ready to write card 2 ...\r\n");
														if(CN)printf("写卡2\r\n");
														if(OLED)GUI_ShowString(0,0,"CARD2...",16,1);
															status = PcdAuthState(KEYA, (test_status*4+3), DefaultKey, SelectedSnr);// 校验1扇区密码,密码位于每一扇区第3块	
																if(!status){
																	status = PcdWrite((test_status*4+0), copy_value);  // 写卡,将buf[0]-buf[16]写入1扇区0块
																	if(!status){
																			
																		
																			LED6R;				//PC13输出高电平
																			delay_ms(20);
																			LED6S;   	//PC13输出低电平
																			delay_ms(20);
																			LED6R;				//PC13输出高电平
																			delay_ms(20);
																			LED6S;   	//PC13输出低电平
																			delay_ms(20);
																			LED6R;				//PC13输出高电平
																		
																			if(EN)printf("Copy success (*^▽^*) \r\n");
																			if(CN)printf("写入成功 (*^▽^*) \r\n");
																			if(OLED)GUI_ShowString(0,16,"Copy SUCC (*^▽^*)",16,1);
																		}else{
																			if(EN)printf("Copy the failure (╯‵□′)╯︵┻━┻ \r\n");
																			if(CN)printf("复制失败	 (╯‵□′)╯︵┻━┻  \r\n");
																			if(OLED)GUI_ShowString(0,16,"Copy the failure",16,1);
																		}
																	}else{
																		if(EN)printf("card 2 wrong password \r\n");
																		if(CN)printf("卡2密码错误 \r\n");
																		if(OLED)GUI_ShowString(0,16,"card 2 PASS WRONG",16,1);	
																	}
																	LED6R;				//PC13输出高电平
													}else{
														if(EN)printf("Looking for failure \r\n");
														if(CN)printf("卡片2未找到 \r\n");
														if(OLED)GUI_ShowString(0,16,"4",16,1);
														LED6R;				//PC13输出高电平
													}
													LED6R;				//PC13输出高电平
													copy_tf = 0;
												}
											}while(copy_tf);
											
											
											
											
								}else{
									if(EN)printf("wrong password \r\n");
									if(CN)printf("密码错误 \r\n");
									if(OLED)GUI_ShowString(0,16,"5",16,1);	
								}

			}else{
				if(EN)printf("Looking for failure \r\n");
				if(CN)printf("卡片未找到 \r\n");
				if(OLED)GUI_ShowString(0,16,"4",16,1);
			}
	}

 

密码测试

测试每个扇区的第3区块密码,当然幸运的话就是初始密码,点背的话也没关系只需要255*255*255*255*255*255 = 274,941,996,890,625次尝试也可以得到密码


//				
//					notarize = 3 常规密码测试
//					
		
		void  notarize_type3(){
		u8 status;
		u8 section=0;
		u8 block_num=0;
		u8 KEY_num = 0 ;
		unsigned char block_value[16];
	
		u8 i=0;
		status = Pcdmain_3();
			if(!status){
				if(EN)printf("function NO3 Password test ...\r\n");
				if(CN)printf("功能3 常规密码测试 \r\n");
				if(OLED)GUI_ShowString(48,0,"NO_3",16,1);
						for( section = 0 ; section <16 ; section++ ){
					for( KEY_num =0 ; KEY_num < 13 ; KEY_num++){
								status = Pcdmain_3();
						if(!status){
								//printf("section:%d  KEY:%d %d %d %d %d %d   ",section,KEY[KEY_num][0],KEY[KEY_num][1],KEY[KEY_num][2],KEY[KEY_num][3],KEY[KEY_num][4],KEY[KEY_num][5]);
								status = PcdAuthState(KEYA, (section*4+3), KEY[KEY_num], SelectedSnr);// 校验1扇区密码,密码位于每一扇区第3块
							if(!status)
								{
									status = 1;
									//for(block_num = 0; block_num< 4 ; block_num++){
										
										status = PcdRead((section*4+3), block_value);  // 读卡,读取1扇区0块数据到buf[0]-buf[16] 
										if(EN)printf("SQ:%d , QK:%d  KEY:%X %X %X %X %X %X   ",section,3,KEY[KEY_num][0],KEY[KEY_num][1],KEY[KEY_num][2],KEY[KEY_num][3],KEY[KEY_num][4],KEY[KEY_num][5]);
											if(EN)printf("passA	");
											for (i = 0 ; i<6; i++)
											{ 
											if(EN)printf("%X ",block_value[i]);
											}
											if(EN)printf("		Value	");
											for (i = 6; i<10; i++)
											{    
											if(EN)printf("%X ",block_value[i]);
											}
											if(EN)printf("		passB	");
											for (i = 10; i<16; i++)
											{    
											if(EN)printf("%X ",block_value[i]);
											}
											if(EN)printf("\r\n");
											
									//}	
									
									
									
								}else {
									
								}
							}
							status = 1;
						}
					}
							if(EN)printf("\r\n");
							if(EN)printf("\r\n");
							if(EN)printf("\r\n");
						
			}else{
				if(EN)printf("Looking for failure \r\n");
				if(CN)printf("卡片未找到 \r\n");
				if(OLED)GUI_ShowString(0,16,"4",16,1);
			}
	}

复制全卡

由于全卡每个扇区的密码不同所以复制全卡用处不大


//				
//					notarize = 4 复制全卡
//					
		
		void  notarize_type4(){
		u8 status;
		u8 section=0;
		u8 block = 0;
		u8 block_num=0;
		u8 copy_tf = 1;
		unsigned char block_value[16];
		unsigned char copy_value[16][3][16];
	
		status = Pcdmain_3();
			if(!status){
				if(EN)printf("function NO1 Read the card ...\r\n");
				if(CN)printf("功能1 读取卡片 \r\n");
				if(OLED)GUI_ShowString(48,0,"NO_4",16,1);
					for( section = 0; section <16 ; section++ ){
								status = PcdAuthState(KEYA, (section*4+3), DefaultKey, SelectedSnr);// 校验1扇区密码,密码位于每一扇区第3块
								if(!status)
								{	
									for(block = 0; block< 3 ; block++){
										status = PcdRead((section*4+block), block_value);  // 读卡,读取1扇区0块数据到buf[0]-buf[16] 
										for( block_num = 0; block_num < 16 ; block_num++){
											copy_value[section][block][block_num] = block_value[block_num];
										}
										}
								}
							}
							
											if(EN)printf("\r\n");
											if(EN)printf("\r\n");
											if(EN)printf("\r\n");
											if(EN)printf("\r\n");
							
							for(section = 0 ; section < 16 ; section++){
									for(block = 0 ; block < 3 ; block++){
											//for(block_num = 0 ; block_num < 16 ; block_num++){
											if(EN)printf("SQ:%d , QK:%d     ",section,block);
											if(EN)printf("passA	");
											for (block_num = 0; block_num<6; block_num++)
											{    
											if(EN)printf("%X ",copy_value[section][block][block_num]);
											}
											if(EN)printf("		Value	");
											for (block_num = 6; block_num<10; block_num++)
											{    
											if(EN)printf("%X ",copy_value[section][block][block_num]);
											}
											if(EN)printf("		passB	");
											for (block_num = 10; block_num<16; block_num++)
											{    
											if(EN)printf("%X ",copy_value[section][block][block_num]);
											}
											
											if(EN)printf("\r\n");
										

							//}
							}
										if(EN)printf("\r\n");
							}
											if(EN)printf("\r\n");
											if(EN)printf("\r\n");
											if(EN)printf("\r\n");
							
							
									if(EN)printf("Read over \r\n");
									if(CN)printf("复制成功 替换目标卡片 \r\n");
									if(OLED)GUI_ShowString(0,16,"COPY OK, CARD_2",16,1);				
											
											//读取第二张卡片
											do{
												if(KEY1==0){
												status = Pcdmain_3();
													if(!status){
														if(EN)printf("Ready to write card 2 ...\r\n");
														if(CN)printf("写卡2\r\n");
														if(OLED)GUI_ShowString(0,0,"CARD2...",16,1);
																for(section = 0 ; section < 16 ; section++){
																		//status = Pcdmain_3();
																		//if(!status){
																			status = PcdAuthState(KEYA, (section*4+3), DefaultKey, SelectedSnr);// 校验1扇区密码,密码位于每一扇区第3块	
																			if(!status){
																			for(block = 0 ; block < 3 ; block++){
																				//status = PcdWrite((section*4+block), copy_value[section][block]);  // 写卡,将buf[0]-buf[16]写入1扇区0块
																				//status = PcdWrite((section*4+block), zero);  // 写卡,将buf[0]-buf[16]写入1扇区0块
																				status = PcdWrite((4*4+3), setkey);  // 写卡,将buf[0]-buf[16]写入1扇区0块
																				
																				if(EN)printf("SQ:%d , QK:%d     ",section,block);
																				if(EN)printf("passA	");
																				for (block_num = 0; block_num<6; block_num++)
																				{    
																				if(EN)printf("%X ",copy_value[section][block][block_num]);
																				}
																				if(EN)printf("		Value	");
																				for (block_num = 6; block_num<10; block_num++)
																				{    
																				if(EN)printf("%X ",copy_value[section][block][block_num]);
																				}
																				if(EN)printf("		passB	");
																				for (block_num = 10; block_num<16; block_num++)
																				{    
																				if(EN)printf("%X ",copy_value[section][block][block_num]);
																				}
																				
																				if(EN)printf("\r\n");
																				
																			if(!status){
																				if(EN)printf("SQ:%d , QK:%d     Copy success (*^▽^*) \r\n",section,block);
																				if(CN)printf("SQ:%d , QK:%d     写入成功 (*^▽^*) \r\n",section,block);
																				if(OLED)GUI_ShowString(0,16,"Copy SUCC ",16,1);
																			}else{
																				if(EN)printf("SQ:%d , QK:%d     Copy the failure (* ̄︿ ̄) \r\n",section,block);
																				if(CN)printf("SQ:%d , QK:%d     复制失败    (* ̄︿ ̄) \r\n",section,block);
																				if(OLED)GUI_ShowString(0,16,"Copy the failure",16,1);
																			}
																				if(CN)printf("SQ:%d , QK:%d (*^▽^*) \r\n",section,block);
																			}
																		}else{
																		if(EN)printf("card 2 wrong password \r\n");
																		if(CN)printf("卡2密码错误 \r\n");
																		if(OLED)GUI_ShowString(0,16,"5",16,1);	
																	}		
														}	
													}else{
														if(EN)printf("Looking for failure \r\n");
														if(CN)printf("卡片2未找到 \r\n");
														if(OLED)GUI_ShowString(0,16,"4",16,1);
													}
													copy_tf = 0;
												}
											}while(copy_tf);	
			}else{
				if(EN)printf("Looking for failure \r\n");
				if(CN)printf("卡片未找到 \r\n");
				if(OLED)GUI_ShowString(0,16,"4",16,1);
			}
	}

总结

 最后显摆一下我的手工

这篇文章写一半的时候就停了下来,在草稿中存了小半年,最后在年末穿上秋裤的时候想了想还是补全发出来吧

让我写文章的动力是因为C语言可以对这类单片机进行编程,进而读取环境数据,简单的温湿度模块,人体红外感应模块,触摸模块,光敏模块等等

而这与网络爬虫的作用很相似,一个是获取网络信息的自动程序,一个是获取现实世界信息的自动程序,这也是我为什么写爬虫写着写着就学起C的原因

当然爬虫这方面也在找一些有趣有挑战的网站,如果有人能分享有挑战的项目我也会尝试的

 

三.源码

 

闲聊到这里,想要源码的两种途径

1.积分下载 链接我会放上来

https://download.csdn.net/download/qq_41873771/13992549

由于有部分人不尊重我的劳动成果,写了分享条件不遵守,依然私信直接发邮箱,现博客整顿所有资源取消积分下载,如有需要请私信说明缘由小问题我会直接解答,需要源码需要和我聊天,只要私信我的不管任何形式只要出现邮箱直接屏蔽拉黑

2.私信我 陪我聊聊天好么 秋梨膏

 

那么终于能完结这篇文章了,主要是我太懒,没有什么动力能刺激到我创作

预告一下,下次我要做......等一下有人敲门  我去看看......

 

 

 

 

 

 

版权声明:本文为CSDN博主「张德仁」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41873771/article/details/107815461

生成海报
点赞 0

张德仁

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

OV7670摄像头模块资料

OV7670摄像头模块资料 一、实物图和原理图 二、模块简介 OV7670 是 OV( OmniVision)公司生产的 CMOS VGA 图像传感器。该传感器体积小、工作电压低,提供单片 VGA

pwm电机调速的原理介绍与代码实现

1、pwm实现调速的原理与介绍 PWM(Pulse Width Modulation)脉冲宽度调制。 1)占空比 pwm占空比就是一个脉冲周期内有效电平在整个周期所占的比例。 通过调节PWM的占空比就能调节IO口上电压的持续

【STM32Cube笔记】2-STM32Cube安装教程

【STM32Cube笔记】系列文章目录 1-基于STM32的VSCode入门级教程前言 2-STM32Cube安装教程 3-STM32CubeIDE汉化 4-STM32Cube配置时钟设置 5-跑马灯引脚配置 6-Cortex-M7内核基本配