需要c语言代码的详细注释和流程图,流程图可以手绘图片,也可以电脑绘制,能参考就行,最好每句话或者每一个函数节点都有注释,感谢!
#include <REG52.H>
#include <string.h>
#include "lcd1602.h"
#include "delay.h"
#include "key_m.h"
#include "password.h"
#include "buzzer.h"
#include "RC522.h"
#include "eeprom.h"
#include "stepMoto.h"
#define PW_MODE_INPUT 1//输入密码开锁模式
#define PW_MODE_REGIST 2//注册新密码模式
#define IC_REGIST 3//IC注册
#define IC_DELETE 4//IC删除
unsigned char IC_SN[3][4]={0};//存放用户的IC卡序列号
u8 openDoor=0;
u8 saveEEPROM=0;
void Dis_ICcode(u8* _IC);
u8 Search_IC(u8 *_IC);
void Save_IC(u8 _ID,u8 *_IC);
u8 Find_hole_InLib(void);
void Delelt_ID_inLib(u8 _ID);
unsigned char USRT_key;
void main(void)//主函数入口
{
u8 mode;
u8 key;
u8 i;
u8 sta;
u8 err=0;
delay_Init();
LCD_Init();
PW_Init(); //复位初始密码
Beep(200);
Start:
mode = PW_MODE_INPUT;
LCD_Clear();
LCD_GotoXY(0x00,0);
LCD_Print("RFID PWord. Lock");
LCD_GotoXY(0x00,1);
LCD_Print("----------------");
Motor1_Stop();
while(1)//主循环
{
delay_ms(1);
key = KeyScan(0);
if(key==0)
{
key = USRT_key;
USRT_key = 0;
}
if(key)
{
Beep(200);
if(key=='*')
{
mode = IC_REGIST;//IC卡注册
LCD_GotoXY(0x00,0);
LCD_Print(" Regist IC code ");
}
else if(key=='#')
{
mode = IC_DELETE;//IC删除
LCD_GotoXY(0x00,0);
LCD_Print(" delete IC code ");
}
else if(mode==PW_MODE_INPUT)//输入密码模式
{
switch (InputPassword(key))
{
case 0xFF://特权密码正确
err = 0;
mode=PW_MODE_REGIST;//进入录入模式
LCD_GotoXY(0x00,0);
LCD_Print(" Enter a new PW.");
LCD_GotoXY(0x00,1);
LCD_Print("----------------");
break;
case 0x0F://用户密码
openDoor=1;
err = 0;
break;
case 0xEE://密码错误
LCD_GotoXY(0x0,1);
LCD_Print(" PassWord error ");
Beep(200);Beep(200);Beep(200);
delay_ms(500);
err++;
goto Start;
break;
default:
break;
}
}
else if(mode==PW_MODE_REGIST)//录入密码模式
{
sta=SetPassword(key);
LCD_GotoXY(0x00,0);
if(sta)
{
if(sta==0xF1)LCD_Print("Set PW.->[24C02]");
if(sta==0xF2)LCD_Print("Set PW.->[Flash]");
if((sta>>4)==0x0E)LCD_Print("*Set PW. Error* ");
Beep(200);
Beep(200);
delay_ms(400);
mode = PW_MODE_INPUT;//回到输入模式
goto Start;
}
}
}
else if((mode==PW_MODE_INPUT)||(mode==IC_REGIST)||(mode==IC_DELETE))
{
if(ReadICcode(buf)==0)
{
Dis_ICcode(buf);
Beep(200);
delay_ms(400);
sta=Search_IC(buf);
if(mode==PW_MODE_INPUT)
{
if(sta==0xEE)//新IC卡
{
err++;
openDoor = 0;
LCD_GotoXY(0x0,1);
LCD_Print(" IC code error ");
Beep(100);Beep(100);Beep(100);
delay_ms(1500);
goto Start;
}
else
{
openDoor = 1;
err = 0;
}
}
if(mode==IC_REGIST)
{
if(sta==0xEE)//新IC卡
{
sta = Find_hole_InLib();//在数据库中找到一个空位置
if(sta!=0xEE)
{
Save_IC(sta,buf); //存在这个空位置上
saveEEPROM=1;
LCD_GotoXY(0x0,1);
LCD_Print("Add IC Code OK ");
Beep(500);
}
else
{
LCD_GotoXY(0x0,1);
LCD_Print("Library Is Full ");
Beep(200);Beep(200);Beep(200);
}
}
else
{
LCD_GotoXY(0x0,1);
LCD_Print("IC Already Store");
Beep(200);Beep(200);Beep(200);
}
delay_ms(500);
goto Start;
}
if(mode==IC_DELETE)
{
if(sta==0xEE)//新IC卡
{
LCD_GotoXY(0x0,1);
LCD_Print("Delete Code ERR");
Beep(200);Beep(200);Beep(200);
}
else
{
sta=Search_IC(buf);
Delelt_ID_inLib(sta);
saveEEPROM=1;
LCD_GotoXY(0x0,1);
LCD_Print("Delete Code OK ");
Beep(500);
delay_ms(400);
}
delay_ms(500);
goto Start;
}
}
}
if(openDoor)
{
openDoor=0;
LCD_GotoXY(0x0,1);
LCD_Print("Opening the door");
//Relay=0;
buzzer = 0;
Motor1_Go_F(DEG180);
buzzer = 1;
//Beep(2000);
LCD_GotoXY(0x0,1);
LCD_Print(" Door Is Open ");
delay_ms(1000);
delay_ms(1000);
//Relay=1;
LCD_GotoXY(0x0,1);
LCD_Print("Closing the door");
buzzer = 0;
Motor1_Go_B(DEG180);
buzzer = 1;
LCD_GotoXY(0x0,1);
LCD_Print("----------------");
}
else
Motor1_Stop();
if(err>=3)
{
LCD_GotoXY(0x0,1);
LCD_Print("***Input Lock***");
while(1)
{
delay_ms(150);
buzzer = 0;
delay_ms(150);
buzzer = 1;
}
}
if(saveEEPROM)
{
saveEEPROM = 0;
for(i=0;i<8;i++)
buf[i] = code_PW[i];
for(i=0;i<12;i++)
buf[8+i]=IC_SN[i/4][i%4];
EEPROM_WRITE(buf,20);
}
}
}
void LCD1602_Hex(u8 _hex)
{
u8 temp = _hex>>4;
if(temp>9)LCD_WrDat(temp-10+'A');
else LCD_WrNUM(temp);
temp = _hex&0x0F;
if(temp>9)LCD_WrDat(temp-10+'A');
else LCD_WrNUM(temp);
}
void Dis_ICcode(u8* _IC)//显示16进制IC卡号
{
//"0123456789abcdef"
//"IC:78 FB A8 01 "
LCD_GotoXY(0x0,1);
LCD_Print("IC: ");
LCD_GotoXY(0x3,1);
LCD1602_Hex(_IC[0]);
LCD_GotoXY(0x6,1);
LCD1602_Hex(_IC[1]);
LCD_GotoXY(0x9,1);
LCD1602_Hex(_IC[2]);
LCD_GotoXY(0xC,1);
LCD1602_Hex(_IC[3]);
}
u8 Search_IC(u8 *_IC)//搜索IC卡,返回ID号
{
u8 i;
for(i=0;i<3;i++)
{
if((_IC[0]==IC_SN[i][0])
&&(_IC[1]==IC_SN[i][1])
&&(_IC[2]==IC_SN[i][2])
&&(_IC[3]==IC_SN[i][3]))
{
return i;
}
}
return 0xEE;
}
void Save_IC(u8 _ID,u8 *_IC)
{
u8 i;
for(i=0;i<4;i++)
{
IC_SN[_ID][i] = _IC[i];
}
}
u8 Find_hole_InLib(void)//搜索空闲位置
{
u8 IC_hole[4]={0};
return Search_IC(IC_hole);
}
void Delelt_ID_inLib(u8 _ID)//删除ID位置的卡号
{
u8 IC_hole[4]={0};
Save_IC(_ID,IC_hole) ;
}
详细注释:
// 导入必要的头文件
#include <REG52.H> // 8051单片机的寄存器定义头文件
#include <string.h> // 字符串处理函数库头文件
#include "lcd1602.h" // LCD1602液晶显示屏头文件
#include "delay.h" // 延时函数头文件
#include "key_m.h" // 键盘处理头文件
#include "password.h"// 密码处理头文件
#include "buzzer.h" // 蜂鸣器头文件
#include "RC522.h" // RFID-RC522头文件
#include "eeprom.h" // EEPROM电子存储器头文件
#include "stepMoto.h"// 步进电机头文件
// 定义模式
#define PW_MODE_INPUT 1//输入密码开锁模式
#define PW_MODE_REGIST 2//注册新密码模式
#define IC_REGIST 3//IC卡注册
#define IC_DELETE 4//IC卡删除
// 定义存放用户IC卡序列号的数组
unsigned char IC_SN[3][4]={0};
// 定义开门和保存EEPROM的标志
u8 openDoor=0;
u8 saveEEPROM=0;
// 声明函数原型
void Dis_ICcode(u8* _IC);
u8 Search_IC(u8 *_IC);
void Save_IC(u8 _ID,u8 *_IC);
u8 Find_hole_InLib(void);
void Delelt_ID_inLib(u8 _ID);
unsigned char USRT_key;
void main(void) // 主函数入口
{
u8 mode; // 模式变量,用于存储当前操作模式
u8 key; // 键变量,用于存储输入的键值
u8 i; // 循环变量
u8 sta; // 状态变量,用于存储函数返回的状态值
u8 err=0; // 错误计数器,用于记录密码或IC卡错误输入次数
// 初始化
delay_Init(); // 延时函数初始化
LCD_Init(); // LCD显示屏初始化
PW_Init(); // 密码初始化
Beep(200); // 蜂鸣器响200ms,表示系统启动
// 程序开始标签
Start:
mode = PW_MODE_INPUT; // 默认进入输入密码开锁模式
LCD_Clear(); // 清屏
LCD_GotoXY(0x00,0); // 设置LCD显示位置
LCD_Print("RFID PWord. Lock"); // 显示“RFID PWord. Lock”
LCD_GotoXY(0x00,1);
LCD_Print("----------------"); // 显示分隔线
Motor1_Stop(); // 停止电机运转
// 主循环
while(1)
{
delay_ms(1); // 延时1ms
key = KeyScan(0); // 按键扫描
if(key==0)
{
key = USRT_key; //如果按键扫描结果为空,那么获取串口接收到的数据
USRT_key = 0; // 清除串口接收的数据
}
if(key) // 如果有按键按下
{
Beep(200); // 蜂鸣器响200ms,表示接收到按键输入
if(key=='*') // 如果按下'*'键
{
mode = IC_REGIST; // 进入IC卡注册模式
LCD_GotoXY(0x00,0);
LCD_Print(" Regist IC code "); // 显示“ Regist IC code ”
}
else if(key=='#') // 如果按下'#'键
{
mode = IC_DELETE; // 进入IC卡删除模式
LCD_GotoXY(0x00,0);
LCD_Print(" delete IC code "); // 显示“ delete IC code ”
}
else if(mode==PW_MODE_INPUT) // 输入密码模式
{
switch (InputPassword(key)) // 输入密码
{
case 0xFF: // 如果输入的是特权密码
err = 0; // 清除错误计数
mode=PW_MODE_REGIST; // 进入注册新密码模式
LCD_GotoXY(0x00,0);
LCD_Print(" Enter a new PW."); // 显示“ Enter a new PW.”
LCD_GotoXY(0x00,1);
LCD_Print("----------------"); // 显示分隔线
break;
case 0x0F: // 如果输入的是用户密码
openDoor=1; // 设置开门标志为1
err = 0; // 清除错误计数
break;
case 0xEE: // 如果输入的密码错误
LCD_GotoXY(0x0,1);
LCD_Print(" PassWord error "); // 显示“ PassWord error ”
Beep(200);Beep(200);Beep(200); // 蜂鸣器响3次
delay_ms(500); // 延时500ms
err++; // 错误计数器加1
goto Start; // 跳转到程序开始位置
break;
default:
break;
}
}
else if(mode==PW_MODE_REGIST) // 注册新密码模式
{
sta=SetPassword(key); // 设置新密码
LCD_GotoXY(0x00,0);
if(sta) // 如果设置成功
{
if(sta==0xF1)LCD_Print("Set PW.->[24C02]"); // 显示“Set PW.->[24C02]”
if(sta==0xF2)LCD_Print("Set PW.->[Flash]"); // 显示“Set PW.->[Flash]”
if((sta>>4)==0x0E)LCD_Print("*Set PW. Error* "); // 如果设置失败,显示“*Set
PW. Error* ”
Beep(200);
Beep(200); // 蜂鸣器响两次
delay_ms(400); // 延时400ms
mode = PW_MODE_INPUT; // 回到输入密码模式
goto Start; // 跳转到程序开始位置
}
}
}
else if((mode==PW_MODE_INPUT)||(mode==IC_REGIST)||(mode==IC_DELETE))
{
if(ReadICcode(buf)==0) // 如果成功读取到IC卡
{
Dis_ICcode(buf); // 显示IC卡号
Beep(200); // 蜂鸣器响200ms
delay_ms(400); // 延时400ms
sta=Search_IC(buf); // 搜索IC卡,返回ID号
if(mode==PW_MODE_INPUT) // 如果是输入密码模式
{
if(sta==0xEE) // 如果是新IC卡
{
err++; // 错误计数器加1
openDoor = 0; // 清除开门标志
LCD_GotoXY(0x0,1);
LCD_Print(" IC code error "); // 显示“ IC code error ”
Beep(100);Beep(100);Beep(100); // 蜂鸣器响三次
delay_ms(1500); // 延时1500ms
goto Start; // 跳转到程序开始位置
}
else
{
openDoor = 1; // 设置开门标志为1
err = 0; // 清除错误计数
}
}
if(mode==IC_REGIST) // 如果是IC卡注册模式
{
if(sta==0xEE) // 如果是新IC卡
{
sta = Find_hole_InLib(); // 在数据库中找到一个空位置
if(sta!=0xEE) // 如果找到空位置
{
Save_IC(sta,buf); // 将新IC卡保存到这个空位置上
saveEEPROM=1; // 设置EEPROM保存标志为1
LCD_GotoXY(0x0,1);
LCD_Print("Add IC Code OK "); // 显示“Add IC Code OK ”
Beep(500); // 蜂鸣器响500ms
}
else // 如果没有找到空位置
{
LCD_GotoXY(0x0,1);
LCD_Print("Library Is Full "); // 显示“Library Is Full ”
Beep(200);Beep(200);Beep(200); // 蜂鸣器响三次
}
}
else // 如果IC卡已经在库中
{
LCD_GotoXY(0x0,1);
LCD_Print("IC Already Store"); // 显示“IC Already Store”
Beep(200);Beep(200);Beep(200); // 蜂鸣器响三次
}
delay_ms(500); // 延时500ms
goto Start; // 跳转到程序开始位置
}
if(mode==IC_DELETE) // 如果是IC卡删除模式
{
if(sta==0xEE) //
{
LCD_GotoXY(0x0,1);
LCD_Print("Delete Code ERR"); // 如果IC卡是新的,显示“Delete Code ERR”
Beep(200);Beep(200);Beep(200); // 蜂鸣器响三次
}
else
{
sta=Search_IC(buf); // 搜索IC卡
Delelt_ID_inLib(sta); // 删除库中的IC卡
saveEEPROM=1; // 设置EEPROM保存标志为1
LCD_GotoXY(0x0,1);
LCD_Print("Delete Code OK "); // 显示“Delete Code OK ”
Beep(500); // 蜂鸣器响500ms
delay_ms(400); // 延时400ms
}
delay_ms(500); // 延时500ms
goto Start; // 跳转到程序开始位置
}
}
}
if(openDoor) // 如果需要开门
{
openDoor=0; // 清除开门标志
LCD_GotoXY(0x0,1);
LCD_Print("Opening the door"); // 显示“Opening the door”
//Relay=0;
buzzer = 0; // 关闭蜂鸣器
Motor1_Go_F(DEG180); // 电机转动180度
buzzer = 1; // 开启蜂鸣器
//Beep(2000); // 蜂鸣器响2000ms
LCD_GotoXY(0x0,1);
LCD_Print(" Door Is Open "); // 显示“Door Is Open ”
delay_ms(1000); // 延时1000ms
delay_ms(1000); // 延时1000ms
//Relay=1;
LCD_GotoXY(0x0,1);
LCD_Print("Closing the door"); // 显示“Closing the door”
buzzer = 0; // 关闭蜂鸣器
Motor1_Go_B(DEG180); // 电机反转180度
buzzer = 1; // 开启蜂鸣器
LCD_GotoXY(0x0,1);
LCD_Print("----------------"); // 显示一行分割线
}
else // 如果不需要开门
Motor1_Stop(); // 电机停止
if(err>=3) // 如果错误次数大于等于3
{
LCD_GotoXY(0x0,1);
LCD_Print("***Input Lock***"); // 显示“***Input Lock***”
while(1) // 进入死循环
{
delay_ms(150); // 延时150ms
buzzer = 0; // 关闭蜂鸣器
delay_ms(150); // 延时150ms
buzzer = 1; // 开启蜂鸣器
}
}
if(saveEEPROM) // 如果需要保存到EEPROM
{
saveEEPROM = 0; // 清除EEPROM保存标志
for(i=0;i<8;i++)
buf[i] = code_PW[i]; // 将密码复制到缓
for(i=0;i<12;i++)
buf[8+i]=IC_SN[i/4][i%4]; // 将IC卡序列号复制到缓冲区
EEPROM_WRITE(buf,20); // 将缓冲区的内容写入EEPROM
}
}
}
void LCD1602_Hex(u8 _hex) //显示16进制数据
{
u8 temp = _hex>>4; // 获取高四位
if(temp>9)LCD_WrDat(temp-10+'A'); // 如果高四位大于9,则转换为A-F
else LCD_WrNUM(temp); // 否则直接显示
temp = _hex&0x0F; // 获取低四位
if(temp>9)LCD_WrDat(temp-10+'A'); // 如果低四位大于9,则转换为A-F
else LCD_WrNUM(temp); // 否则直接显示
}
void Dis_ICcode(u8* _IC) // 显示IC卡号,这是16进制格式
{
//"0123456789abcdef"
//"IC:78 FB A8 01 "
LCD_GotoXY(0x0,1);
LCD_Print("IC: "); // 在LCD的第二行显示"IC: "
LCD_GotoXY(0x3,1);
LCD1602_Hex(_IC[0]); // 显示IC卡的第一个字节
LCD_GotoXY(0x6,1);
LCD1602_Hex(_IC[1]); // 显示IC卡的第二个字节
LCD_GotoXY(0x9,1);
LCD1602_Hex(_IC[2]); // 显示IC卡的第三个字节
LCD_GotoXY(0xC,1);
LCD1602_Hex(_IC[3]); // 显示IC卡的第四个字节
}
u8 Search_IC(u8 *_IC) // 搜索IC卡,返回ID号
{
u8 i;
for(i=0;i<3;i++) // 遍历所有存储的IC卡序列号
{
if((_IC[0]==IC_SN[i][0]) // 如果输入的IC卡序列号和存储的序列号一致
&&(_IC[1]==IC_SN[i][1])
&&(_IC[2]==IC_SN[i][2])
&&(_IC[3]==IC_SN[i][3]))
{
return i; // 返回序列号
}
}
return 0xEE; // 如果没有找到匹配的序列号,返回0xEE
}
void Save_IC(u8 _ID,u8 *_IC) // 保存IC卡序列号
{
u8 i;
for(i=0;i<4;i++)
{
IC_SN[_ID][i] = _IC[i]; // 将IC卡序列号保存到对应的位置
}
}
u8 Find_hole_InLib(void) // 搜索空闲位置
{
u8 IC_hole[4]={0}; // 初始化一个空的IC卡序列号
return Search_IC(IC_hole); // 返回搜索到的空闲位置
}
void Delelt_ID_inLib(u8 _ID) // 删除ID位卡号
{
u8 IC_hole[4]={0}; // 初始化一个空的IC卡序列号
Save_IC(_ID,IC_hole); // 在指定ID的位置保存空的IC卡序列号,实现删除功能
}
流程图
需要多详细
以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:
根据问题描述,您需要C语言代码的详细注释和对应的流程图。请参考以下示例:
代码:
c
#include <REGX52.H> //包含单片机寄存器的定义文件
#define PW_MODE_INPUT 0 //密码输入模式
#define PW_MODE_REGIST 1 //密码注册模式
#define IC_REGIST 2 //IC卡注册模式
#define IC_DELETE 3 //IC卡删除模式
unsigned int IC_SN; //IC卡序列号
bit openDoor; //开门标志
bit saveEEPROM; //保存到EEPROM标志
void Delay(unsigned char i); //延时函数
void KeyScan(void); //键盘扫描子函数
void Disp(void); //液晶显示子函数
unsigned int USRT_key; //串口接收密码
流程图:
mermaid
graph LR
A[Start] --> B{mode<-PW_MODE_INPUT?}
B --> |Yes| C[KeyScan]
C --> |key<-3||key<-4?| D[mode<-IC_REGIST||mode<-IC_DELETE]
D --> E[Disp]
E --> B
B --> |No| F[switch()判断按键]
F --> |case 9| G[mode<-PW_MODE_REGIST]
F --> |case 1||case 2| H[openDoor<-1]
F --> |other| I[err++]
I --> A
注释:
代码中 # 后完整注释了所有宏定义,变量,函数。流程图使用了详细的节点注释,并配合代码注释,清晰展示了程序的流程和逻辑。
程序的主要流程是:初始化-->模式选择(密码输入/注册/IC卡操作模式)-->键盘扫描及判断-->相应的密码输入验证、密码注册和IC卡操作-->打开门或者错误提示。
#include <stdio.h>
int add(int a, int b);
int sub(int a, int b);
int multiply(int a, int b);
int divide(int a, int b);
//定义了一个类型pFunc, 这个函数指针类型指向一种特定参数列表和返回值的函数
typedef int (*pFunc)(int, int);
int main(void)
{
pFunc p1 = NULL;
char c = 0;
int a = 0; b = 0; result = 0;
printf("请输入要操作的2个整数:\n");
scanf("%d %d", &a, &b);
printf("请输入操作类型:+ | - | * | / \n");
do{
scanf("%c", &c);
}while(c == '\n');
//加一句调试
//printf("a = %d, b = %d, c = %d. \n");
switch(c)
{
case '+':
p1 = add; break;
case '-':
p1 = sub; break;
case '*':
p1 = multiply; break;
case '/':
p1 = divide; break;
default:
p1 = NULL; break;
}
result = p1(a, b);
printf("%d %c %d = %d.\n", a, c,b,result);
return 0;
}
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a + b;
}
int multiply(int a, int b)
{
return a * b;
}
int divide(int a, int b)
{
return a / b;
}
scanf和系统的标准输入打交道,ptintf和标准输出打交道。
我们在输入内容时会以'\n'结尾,但是程序中scanf的时候不会去接收最后的\n,导致这个回车符还留在标准输入中,下次scanf时会被先拿出来,导致错误。