STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID(二)

本文继上一篇:STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID

本文介绍在运用RC522模块时,运用链表结构存储数据的操作

Let's go!


前言

(一)顺序表是最常用且最简单的一种数据结构。简而言之,一个线性表是n个数据元素的有限序列,至于每个数据元素的具体含义,在不同的情况下各不相同,它可以是一个数或一个符号,也可以是一页书,甚至其他更复杂的信息。在稍复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表称为文件。


(二)线性结构分类:连续存储【数组】、离散存储【链表】

(三)线性表的链式存储结构的特点是用一组任意的存储单眼存储线性表的元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继的存储位置)。这两部分信息组成数据元素ai的存储映像,称为结点(node)。它包括两个域,其中存储数据元素的信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称为指针或链。n个节点链结成一个链表,即为线性表的链式存储结构。又由于此链表的每一个结点中只包含一个指针域,故又称线性链表或单链表。

(四) 简单的说:n个结点离散分配,彼此用指针相连,每个结点有且只有一个前驱结点有且只有一个后继结点,尾结点没有后继结点。每个结点可以访问下一个结点,无法访问上一个点。

(五)关于链表的相关术语:

首结点:第一个有效结点
尾结点:最后一个有效结点

头结点:第一个结点,首结点前的那个结点。头结点不存放有效数据,它存在的目的是为了方便对链表的操作
头指针:指向头结点的指针链表
尾指针:指向尾指针的指针变量

(6)总而言之,链表比数组存储更灵活,所以用链表


1.较上一篇需改动的地方

 2.代码实现思路           

 3.部分代码

(1)RC522读卡部分

//==============================================================================
//读取卡的类型
//读取卡的ID号
//==============================================================================
void ReaderCard(void)
{
	int temp_value=0;
    
	if(PcdRequest(PICC_REQALL,Temp)==MI_OK)	//选卡
	{
		if(Temp[0]==0x04&&Temp[1]==0x00)  
				printf("\r\n卡类型:MFOne-S50\r\n");
		else if(Temp[0]==0x02&&Temp[1]==0x00)
			printf("MFOne-S70");
		else if(Temp[0]==0x44&&Temp[1]==0x00)
			printf("MF-UltraLight");
		else if(Temp[0]==0x08&&Temp[1]==0x00)
			printf("MF-Pro");
		else if(Temp[0]==0x44&&Temp[1]==0x03)
			printf("MF Desire");
		else
			printf("Unknown");
		if(PcdAnticoll(UID)==MI_OK)			//防冲撞
		{ 
//			printf("Card Id is:");
//			/* 获取卡值  */
//			printf("%d%d%d%d\r\n",UID[0],UID[1],UID[2],UID[3]); 		              
			temp_value = ((UID[0]>>4)*10+(UID[0]&0x0f));//原卡ID太长,取原卡ID的高几位作为新卡ID
            
            
         if(Car_D==1&&Car_R==1)  //正常读取模式                          
         {   
             if(1==Read_Car(pHead,temp_value))  
                    printf("欢迎光临ID:%d\r\n",temp_value);
             else   printf("当前卡ID未录入,通行失败!\r\n");	

         }
         
         if(Car_D==1&&Car_R==0)     //录入模式                       
         {  
             Insert_Car(pHead,temp_value);
                Output_Car(pHead) ;            
         }
         
         if(Car_D==0&&Car_R==1)    //删除模式                         
         { 
             Delete_Car(pHead,temp_value);                      
         }
            

         
		}
  } 
}

(2)链表操作函数.h文件代码

#ifndef __CHAIN_H
#define __CHAIN_H 


struct My_Car   //结构体,目前只存放卡ID,更多数据类型可自行添加
{	
	int Car_ID;//卡ID	
//    char Name[10];
};


typedef struct Node//结点
{
	struct My_Car st;//数据域
	struct Node *pNext;//指针域
}NODE, *PNODE;
/*
NODE等价于struct My_Car st
PNODE等价于struct Node *pNext
*/


PNODE First_Car(void);                       //创建头结点
void  Output_Car(PNODE pHead);               //打印全部已录入的卡ID
void  Insert_Car(PNODE pHead,int temp_value);//录入一个卡ID(传入参数temp_value为读出的卡ID)
int   Read_Car(PNODE pHead,int temp_value); //读取链表是否存在此卡ID(传入参数temp_value为读出的卡ID)
int   Search_Car(PNODE pHead,int temp_value );//定位某个卡ID在链表的位置(传入参数temp_value为读出的卡ID)
void  Delete_Car(PNODE pHead,int temp_value);//删除掉此卡ID(传入参数temp_value为读出的卡ID)

#endif

(3)链表操作函数.c文件代码

#include "Chain.h"
#include "stdlib.h"
#include "stdio.h"


