20210320069-苏荣意
本章讲解运用C#及Visual Studio 2022编写代码获取高频RFID卡实现简单的停车场收费系统
1. 介绍
在物联网工程的学习过程中,我深入了解了RFID技术,并掌握了其关键技术。同时,我也学会了使用串口工具,这为我在RFID应用中的数据传输提供了便利。
2. RFID技术
RFID技术(Radio Frequency Identification)是一种通过无线电频率识别和追踪标签的技术。它可以实现对物体的自动识别和数据采集,使得物联网系统更加智能化和高效。
3. 学会使用RFID技术
在学习过程中,我深入了解了RFID技术的原理和应用。我学会了选择合适的RFID标签和读写器,并掌握了其配置和使用方法。通过实践,我成功地实现了RFID标签的读取和写入,为物联网应用中的数据采集和追踪提供了基础支持。
4. 学会使用串口工具
为了更好地实现RFID数据的传输和处理,我学会了使用串口工具。串口工具可以连接RFID读写器和计算机,通过串口通信实现数据的传输和控制。我学会了设置串口的参数,如波特率、数据位、停止位等,并成功地实现了RFID数据的读取和写入实现简单停车场收费系统。
硬件连接
串口线:连接计算机串口与 NEWLab 平台串口。电源适配器:连接电源适配器 DC12V 到 NEWLab 平台。I0 口: H 射频模块和 M3 核心模块采用 SPI 通信方式。SPI 是行外设接SerialPeripheral Interface 简写)。SPI 的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4 根线。HF 射频模块 MISO、MOSI、SCK、NSS、RST分别连接 M3 核心模块的 PA6、PA7、PA5、PA4、PA0
VS Form的窗体界面及代码
串口配置
停车场收费系统
public partial class Form1 : Form
{
public delegate void showReceiveDelegate(string text); //当采用响应模式,应申明一个委托,实现不同线程的控件实验
SerialPort com = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
int com_num = 0;
int timer_num;
/*-------------------------------------------------------------
* status_num状态字
* 1,表示读取信息
--------------------------------------------------------------*/
int status_num=0;//状态字
public Form1()
{
InitializeComponent();
}
//窗体加载
private void Form1_Load(object sender, EventArgs e)
{
//串口初始化
cmbPort.SelectedIndex = 2;
cmbBaudRate.SelectedIndex = 4;
cmbDataBits.SelectedIndex = 0;
cmbStopBits.SelectedIndex = 0;
cmbParity.SelectedIndex = 0;
//定时器初始化
System.Timers.Timer t = new System.Timers.Timer(50);//实例化Timer类,设置间隔时间为1000毫秒 就是1秒;
t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到达时间的时候执行事件;
t.AutoReset = true; //设置是执行一次(false)还是一直执行(true);
t.Enabled = true; //是否执行System.Timers.Timer.Elapsed事件;
timer_num = 0;
}
//串口打开与关闭
private void btnOpen_Click(object sender, EventArgs e)
{
if (btnOpen.Text == "打开串口")
{
try
{
if (!com.IsOpen)
{
com.PortName = cmbPort.Text;
com.BaudRate = int.Parse(cmbBaudRate.Text);
com.DataBits = int.Parse(cmbDataBits.Text);
switch (cmbStopBits.SelectedIndex)
{
case 0:
com.StopBits = StopBits.One; break;
case 1:
com.StopBits = StopBits.Two; break;
case 2:
com.StopBits = StopBits.OnePointFive; break;
case 3:
com.StopBits = StopBits.None; break;
}
switch (cmbParity.SelectedIndex)
{
case 0: com.Parity = Parity.None; break;
case 1: com.Parity = Parity.Odd; break;
case 2: com.Parity = Parity.Even; break;
}
com.Open();//打开串口
}
btnOpen.Text = "关闭串口";
txtStatus.Text = "串口已打开!";
btnInformation.Enabled = true;
btnClear.Enabled = true;
button1.Enabled = true;
//button2.Enabled = true;
// 数据接收模式变化时,设置串口的数据接收侦听事件
try
{
com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived); //加载接收事件
}
catch (Exception err)
{
txtStatus.Text = err.ToString();
}
}
catch
{ txtStatus.Text = "串口打开错误或串口不存在!";
}
}
else //关闭串口
try
{
if (com.IsOpen)
com.Close(); //关闭串口
btnOpen.Text = "打开串口";
txtStatus.Text = "串口已关闭!";
btnInformation.Enabled = false;
btnClear.Enabled = false;
button1.Enabled = false;
//button2.Enabled = false;
}
catch
{
txtStatus.Text = "串口关闭错误或串口不存在!";
}
}
//--------------------------------------------------------------------------------
//定时器相关设置
public void theout(object source, System.Timers.ElapsedEventArgs e)
{
timer_num++;
this.BeginInvoke(new TextOption(function1));//invok 委托实现跨线程的调用
}
delegate void TextOption();//定义一个委托
void function1()
{
if ((timer_num > 10)&&(com_num>5))
{
com_num = 0;
try
{
int count = com.BytesToRead;
byte[] readBuffer = new byte[count];
com.Read(readBuffer, 0, count);
//String strReceive = Encoding.Default.GetString(readBuffer); //字母、数字、汉字转换为字符串
String strReceive = getStringFromBytes(readBuffer); //转十六进制
this.Invoke(new showReceiveDelegate(doShowReceive), strReceive);
}
catch (Exception err)
{
txtStatus.Text = err.ToString();
}
}
}
//--------------------------------------------------------------------------------
// 响应模式时,串口接收数据事件
private void com_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
com_num = com.BytesToRead;
timer_num = 0;
}
// 把字节数组转换为十六进制格式的字符串。
// <param name="pByte">要转换的字节数组。</param>
// <returns>返回十六进制格式的字符串。</returns>
public static string getStringFromBytes(byte[] pByte)
{
string str = ""; //定义字符串类型临时变量。
//遍历字节数组,把每个字节转换成十六进制字符串,不足两位前面添“0”,以空格分隔累加到字符串变量里。
for (int i = 0; i < pByte.Length; i++)
str += (pByte[i].ToString("X").PadLeft(2, '0') + " ");
str = str.TrimEnd(' '); //去掉字符串末尾的空格。
return str; //返回字符串临时变量。
}
//<summary>
//把十六进制格式的字符串转换成字节数组。
//</summary>
//<param name="pString">要转换的十六进制格式的字符串</param>
//<returns>返回字节数组。</returns>
public static byte[] getBytesFromString(string pString)
{
string[] str = pString.Split(' '); //把十六进制格式的字符串按空格转换为字符串数组。
byte[] bytes = new byte[str.Length]; //定义字节数组并初始化,长度为字符串数组的长度。
for (int i = 0; i < str.Length; i++) //遍历字符串数组,把每个字符串转换成字节类型赋值给每个字节变量。
bytes[i] = Convert.ToByte(Convert.ToInt32(str[i], 16));
return bytes; //返回字节数组。
}
//------------------------------------------------------------
//清空接收框内容
private void btnClear_Click(object sender, EventArgs e)
{
txtSend.Text = "";
txtReceive.Text = "";
txtInformation.Text = "";
txtStatus.Text = "数据已经清除!";
}
//异步线程处理接受的字符,显示在接收的文本框中
public void doShowReceive(string str)
{
txtReceive.Text = str;
//高频卡获取卡信息
if (status_num == 20)
{
status_num = 0;
int i;
for (i = 0; i < 10; i++)
{
if (str.Substring(i, 20).Equals("FF 55 00 00 81 03 08"))
{
btn_Entrance.Enabled = true;
txtInformation.Text = str.Substring(i + 21, 11);//截取4个字节
txtStatus.Text = "高频卡信息读取成功!";
break;
}
}
if (i >= 10)
{
txtStatus.Text = "无法获取高频卡信息!";
}
}
//入场
if (status_num == 21)
{
status_num = 0;
if (str.Substring(18, 2).Equals("08"))
{
string str1 = str.Substring(21, 11);
txtInformation.Text = str1;
if (!File.Exists(@"E:\物联网关键技术\20210320069\停车场信息1.txt"))
{
FileStream fs = new FileStream(@"E:\物联网关键技术\20210320069\停车场信息1.txt", FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);
fs.Close();
}
List<string> lines2 = new List<string>(File.ReadAllLines(@"E:\物联网关键技术\20210320069\停车场信息1.txt"));
for (int j = 0; j < lines2.Count; j++)
{
if (str1 == lines2[j])
{
txtStatus.Text = "卡信息已注册!";
textBox13.Text = "";
textBox14.Text = "";
textBox17.Text = "";
textBox18.Text = "";
textBox19.Text = "";
return;
}
}
textBox13.Text = DateTime.Now.ToString();
textBox14.Text = "10000";
string[] lines1 = { textBox13.Text, textBox14.Text, txtInformation.Text };
File.AppendAllLines(@"E:\物联网关键技术\20210320069\停车场信息1.txt", lines1);
txtStatus.Text = "读卡成功,进入停车场,开始记录时间!";
}
}
//出场
if (status_num == 22)
{
status_num = 0;
if (str.Substring(18, 2).Equals("08"))
{
string str1 = str.Substring(21, 11);//截取4个字节
List<string> lines = new List<string>(File.ReadAllLines(@"E:\物联网关键技术\20210320069\停车场信息1.txt"));
for (int i = 0; i < lines.Count; i++)
{
if (str1 == lines[i])
{
var t = Convert.ToDateTime(lines[i - 2]);
textBox18.Text = t.ToString();
var tt = DateTime.Now - t;
textBox17.Text = tt.ToString();
txtStatus.Text = "出场成功!";
int h, m, s, sum;
string a;
h = tt.Hours;
m = tt.Minutes;
s = tt.Seconds;
s = h * 3600 + m * 60 + s * 2;
a = lines[i - 1];
sum = int.Parse(a) - s;
textBox19.Text = s.ToString();
textBox14.Text = sum.ToString();
textBox13.Text = lines[i - 2];
txtInformation.Text = str1;
lines.RemoveAt(i);
lines.RemoveAt(i - 1);
lines.RemoveAt(i - 2);
File.WriteAllLines(@"E:\物联网关键技术\20210320069\停车场信息1.txt", lines.ToArray());
return;
}
}
txtStatus.Text = "出厂失败,卡号是否已入场!";
textBox13.Text = "";
textBox14.Text = "";
textBox17.Text = "";
textBox18.Text = "";
textBox19.Text = "";
}
}
}
//获取高频卡信息
private void btn_HighFrequencyCardInformation_Click(object sender, EventArgs e)
{
txtSend.Text = "";
txtReceive.Text = "";
status_num = 20;
String str1 = "FF 55 00 00 01 03 00 30 75";
byte[] data = getBytesFromString(str1);
com.Write(data, 0, data.Length);
txtSend.Text = str1;
}
//入场
private void btn_Entrance_Click(object sender, EventArgs e)
{
txtSend.Text = "";
txtReceive.Text = "";
status_num = 21;
String str1 = "FF 55 00 00 01 03 00 30 75";
byte[] data = getBytesFromString(str1);
com.Write(data, 0, data.Length);
txtSend.Text = str1;
}
//出场
private void btn_Leave_Click(object sender, EventArgs e)
{
txtSend.Text = "";
txtReceive.Text = "";
status_num = 22;
String str1 = "FF 55 00 00 01 03 00 30 75";
byte[] data = getBytesFromString(str1);
com.Write(data, 0, data.Length);
txtSend.Text = str1;
}
}
列子
入场冲突
出场
出场冲突