//这个函数用来创建头结点,头结点不存放有效数据,仅供后续使用链表方便
PNODE First_Car(void)
{
	NODE stu;//定义一个结构体
    
	//定义一个头结点并且为头结点分配内存
	PNODE pHead = (PNODE)malloc(sizeof(NODE));
    
	//判断内存是否为空
	if(NULL == pHead) return 0;
    
	//定义一个指向头结点的指针
	PNODE pTail = pHead;
	pTail->pNext = NULL;//清空指针域
 		    
        stu.st.Car_ID=0;        
        //为新节点分配内存
		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		//判断内存是否为空
		if(NULL == pNew)   return 0;
                   
		//初始化结点的数据域
		pNew->st = stu.st;		
		//将新结点挂到老结点后
		pTail->pNext = pNew;		
		//清空新结点的指针域
		pNew->pNext = NULL;		
		//将pTail移到新结点上
		pTail = pNew;	
 
        return pHead;
}

//录入卡ID
void Insert_Car(PNODE pHead,int temp_value)
{
    if( 1==Read_Car(pHead,temp_value) )
            printf("卡ID已存在,请勿重复录入!\r\n");	
    else
        {            
            PNODE p = pHead;    //定义一个指向头结点的指针
            NODE stu;   //定义一个结构体
 	
            p = p->pNext;
			
            PNODE pNew = (PNODE)malloc(sizeof(NODE));

            if(NULL == pNew)  
                printf("动态内存分配失败,程序终止!\r\n");		  
            else
                {   stu.st.Car_ID=temp_value;                      
                    pNew->st = stu.st; 
                    pNew->pNext = p->pNext;
                    p->pNext = pNew;
                }
                printf("卡ID:%d 录入成功!\r\n",temp_value);	
        }     
}

//读取卡号存储数据
int Read_Car(PNODE pHead,int temp_value )
{	
	PNODE p = pHead->pNext;  //定义一个指向头结点后一个结点的指针
    
	while(NULL != p)
	{     
		if(p->st.Car_ID==temp_value) 
        { 
          break; 
        }            
		p = p->pNext;
	}
    
    if(NULL == p)	   return 0;	
    else               return 1;
    
}
//定位卡ID在链表的位置
int Search_Car(PNODE pHead,int temp_value )
{	
	PNODE p = pHead->pNext;//定义一个指向头结点后一个结点的指针
    int i=0;
	while(NULL != p)
	{
        i++;
		if(p->st.Car_ID==temp_value)   break;                   
		p = p->pNext;
	}
    return i;   
}

//删除卡ID
void Delete_Car(PNODE pHead,int temp_value)
{
    if( 0==Read_Car(pHead,temp_value) )
            printf("卡ID不存在,删除失败!\r\n");	
  else  
    { 
        PNODE p = pHead;//定义一个指向头结点的指针
        int i = 0;
        int pos;
	
        pos=Search_Car(pHead,temp_value );//获取要删除的卡ID在链表位置
 
        while(NULL != p->pNext && i<pos-1)  //使指针p指向要删除结点的前一个结点
        {
            p = p->pNext;
            i++;
        }
 
        if(NULL == p->pNext || i>pos-1)
        {
            printf("没找到需要删除的卡ID编号!\r\n");	
        }
 
        PNODE q = p->pNext;
        p->pNext = q->pNext;
        free(q);
        q = NULL;
 
        printf("你已经成功删除卡ID:%d !\r\n",temp_value);
   }
}

//打印输出全部卡号
void Output_Car(PNODE pHead)
{
	
	PNODE p = pHead->pNext->pNext;//p指向头结点的后一个结点
 
	printf("当前录入卡号有:");
	
	while(NULL != p)
	{
		printf("%d、", p->st.Car_ID);
		p = p->pNext;
	}
    
    printf("\r\n");
}

4.实现效果

                         

本例程源码下载:点击跳转 

  • 13
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
您可以使用STM32CubeMX来配置STM32F103C8T6的OLED驱动代码。首先,您需要在STM32CubeMX中创建一个新的工程,并选择STM32F103C8T6作为目标芯片。然后,您可以打开I2C接口并生成代码。接下来,您需要对生成的代码进行一处修改,将i2c.c文件中的"GPIO_InitStruct.Pull = GPIO_NOPULL;"替换为"GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;"。这样就可以成功配置STM32F103C8T6的OLED驱动代码了。\[2\]如果您需要更详细的教程,您可以参考正点原子和小蜜蜂笔记在哔哩哔哩上的相关视频教程。\[3\] #### 引用[.reference_title] - *1* *2* [基于STM32CubeMX的stm32f103c6t6液晶0.96OLED显示字母数字汉字图片显示](https://blog.csdn.net/veteran412/article/details/127540347)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [基于HAL库STM32F103C8T6+0.96寸四线OLED+IIC总线协议+STM32CubeMX(附百度网盘下载链接)](https://blog.csdn.net/weixin_45498562/article/details/124591964)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式创客工坊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值