first commit

This commit is contained in:
2024-09-05 13:29:00 +08:00
commit 53515a5a50
75 changed files with 3863 additions and 0 deletions

View File

@@ -0,0 +1,410 @@
![cover](cover.png)
---
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 主要负责完成实验一二三的操作,对实验器材与软件进行测试,在测试中发现问题并与队员协作解决,在实验中也发现部分模块有损坏无法正常使用。 |
| 李桦炅 | 21281282 | 主要负责队员之间的沟通协作,协助完成实验并对实验过程中发现的问题进行记录,再进行沟通完善报告的描述。 |
| 王子励 | 21281292 | 负责实验报告的撰写,查阅背景知识资料工作。 |
| 李志民 | 20281146 | 中途加入小组,完成了实验一的环境配置后,协助了实验中遇到问题的解决。 |
# **实验一** 环境搭建
## 1.1. 实验目的
安装必要的开发工具、烧写工具构建EnOcean模块开发环境以便进行模块开发及实验。
## 1.2. 工具/原料
- 计算机Windows操作系统
- IAR FOR ARM 7.20安装包
- TI-TM4C-SDK工具包
- DolphinView安装包
- J-link安装包
## 1.3. 实验步骤
实验一的实验步骤在实验指导书上非常详细,只需要按照配图和文字执行即可。因此我们在本实验报告中仅简单概括一下实验的步骤,并说明我们对每个步骤在本物联网项目中在架构与技术上的理解。
1. 安装IAR FOR ARM 7.20
IAR软件作为项目的IDE软件主要用于编写程序代码、搭建软件工程、调用JTAG工具烧写硬件以及进行DEBUG等。
2. 破解IAR软件
~~IAR软件是商业收费软件。~~
3. 安装SDK工具包
SDK工具包是使用软件驱动硬件的依赖文件是厂商设计的与硬件通信的接口由硬件制造厂商提供。
4. 重建SDK驱动程序库
为了使IAR能在新的安装路径中找到SDK驱动程序需要重建SDK驱动程序库。
在这个步骤我们遇到了困难。排查原因发现是由于项目文件路径含有中文字符导致。由于编译机器使用MinGW作为C语言编译器MinGW不支持中文路径。
5. 安装J-link驱动
J-link是PC机与物联网模块进行烧写和DEBUG等的工具。作为外接的额外硬件需要在PC机上安装J-link的驱动以实现让PC机调用J-link的接口进行控制。
6. 安装DolphinView软件
DolphinView软件能够与后面烧写的Sniffer进行联动显示EnOcean_Sniffer程序采集的数据包。
## 1.4. 实验结果
我们最后成功将实验环境配置完成。
## 1.5. 实验感想
通过此次实验我们对物联网系统开发流程有了更直观的了解。在配置开发环境过程中我们安装了IAR、JLink等开发和调试所需的软硬件工具并解决了编译链接和烧录时遇到的问题。这使我们对物联网设备固件的编译、烧录等开发过程有了直接的体会。
# 实验二 EnOcean Sniffer 实验
## 2.1. 实验目的
将一个易能森设备配置为嗅探器Sniffer抓取易能森通信数据包以便分析数据。
## 2.2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
## 2.3. 预备知识
1. Sniffer嗅探器是一种基于被动侦听原理的网络分析方式。使用这种技术方式可以监视网络的状态、数据流动情况以及网络上传输的信息。
2. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
3. 利用DolphinView 可以实现Sniffer的检测。
## **2.4**. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
void EnOceanUARTIntHandler(void) {
uint32_t ui32Ints; // 用于存储UART中断标志的变量
uint8_t data; // 用于存储接收到的数据字节
static uint8_t PacketHeader = 0; // 表示数据包头部的标志
static uint32_t PacketLen = 0; // 用于存储预期数据包长度的变量
//
// Get and clear the current interrupt source(s)
//
// 获取并清除当前的中断源
ui32Ints = ROM_UARTIntStatus(ENOCEAN_UART_BASE, true);
ROM_UARTIntClear(ENOCEAN_UART_BASE, ui32Ints); // 清除已处理的中断
//
// Handle receive interrupts.
//
// 处理接收中断。
if (ui32Ints & (UART_INT_RX | UART_INT_RT)) { // 检查RX FIFO非空或者超时中断是否发生
data = ROM_UARTCharGetNonBlocking(ENOCEAN_UART_BASE); // 从UART中读取一个字符
// 检查接收缓冲区是否有空间,并且数据包接收不在进行中
if (EnOceanRxCount < ENOCEAN_RX_BUFFER_SIZE && (!EnOceanTelegramRxflags)) {
EnOceanRxBuffer[EnOceanRxCount++] = data; // 将接收到的数据存储到缓冲区中
// 检查数据包头部是否已经被检测到
if (!PacketHeader) {
// 检查数据包的第一个字节是否是头部0x55
if (EnOceanRxBuffer[0] != 0x55) EnOceanRxCount = 0; // 如果头部不符合预期,重置缓冲区
else {
// 检查是否已经接收到6个字节头部 + 数据长度 + 校验和)
if (EnOceanRxCount == 6) {
// 使用接收到的数据计算预期的数据包长度
if (GetCheckSum(&EnOceanRxBuffer[1], 4) == EnOceanRxBuffer[5]) {
PacketLen = 7 + (EnOceanRxBuffer[1] << 8) + EnOceanRxBuffer[2] + EnOceanRxBuffer[3];
PacketHeader = 1; // 设置数据包头部标志
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 将引脚写为0
} else {
EnOceanRxCount = 0; // 如果校验和验证失败,重置缓冲区
}
}
}
} else if (EnOceanRxCount == PacketLen) {
EnOceanTelegramRxflags = 1; // 设置表示完整数据包接收的标志
PacketHeader = 0; // 重置数据包头部标志
PacketLen = 0; // 重置预期数据包长度
}
} else {
// 如果缓冲区已满或者接收到无效的数据包,重置接收缓冲区和数据包头部信息
EnOceanRxCount = 0;
PacketHeader = 0;
PacketLen = 0;
}
}
}
```
## 2.5. 实验步骤
### 2.5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 2.5.2. 步骤二 加载工程文件
加载EnOcean_Sniffer工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.1EnOcean_Sniffer\IAR_Files”目录下的“EnOcean_Sniffer.eww”工程文件点击“打开”。
### 2.5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
在这里我们遇到了问题。在完成上述设置后,我们还是遇到了烧录错误,报错截图如下:
<img src="picture1.png" alt="picture1" style="zoom: 67%;" />
上网查阅资料后我们对比发现设置中的Interface默认为SWD但是我们实验使用的工具为JATG所以需要选择JATG。更改如下
<img src="picture2.png" alt="picture2" style="zoom:67%;" />
更改该选项之后,成功烧录程序。
**加载一位翘板开关工程Rocker_Switch工程**
点击工具栏的红叉退出调试拔掉下载EnOcean_Sniffe程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载1.4Rocker_Switch工程。
### 2.5.4. 步骤四 安装USB Serial Port
将下载EnOcean Sniffer程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电和传输数据。
在这里我们再次遇到了问题。
用一根micro USB线将OURS_EnOcean模块和PC机相连后PC机并没有如实验指导书所述弹出驱动安装提示窗口。且在设备管理器中可以看到PC机没有正确识别OURS_EnOcean设备如下图所示
<img src="picture3.png" alt="picture3" style="zoom:67%;" />
我们在网上查找新版本的设备驱动程序。将驱动程序版本从“TivaWare_C_Series-2.1.4.178”升级到了“TivaWare_C_Series-2.2.0.295”。在设备管理器右键设备->点击“属性”->点击“驱动程序”->点击“更新驱动程序”->点击“浏览我的电脑以查找驱动程序”->点击“浏览”->选择新驱动的安装目录->点击“确定”即可让PC机更新驱动。现在PC机能正确识别OURS_EnOcean设备了
<img src="picture4.png" alt="picture4" style="zoom:67%;" />
### 2.5.5. 步骤五 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Rocker_Switch工程的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Rocker_Switch工程的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
## 2.6. 实验结果
按下烧有Rocker_Switch工程的OURS-EnOcean模块的S3、S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。按下S4键数据包的Data为00按下S3键数据包的Data为10。
<img src="picture5.png" alt="picture5" style="zoom:67%;" />
在这个过程中我们将烧有Rocker_Switch工程的OURS-EnOcean模块脱离连接着Sniffer的PC机使用手机充电器供电也能在Sniffer上接收到Rocker_Switch的数据包这验证了数据包是无线传输的。
## 2.7. 实验感想
在Sniffer实验中我们通过串口抓取了EnOcean无线模块之间的通信数据包并在DolphinView可视化软件中查看。这帮助我们理解和掌握了Sniffer嗅探器的工作原理。同时阅读Sniffer源码也加深了我们对EnOcean通信协议和TM4C单片机串口通信的理解。
在实验过程中,我们学习到了解决实验问题的方法。当遇到困难时,我们会小组讨论分析问题原因,充分利用网络资源查阅相关资料,在助教的帮助下最终找到解决办法。这种经验对我们今后独立分析和解决问题具有重要的启示意义。
本次实验采用小组合作形式。通过分工协作,不仅提高了工作效率,也培养了我们的团队协作能力。今后我们会继续提升合作中各成员的配合水平。
# 实验三 EnOcean温度采集实验
## 3.1. 实验目的
学习易能森协议栈温度传感器采集Profile模拟一个温度数据以温度采集Profile发送出去利用Sniffer进行抓包。
## 3.2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
## 3.3. 预备知识
1. 温度传感器是指能感受温度并转换成可用输出信号的传感器
2. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
3. STM330F为一个室内光能供电的温度传感器。
4. 利用DolphinView 可以实现温度传感器的检测。
## 3.4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
uint8_t SendSensorValue(void)
{
uint8_t datalen = FIRST_DATA_SEQ; // 用于存储数据包长度的变量,初始值为数据包中第一个数据的索引
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 设置GPIO引脚电平为0表示开始发送数据
uint8_t randtemp = g_ui32SysTickCount & 0x3f; // 生成一个随机数模拟温度传感器值
// 设置数据包的各个字段
EnOceanTelegramBuf[SYNC_BYTE_SEQ] = SYNC_BYTE; // 同步字节
EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] = 0x00; // 数据包长度高位字节
EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] = 0x0a; // 数据包长度低位字节
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] = 0x07; // 选项字段长度
EnOceanTelegramBuf[PACKET_TYPE_SEQ] = PACKET_TYPES_RADIO; // 数据包类型为无线电包
EnOceanTelegramBuf[HEADER_CRC8_SEQ] = GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN); // 头部的CRC校验
// 数据字段
EnOceanTelegramBuf[datalen++] = EN_DEVICE_RORG; // EnOcean设备类型
EnOceanTelegramBuf[datalen++] = 0x00; // 数据1
EnOceanTelegramBuf[datalen++] = 0x00; // 数据2
EnOceanTelegramBuf[datalen++] = randtemp; // 随机温度传感器值
EnOceanTelegramBuf[datalen++] = 0x08; // 数据3
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = TCM310F_BaseID[i]; // 发送者ID
}
EnOceanTelegramBuf[datalen++] = 0x80; // 状态
// 选项数据
EnOceanTelegramBuf[datalen++] = 0x03; // 子电报号
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = 0xFF; // 目标ID
}
EnOceanTelegramBuf[datalen++] = 0xFF; // dBm发送功率FF
EnOceanTelegramBuf[datalen++] = 0x00; // 安全级别为0表示电报未加密
// 计算并设置数据段CRC校验和
EnOceanTelegramBuf[datalen] = GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen - FIRST_DATA_SEQ);
// 检查数据包长度是否正确
if (CONVERT_UINT16(EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], EnOceanTelegramBuf[DATA_LENGTH_L_SEQ]) +
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] == datalen - FIRST_DATA_SEQ) {
ENOCEAN_UARTSend(EnOceanTelegramBuf, BASE_PACKET_LEN + (datalen - FIRST_DATA_SEQ)); // 通过UART发送数据包
}
else return 1; // 如果数据包长度不符合预期,返回错误代码
// 等待数据包接收完成
while (!EnOceanTelegramRxflags);
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount); // 将接收到的数据复制到发送缓冲区
EnOceanRxCount = 0; // 重置接收缓冲区计数
EnOceanTelegramRxflags = 0; // 重置数据包接收完成标志
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); // 将引脚写为1表示数据传输完成
// 检查接收到的数据包是否包含返回OK的标志
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == RET_OK) return 0; // 如果包含返回OK的标志返回成功代码
return 1; // 否则返回错误代码
}
```
这个函数的作用是生成并发送一个EnOcean数据包其中包含了模拟的温度传感器值和一些固定的字段。函数通过UART发送数据包然后等待接收到带有返回OK标志的响应。
## 3.5. 实验步骤
### 3.5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 3.5.2. 步骤二 加载工程文件
加载Temp_Sensor工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.1EnOcean_Sniffer\IAR_Files”目录下的“Temp_Sensor.eww”工程文件点击“打开”。
### 3.5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Temp_Sensor程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载EnOcean_Sniffer工程。
### 2.5.4. 步骤四 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Temp_Sensor程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Temp_Sensor程序的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
## 3.6. 实验结果
按下烧有Temp_Sensor工程的OURS-EnOcean模块的S3、S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。按下S3键数据包的Data为固定值08 B0 01 87按下S4键数据包的Data始终变化。
<img src="picture6.png" alt="picture6" style="zoom:67%;" />
## 3.7. 实验感想
通过这次温度传感器数据采集实验我们进一步理解和掌握了EnOcean无线通信模块的使用。我们学会了使用随机数模拟温度传感器值并组装成符合EnOcean协议格式的数据包进行无线发送。在Sniffer端成功捕获了发送的温度数据包验证了传输的正确性。
在阅读Temp_Sensor发送端代码时我们学习到了如何按照通信协议格式组织数据以及校验和的计算方法。这对我们后续开发EnOcean无线传感网络具有很好的指导意义。在配置和调用TM4C单片机外设(如GPIO、UART等)的过程中,也加深了我们对单片机外设编程的理解。
本次实验我们小组分工合作,分工明确,团队协作顺畅,实验效率得到提高。我们会在今后的项目中,继续提升团队协作能力,以适应未来更复杂的开发任务。

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -0,0 +1,100 @@
![cover](cover.png)
<h1><center>实验一 环境搭建</center></h1>
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 主要负责完成实验的组织与操作,对实验器材与软件进行测试,在测试中发现问题并与队员协作解决,在实验中也发现部分模块有损坏无法正常使用。 |
| 李桦炅 | 21281282 | 主要负责队员之间的沟通协作,协助完成实验并对实验过程中发现的问题进行记录,再进行沟通完善报告的描述。 |
| 王子励 | 21281292 | 负责实验报告的撰写,查阅背景知识资料工作。 |
| 李志民 | 20281146 | 中途加入小组,完成了实验一的环境配置后,协助了实验中遇到问题的解决。 |
# 1. 实验目的
安装必要的开发工具、烧写工具构建EnOcean模块开发环境以便进行模块开发及实验。
# 2. 工具/原料
- 计算机Windows操作系统
- IAR FOR ARM 7.20安装包
- TI-TM4C-SDK工具包
- DolphinView安装包
- J-link安装包
# 3. 实验步骤
实验一的实验步骤在实验指导书上非常详细,只需要按照配图和文字执行即可。因此我们在本实验报告中仅简单概括一下实验的步骤,并说明我们对每个步骤在本物联网项目中在架构与技术上的理解。
1. 安装IAR FOR ARM 7.20
IAR软件作为项目的IDE软件主要用于编写程序代码、搭建软件工程、调用JTAG工具烧写硬件以及进行DEBUG等。
2. 破解IAR软件
~~IAR软件是商业收费软件。~~
3. 安装SDK工具包
SDK工具包是使用软件驱动硬件的依赖文件是厂商设计的与硬件通信的接口由硬件制造厂商提供。
4. 重建SDK驱动程序库
为了使IAR能在新的安装路径中找到SDK驱动程序需要重建SDK驱动程序库。
在这个步骤我们遇到了困难。排查原因发现是由于项目文件路径含有中文字符导致。由于编译机器使用MinGW作为C语言编译器MinGW不支持中文路径。
5. 安装J-link驱动
J-link是PC机与物联网模块进行烧写和DEBUG等的工具。作为外接的额外硬件需要在PC机上安装J-link的驱动以实现让PC机调用J-link的接口进行控制。
6. 安装DolphinView软件
DolphinView软件能够与后面烧写的Sniffer进行联动显示EnOcean_Sniffer程序采集的数据包。
# 4. 实验结果
我们最后成功将实验环境配置完成。
# 5. 实验感想
通过此次实验我们对物联网系统开发流程有了更直观的了解。在配置开发环境过程中我们安装了IAR、JLink等开发和调试所需的软硬件工具并解决了编译链接和烧录时遇到的问题。这使我们对物联网设备固件的编译、烧录等开发过程有了直接的体会。

View File

@@ -0,0 +1,185 @@
![cover](cover.png)
<h1><center>实验三 EnOcean温度采集实验</center></h1>
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 主要负责完成实验的组织与操作,对实验器材与软件进行测试,在测试中发现问题并与队员协作解决,在实验中也发现部分模块有损坏无法正常使用。 |
| 李桦炅 | 21281282 | 主要负责队员之间的沟通协作,协助完成实验并对实验过程中发现的问题进行记录,再进行沟通完善报告的描述。 |
| 王子励 | 21281292 | 负责实验报告的撰写,查阅背景知识资料工作。 |
| 李志民 | 20281146 | 中途加入小组,完成了实验一的环境配置后,协助了实验中遇到问题的解决。 |
# 1. 实验目的
学习易能森协议栈温度传感器采集Profile模拟一个温度数据以温度采集Profile发送出去利用Sniffer进行抓包。
# 2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
# 3. 预备知识
1. 温度传感器是指能感受温度并转换成可用输出信号的传感器
2. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
3. STM330F为一个室内光能供电的温度传感器。
4. 利用DolphinView 可以实现温度传感器的检测。
# 4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
uint8_t SendSensorValue(void)
{
uint8_t datalen = FIRST_DATA_SEQ; // 用于存储数据包长度的变量,初始值为数据包中第一个数据的索引
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 设置GPIO引脚电平为0表示开始发送数据
uint8_t randtemp = g_ui32SysTickCount & 0x3f; // 生成一个随机数模拟温度传感器值
// 设置数据包的各个字段
EnOceanTelegramBuf[SYNC_BYTE_SEQ] = SYNC_BYTE; // 同步字节
EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] = 0x00; // 数据包长度高位字节
EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] = 0x0a; // 数据包长度低位字节
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] = 0x07; // 选项字段长度
EnOceanTelegramBuf[PACKET_TYPE_SEQ] = PACKET_TYPES_RADIO; // 数据包类型为无线电包
EnOceanTelegramBuf[HEADER_CRC8_SEQ] = GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN); // 头部的CRC校验
// 数据字段
EnOceanTelegramBuf[datalen++] = EN_DEVICE_RORG; // EnOcean设备类型
EnOceanTelegramBuf[datalen++] = 0x00; // 数据1
EnOceanTelegramBuf[datalen++] = 0x00; // 数据2
EnOceanTelegramBuf[datalen++] = randtemp; // 随机温度传感器值
EnOceanTelegramBuf[datalen++] = 0x08; // 数据3
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = TCM310F_BaseID[i]; // 发送者ID
}
EnOceanTelegramBuf[datalen++] = 0x80; // 状态
// 选项数据
EnOceanTelegramBuf[datalen++] = 0x03; // 子电报号
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = 0xFF; // 目标ID
}
EnOceanTelegramBuf[datalen++] = 0xFF; // dBm发送功率FF
EnOceanTelegramBuf[datalen++] = 0x00; // 安全级别为0表示电报未加密
// 计算并设置数据段CRC校验和
EnOceanTelegramBuf[datalen] = GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen - FIRST_DATA_SEQ);
// 检查数据包长度是否正确
if (CONVERT_UINT16(EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], EnOceanTelegramBuf[DATA_LENGTH_L_SEQ]) +
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] == datalen - FIRST_DATA_SEQ) {
ENOCEAN_UARTSend(EnOceanTelegramBuf, BASE_PACKET_LEN + (datalen - FIRST_DATA_SEQ)); // 通过UART发送数据包
}
else return 1; // 如果数据包长度不符合预期,返回错误代码
// 等待数据包接收完成
while (!EnOceanTelegramRxflags);
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount); // 将接收到的数据复制到发送缓冲区
EnOceanRxCount = 0; // 重置接收缓冲区计数
EnOceanTelegramRxflags = 0; // 重置数据包接收完成标志
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); // 将引脚写为1表示数据传输完成
// 检查接收到的数据包是否包含返回OK的标志
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == RET_OK) return 0; // 如果包含返回OK的标志返回成功代码
return 1; // 否则返回错误代码
}
```
这个函数的作用是生成并发送一个EnOcean数据包其中包含了模拟的温度传感器值和一些固定的字段。函数通过UART发送数据包然后等待接收到带有返回OK标志的响应。
# 5. 实验步骤
## 5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
## 5.2. 步骤二 加载工程文件
加载Temp_Sensor工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.1EnOcean_Sniffer\IAR_Files”目录下的“Temp_Sensor.eww”工程文件点击“打开”。
## 5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Temp_Sensor程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载EnOcean_Sniffer工程。
## 5.4. 步骤四 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Temp_Sensor程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Temp_Sensor程序的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
# 6. 实验结果
按下烧有Temp_Sensor工程的OURS-EnOcean模块的S3、S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。按下S3键数据包的Data为固定值08 B0 01 87按下S4键数据包的Data始终变化。
<img src="picture6.png" alt="picture6" style="zoom:67%;" />
# 7. 实验感想
通过这次温度传感器数据采集实验我们进一步理解和掌握了EnOcean无线通信模块的使用。我们学会了使用随机数模拟温度传感器值并组装成符合EnOcean协议格式的数据包进行无线发送。在Sniffer端成功捕获了发送的温度数据包验证了传输的正确性。
在阅读Temp_Sensor发送端代码时我们学习到了如何按照通信协议格式组织数据以及校验和的计算方法。这对我们后续开发EnOcean无线传感网络具有很好的指导意义。在配置和调用TM4C单片机外设(如GPIO、UART等)的过程中,也加深了我们对单片机外设编程的理解。
本次实验我们小组分工合作,分工明确,团队协作顺畅,实验效率得到提高。我们会在今后的项目中,继续提升团队协作能力,以适应未来更复杂的开发任务。

View File

@@ -0,0 +1,211 @@
![cover](cover.png)
<h1><center>实验二 EnOcean Sniffer 实验</center></h1>
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 主要负责完成实验的组织与操作,对实验器材与软件进行测试,在测试中发现问题并与队员协作解决,在实验中也发现部分模块有损坏无法正常使用。 |
| 李桦炅 | 21281282 | 主要负责队员之间的沟通协作,协助完成实验并对实验过程中发现的问题进行记录,再进行沟通完善报告的描述。 |
| 王子励 | 21281292 | 负责实验报告的撰写,查阅背景知识资料工作。 |
| 李志民 | 20281146 | 中途加入小组,完成了实验一的环境配置后,协助了实验中遇到问题的解决。 |
# 1. 实验目的
将一个易能森设备配置为嗅探器Sniffer抓取易能森通信数据包以便分析数据。
# 2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
# 3. 预备知识
1. Sniffer嗅探器是一种基于被动侦听原理的网络分析方式。使用这种技术方式可以监视网络的状态、数据流动情况以及网络上传输的信息。
2. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
3. 利用DolphinView 可以实现Sniffer的检测。
# 4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
void EnOceanUARTIntHandler(void) {
uint32_t ui32Ints; // 用于存储UART中断标志的变量
uint8_t data; // 用于存储接收到的数据字节
static uint8_t PacketHeader = 0; // 表示数据包头部的标志
static uint32_t PacketLen = 0; // 用于存储预期数据包长度的变量
//
// Get and clear the current interrupt source(s)
//
// 获取并清除当前的中断源
ui32Ints = ROM_UARTIntStatus(ENOCEAN_UART_BASE, true);
ROM_UARTIntClear(ENOCEAN_UART_BASE, ui32Ints); // 清除已处理的中断
//
// Handle receive interrupts.
//
// 处理接收中断。
if (ui32Ints & (UART_INT_RX | UART_INT_RT)) { // 检查RX FIFO非空或者超时中断是否发生
data = ROM_UARTCharGetNonBlocking(ENOCEAN_UART_BASE); // 从UART中读取一个字符
// 检查接收缓冲区是否有空间,并且数据包接收不在进行中
if (EnOceanRxCount < ENOCEAN_RX_BUFFER_SIZE && (!EnOceanTelegramRxflags)) {
EnOceanRxBuffer[EnOceanRxCount++] = data; // 将接收到的数据存储到缓冲区中
// 检查数据包头部是否已经被检测到
if (!PacketHeader) {
// 检查数据包的第一个字节是否是头部0x55
if (EnOceanRxBuffer[0] != 0x55) EnOceanRxCount = 0; // 如果头部不符合预期,重置缓冲区
else {
// 检查是否已经接收到6个字节头部 + 数据长度 + 校验和)
if (EnOceanRxCount == 6) {
// 使用接收到的数据计算预期的数据包长度
if (GetCheckSum(&EnOceanRxBuffer[1], 4) == EnOceanRxBuffer[5]) {
PacketLen = 7 + (EnOceanRxBuffer[1] << 8) + EnOceanRxBuffer[2] + EnOceanRxBuffer[3];
PacketHeader = 1; // 设置数据包头部标志
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 将引脚写为0
} else {
EnOceanRxCount = 0; // 如果校验和验证失败,重置缓冲区
}
}
}
} else if (EnOceanRxCount == PacketLen) {
EnOceanTelegramRxflags = 1; // 设置表示完整数据包接收的标志
PacketHeader = 0; // 重置数据包头部标志
PacketLen = 0; // 重置预期数据包长度
}
} else {
// 如果缓冲区已满或者接收到无效的数据包,重置接收缓冲区和数据包头部信息
EnOceanRxCount = 0;
PacketHeader = 0;
PacketLen = 0;
}
}
}
```
# 5. 实验步骤
## 5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
## 5.2. 步骤二 加载工程文件
加载EnOcean_Sniffer工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.1EnOcean_Sniffer\IAR_Files”目录下的“EnOcean_Sniffer.eww”工程文件点击“打开”。
## 5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
在这里我们遇到了问题。在完成上述设置后,我们还是遇到了烧录错误,报错截图如下:
<img src="picture1.png" alt="picture1" style="zoom: 67%;" />
上网查阅资料后我们对比发现设置中的Interface默认为SWD但是我们实验使用的工具为JATG所以需要选择JATG。更改如下
<img src="picture2.png" alt="picture2" style="zoom:67%;" />
更改该选项之后,成功烧录程序。
**加载一位翘板开关工程Rocker_Switch工程**
点击工具栏的红叉退出调试拔掉下载EnOcean_Sniffe程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载1.4Rocker_Switch工程。
## 5.4. 步骤四 安装USB Serial Port
将下载EnOcean Sniffer程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电和传输数据。
在这里我们再次遇到了问题。
用一根micro USB线将OURS_EnOcean模块和PC机相连后PC机并没有如实验指导书所述弹出驱动安装提示窗口。且在设备管理器中可以看到PC机没有正确识别OURS_EnOcean设备如下图所示
<img src="picture3.png" alt="picture3" style="zoom:67%;" />
我们在网上查找新版本的设备驱动程序。将驱动程序版本从“TivaWare_C_Series-2.1.4.178”升级到了“TivaWare_C_Series-2.2.0.295”。在设备管理器右键设备->点击“属性”->点击“驱动程序”->点击“更新驱动程序”->点击“浏览我的电脑以查找驱动程序”->点击“浏览”->选择新驱动的安装目录->点击“确定”即可让PC机更新驱动。现在PC机能正确识别OURS_EnOcean设备了
<img src="picture4.png" alt="picture4" style="zoom:67%;" />
## 5.5. 步骤五 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Rocker_Switch工程的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Rocker_Switch工程的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
# 6. 实验结果
按下烧有Rocker_Switch工程的OURS-EnOcean模块的S3、S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。按下S4键数据包的Data为00按下S3键数据包的Data为10。
<img src="picture5.png" alt="picture5" style="zoom:67%;" />
在这个过程中我们将烧有Rocker_Switch工程的OURS-EnOcean模块脱离连接着Sniffer的PC机使用手机充电器供电也能在Sniffer上接收到Rocker_Switch的数据包这验证了数据包是无线传输的。
# 7. 实验感想
在Sniffer实验中我们通过串口抓取了EnOcean无线模块之间的通信数据包并在DolphinView可视化软件中查看。这帮助我们理解和掌握了Sniffer嗅探器的工作原理。同时阅读Sniffer源码也加深了我们对EnOcean通信协议和TM4C单片机串口通信的理解。
在实验过程中,我们学习到了解决实验问题的方法。当遇到困难时,我们会小组讨论分析问题原因,充分利用网络资源查阅相关资料,在助教的帮助下最终找到解决办法。这种经验对我们今后独立分析和解决问题具有重要的启示意义。
本次实验采用小组合作形式。通过分工协作,不仅提高了工作效率,也培养了我们的团队协作能力。今后我们会继续提升合作中各成员的配合水平。

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,580 @@
![cover](cover.png)
---
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 主要负责完成实验一二三的操作,对实验器材与软件进行测试,在测试中发现问题并与队员协作解决,在实验中也发现部分模块有损坏无法正常使用。 |
| 李桦炅 | 21281282 | 主要负责队员之间的沟通协作,协助完成实验并对实验过程中发现的问题进行记录,再进行沟通完善报告的描述。 |
| 王子励 | 21281292 | 负责实验报告的撰写,查阅背景知识资料工作。 |
| 李志民 | 20281146 | 中途加入小组,完成了实验一的环境配置后,协助了实验中遇到问题的解决。 |
# **实验四** EnOcean门卡实验
## 4.1. 实验目的
学习易能森门卡Profile模拟一个门卡监测设备发送数据使用Sniffer进行抓包。
## 4.2. 工具/原料
- 计算机Windows操作系统
- IAR FOR ARM 7.20安装包
- TI-TM4C-SDK工具包
- DolphinView安装包
- J-link安装包
- 调试单板模块(转接板)一个
## 4.3. 预备知识
1. 门卡实验是通过记录是否刷卡,可以用于门禁卡的应用;
2. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
3. 利用DolphinView 可以实现是否刷门卡的检测。
## 4.4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
// CardStatus: 当卡插入时传参为0x70; 当卡拔出时传参为0x00
// main函数中会循环调用这个函数发送门卡状态且通过标志变量在每次门卡状态变化之后只发送1次
uint8_t SendCardStatus(uint8_t CardStatus) {
uint8_t datalen = FIRST_DATA_SEQ; // 用于存储数据包长度的变量,初始值为数据包中第一个数据的索引
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 将引脚写为0表示开始传输数据
// 设置数据包的各个字段
EnOceanTelegramBuf[SYNC_BYTE_SEQ] = SYNC_BYTE; // 同步字节
EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] = 0x00; // 数据包长度高位字节
EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] = 0x07; // 数据包长度低位字节
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] = 0x07; // 选项字段长度
EnOceanTelegramBuf[PACKET_TYPE_SEQ] = PACKET_TYPES_RADIO; // 数据包类型为无线电包
EnOceanTelegramBuf[HEADER_CRC8_SEQ] = GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN); // 头部的CRC校验和
// 数据字段
EnOceanTelegramBuf[datalen++] = EN_DEVICE_RORG; // EnOcean设备RORG
EnOceanTelegramBuf[datalen++] = CardStatus; // 卡片状态
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = TCM310F_BaseID[i]; // 发送者ID
}
EnOceanTelegramBuf[datalen++] = 0xA0; // 状态
// 选项数据
EnOceanTelegramBuf[datalen++] = 0x03; // 子电报号
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = 0xFF; // 目标ID
}
EnOceanTelegramBuf[datalen++] = 0xFF; // dBm发送情况FF
EnOceanTelegramBuf[datalen++] = 0x00; // 安全级别0表示电报未加密
// 计算并设置数据包的校验和
EnOceanTelegramBuf[datalen] = GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen - FIRST_DATA_SEQ);
// 检查数据包长度是否符合预期
if (CONVERT_UINT16(EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], EnOceanTelegramBuf[DATA_LENGTH_L_SEQ]) +
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] == datalen - FIRST_DATA_SEQ) {
ENOCEAN_UARTSend(EnOceanTelegramBuf, BASE_PACKET_LEN + (datalen - FIRST_DATA_SEQ)); // 发送数据包
}
else return 1; // 如果数据包长度不符合预期,返回错误代码
// 等待数据包接收完成
while (!EnOceanTelegramRxflags);
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount); // 将接收到的数据复制到发送缓冲区
EnOceanRxCount = 0; // 重置接收缓冲区计数
EnOceanTelegramRxflags = 0; // 重置数据包接收完成标志
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); // 将引脚写为1表示数据传输完成
// 检查接收到的数据包是否包含返回OK的标志
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == RET_OK) return 0; // 如果包含返回OK的标志返回成功代码
return 1; // 否则返回错误代码
}
```
## 4.5. 实验步骤
### 4.5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 4.5.2. 步骤二 加载工程文件
加载Key_Card工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.3Key_Card\IAR_Files”目录下的“Key_Card.eww”工程文件点击“打开”。
### 4.5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Key_Card程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载EnOcean_Sniffer工程。
### 4.5.4. 步骤四 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Key_Card程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Key_Card程序的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
## 4.6. 实验结果
按下烧有Key_Card工程的OURS-EnOcean模块的S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。
按下S4键模拟门卡插入发送数据包的Data为0x70松开S4键模拟门卡拔出发送数据包的Data为0x00。所以按一次S4按钮DolphinView窗口会显示收到两个数据包。
<img src="p1.png" alt="p1" style="zoom:67%;" />
## 4.7. 实验感想
通过这次门卡状态检测实验我们进一步理解和掌握了EnOcean无线通信模块的使用。我们模拟门卡插入和拔出的状态按照EnOcean协议格式组装数据并无线发送。同时模拟了一个门卡监测设备使用Sniffer进行抓包并在Sniffer端成功捕获了发送的门卡状态数据包验证了无线传输的正确性。这样可以监测和分析EnOcean门卡的通信数据。通过分析抓包数据我们可以了解门卡的工作状态、通信协议以及与其他设备的交互过程。这对于门卡系统的优化和故障排查非常有帮助。通过这个实验我们对EnOcean技术有了更深入的了解。
本次实验我们小组分工明确,合作顺畅。通过合理的分工,我们提高了实验效率。我们会在今后的项目中,继续提升团队协作能力,以适应未来更复杂的系统开发任务。
# 实验五 易能森开关控制实验
## 5.1. 实验目的
学习易能森开关控制Profile模拟一个开关发送开关指令使用Sniffer抓包。
## 5.2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
## 5.3. 预备知识
1. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
2. 利用DolphinView 可以实现对于翘板开关打开关闭的检测。
## 5.4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
// SwitchStatus: 当开关打开时传参为0x10; 当开关关闭时传参为0x00
// main函数中会循环调用这个函数发送开关状态且通过标志变量在每次开关状态变化之后只发送1次
uint8_t SendSwitchStatus(uint8_t SwitchStatus) {
uint8_t datalen = FIRST_DATA_SEQ; // 用于存储数据包长度的变量,初始值为数据包中第一个数据的索引
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 将引脚写为0表示开始传输数据
// 设置数据包的各个字段
EnOceanTelegramBuf[SYNC_BYTE_SEQ] = SYNC_BYTE; // 同步字节
EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] = 0x00; // 数据包长度高位字节
EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] = 0x07; // 数据包长度低位字节
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] = 0x07; // 选项字段长度
EnOceanTelegramBuf[PACKET_TYPE_SEQ] = PACKET_TYPES_RADIO; // 数据包类型为无线电包
EnOceanTelegramBuf[HEADER_CRC8_SEQ] = GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN); // 头部的CRC校验和
// 数据字段
EnOceanTelegramBuf[datalen++] = EN_DEVICE_RORG; // EnOcean设备RORG
EnOceanTelegramBuf[datalen++] = SwitchStatus; // 开关状态0表示关闭1表示打开
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = TCM310F_BaseID[i]; // 发送者ID
}
EnOceanTelegramBuf[datalen++] = 0xA0; // 状态
// 选项数据
EnOceanTelegramBuf[datalen++] = 0x03; // 子电报号
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = 0xFF; // 目标ID
}
EnOceanTelegramBuf[datalen++] = 0xFF; // dBm发送情况FF
EnOceanTelegramBuf[datalen++] = 0x00; // 安全级别0表示电报未加密
// 计算并设置数据包的校验和
EnOceanTelegramBuf[datalen] = GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen - FIRST_DATA_SEQ);
// 检查数据包长度是否符合预期
if (CONVERT_UINT16(EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], EnOceanTelegramBuf[DATA_LENGTH_L_SEQ]) +
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] == datalen - FIRST_DATA_SEQ) {
ENOCEAN_UARTSend(EnOceanTelegramBuf, BASE_PACKET_LEN + (datalen - FIRST_DATA_SEQ)); // 发送数据包
}
else return 1; // 如果数据包长度不符合预期,返回错误代码
// 等待数据包接收完成
while (!EnOceanTelegramRxflags);
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount); // 将接收到的数据复制到发送缓冲区
EnOceanRxCount = 0; // 重置接收缓冲区计数
EnOceanTelegramRxflags = 0; // 重置数据包接收完成标志
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); // 将引脚写为1表示数据传输完成
// 检查接收到的数据包是否包含返回OK的标志
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == RET_OK) return 0; // 如果包含返回OK的标志返回成功代码
return 1; // 否则返回错误代码
}
```
## 5.5. 实验步骤
### 5.5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 5.5.2. 步骤二 加载工程文件
加载Rocker_Switch工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.4Rocker_Switch\IAR_Files”目录下的“Rocker_Switch.eww”工程文件点击“打开”。
### 5.5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Rocker_Switch程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载EnOcean_Sniffer工程。
### 5.5.4. 步骤四 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Rocker_Switch程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Rocker_Switch程序的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
## 5.6. 实验结果
按下烧有Rocker_Switch工程的OURS-EnOcean模块的S3、S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。
按下S3键表示关闭开关发送数据包的Data为固定值00按下S4键表示打开开关发送数据包的Data为固定值10。
<img src="p2.png" alt="p2" style="zoom:67%;" />
## 5.7. 实验感想
通过这次开关状态检测实验我们进一步掌握了EnOcean无线通信模块的使用方法。我们学习了如何模拟开关的打开和关闭状态,按照EnOcean协议要求组装无线数据包。在Sniffer端成功捕获了发送的开关状态数据验证了无线传输的正确性。
这个实验让我们意识到,在物联网时代,各种智能设备之间的通信变得越来越重要。了解和掌握设备的通信协议和控制方式,可以帮助我们更好地理解和应用这些智能设备。这对于我今后在物联网领域的学习和研究将会非常有帮助。
本次实验我们小组分工明确,合作顺畅。通过合理的分工,提高了实验效率。我们会在今后的项目中,继续提升团队协作能力,以适应更复杂的系统开发。
# 实验六 易能森照明控制实验
## 6.1. 实验目的
学习通过开关控制Profile发送控制指令控制另一个设备上的LED实现模拟照明控制。
## 6.2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
## 6.3. 预备知识
1. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
2. 与EnOcean一位翘板开关结合以实现智能控制LED灯的目的。
## 6.4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
int main(void) {
// 启用延迟堆栈,允许在中断处理程序中使用浮点指令,但会增加额外的堆栈使用。
ROM_FPULazyStackingEnable();
// 设置时钟运行在50MHz的PLL模式下
ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
// 启用系统滴答定时器
ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICK_PERIOD_MS - 1);
ROM_SysTickIntEnable();
ROM_SysTickEnable();
// 启用用于板载LED的GPIO端口
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_4);
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
// 启用用于其他设备的GPIO端口
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_7);
ROM_GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_7, GPIO_PIN_7);
// 启用处理器中断
ROM_IntMasterEnable();
// 初始化EEPROM
HW_Initeeprom();
// 初始化定时器0A
Timer0AInit();
// 初始化EnOcean UART
EnOcean_uart_Init();
// 初始化按键
InitKey();
// 初始化TCM310F设备
InitTCM310F();
while (1) {
// 处理LightLRNFlags标志该标志用于表示系统正在学习中
if (LightLRNFlags) {
// 启用定时器和禁用过滤器
ROM_TimerEnable(TIMER0_BASE, TIMER_A);
FilterEnable(0);
// 在LightLRNFlags标志被清除前持续处理EnOcean数据包
while (LightLRNFlags) {
// 处理EnOcean数据包的接收标志EnOceanTelegramRxflags
if (EnOceanTelegramRxflags) {
// 关闭LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
// 复制接收到的EnOcean数据包到缓冲区
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount);
EnOceanRxCount = 0;
EnOceanTelegramRxflags = 0; // 清除接收标志
// 检查数据包的CRC校验和和数据包类型
if (EnOceanTelegramBuf[HEADER_CRC8_SEQ] == GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN) &&
EnOceanTelegramBuf[PACKET_TYPE_SEQ] == PACKET_TYPES_RADIO) {
// 计算数据包的总长度
uint16_t datalen = (EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] << 8) + EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] + EnOceanTelegramBuf[OPTION_LENGTH_SEQ];
// 检查数据包的尾部CRC校验和
if (EnOceanTelegramBuf[BASE_PACKET_LEN + datalen - 1] == GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen)) {
// 检查数据包类型是否为EN_DEVICE_RORG
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == EN_DEVICE_RORG) {
// 提取设备ID
uint32_t DeviceID = (EnOceanTelegramBuf[FIRST_DATA_SEQ + 2] << 24) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 3] << 16) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 4] << 8) +
EnOceanTelegramBuf[FIRST_DATA_SEQ + 5];
// 检查设备ID是否需要被控制
if (PollControlDeviceID(DeviceID)) {
// 存储控制的设备ID然后切换灯的状态
ControlDeviceIDMsg.ControlDeviceID[ControlDeviceIDMsg.ControlDeviceIDNum % 32] = DeviceID;
ControlDeviceIDMsg.ControlDeviceIDNum += 1;
Light_Toggle(); // 切换灯的状态(开关)
}
}
}
}
// 打开LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
}
}
}
// 处理LightExitLRNFlags标志该标志用于表示系统学习结束
if (LightExitLRNFlags) {
// 禁用定时器、重置学习计时器、清除学习标志
ROM_TimerDisable(TIMER0_BASE, TIMER_A);
LRNTimeCount = 0;
LightLRNFlags = 0;
// 将控制设备ID的信息存储到EEPROM中
ROM_EEPROMProgram((uint32_t*)&ControlDeviceIDMsg, EEPROM_FLAGS_ADDR, sizeof(ControlDeviceIDMsg));
SetControlDevice(); // 设置控制设备
// 启用过滤器并关闭灯
FilterEnable(1);
Light_OFF(); // 关闭灯
LightExitLRNFlags = 0;
}
// 处理LightCLRFlags标志该标志用于表示需要清除控制设备ID的信息
if (LightCLRFlags) {
// 删除所有过滤器并启用新的过滤器
FilterDelAll();
FilterEnable(1);
// 清除控制设备ID的信息
ControlDeviceIDMsg.ControlDeviceIDNum = 0;
ROM_EEPROMProgram((uint32_t*)&ControlDeviceIDMsg, EEPROM_FLAGS_ADDR, sizeof(ControlDeviceIDMsg));
LightCLRFlags = 0;
}
// 处理EnOcean数据包
if (EnOceanTelegramRxflags) {
// 关闭LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
// 复制接收到的数据包到缓冲区
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount);
EnOceanRxCount = 0;
EnOceanTelegramRxflags = 0; // 清除接收标志
// 检查数据包的CRC校验和和数据包类型
if (EnOceanTelegramBuf[HEADER_CRC8_SEQ] == GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN) &&
EnOceanTelegramBuf[PACKET_TYPE_SEQ] == PACKET_TYPES_RADIO) {
// 计算数据包的总长度
uint16_t datalen = (EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] << 8) + EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] + EnOceanTelegramBuf[OPTION_LENGTH_SEQ];
// 检查数据包的尾部CRC校验和
if (EnOceanTelegramBuf[BASE_PACKET_LEN + datalen - 1] == GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen)) {
// 检查数据包类型是否为EN_DEVICE_RORG
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == EN_DEVICE_RORG) {
// 提取设备ID
uint32_t DeviceID = (EnOceanTelegramBuf[FIRST_DATA_SEQ + 2] << 24) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 3] << 16) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 4] << 8) +
EnOceanTelegramBuf[FIRST_DATA_SEQ + 5];
// 检查设备ID是否需要被控制
if (!PollControlDeviceID(DeviceID)) {
// 提取数据包的信息,控制灯的状态
uint8_t data = EnOceanTelegramBuf[FIRST_DATA_SEQ + 1] & 0xf0;
if (data == 0x10 || data == 0x50) {
Light_ON(); // 打开灯
}
else if (data == 0x30 || data == 0x70) {
Light_OFF(); // 关闭灯
}
}
}
}
}
// 打开LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
}
}
}
```
主要实现的功能是:
- **学习模式**不断从接收到的数据包中提取设备ID然后将其存储到EEPROM中。
- **工作模式**不断从接收到的数据包中提取设备ID然后在EEPROM中检索设备ID如果检索到则亮灯。
## 6.5. 实验步骤
### 6.5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 6.5.2. 步骤二 加载工程文件
加载Light_Control工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.5Light_Control\IAR_Files”目录下的“Light_Control.eww”工程文件点击“打开”。
### 6.5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Light_Control程序的OURS-EnOcean模块电源用同样的方法向另外两块OURS-EnOcean模块加载Rocker_Switch工程。
### 6.5.4. 步骤四 实验结果
1. 长按Light_Control模块的S4按键至左上角LED灯闪烁一下清除EEPROM缓存的设备ID
1. 长按Light_Control模块的S3按键至右上角LED灯不断闪烁进入学习模式
1. 按下Rocker_Switch模块的S3按键向Light_Control模块发送数据包
1. 按一下Light_Control模块的S3按键结束学习模式进入工作模式
1. 按下Rocker_Switch模块的S3按键Light_Control模块右上角的LED会点亮按下Rocker_Switch模块的S4按键Light_Control模块右上角的LED会熄灭。
<img src="p3.jpg" alt="p3" style="zoom: 33%;" />
## 6.6. 实验结果
Light_Control模块学习到了收到的数据包的设备ID。
进入工作模式后再次接收到记录的设备ID的数据包后能够辨认该设备并且点亮/熄灭LED灯。
<img src="p4.jpg" alt="p4" style="zoom:33%;" />
## 6.7. 实验感想
通过这次灯光控制实验我们掌握了EnOcean无线通信的学习和控制模式。我们实现了存储控制设备ID并据此点亮和熄灭灯光。在Sniffer端成功捕获了整个过程的无线数据包验证了系统的正确运行。
在阅读代码时我们学习到了如何实现EnOcean设备的双向通信、数据存储和控制。这为我们后续开发基于EnOcean的智能照明控制系统奠定了基础。在配置和调用TM4C单片机外设的过程中进一步加深了对单片机编程的理解。
本次实验我们小组分工明确,合作顺畅。通过合理的分工,提高了实验效率。

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

View File

@@ -0,0 +1,191 @@
![cover](cover.png)
---
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :--------------------------------------------- |
| 柯劲帆 | 21281280 | 详细解读实验代码,规划实验目的,撰写实验报告。 |
| 李桦炅 | 21281282 | 共同完成实验具体操作部分。 |
| 王子励 | 21281292 | 共同完成实验具体操作部分。 |
| 李志民 | 20281146 | 对实验过程中遇到的问题与实验结果进行记录。 |
# 实验五 易能森开关控制实验
## 1. 实验目的
学习易能森开关控制Profile模拟一个开关发送开关指令使用Sniffer抓包。
## 2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
## 3. 预备知识
1. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
2. 利用DolphinView 可以实现对于翘板开关打开关闭的检测。
## 4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
// SwitchStatus: 当开关打开时传参为0x10; 当开关关闭时传参为0x00
// main函数中会循环调用这个函数发送开关状态且通过标志变量在每次开关状态变化之后只发送1次
uint8_t SendSwitchStatus(uint8_t SwitchStatus) {
uint8_t datalen = FIRST_DATA_SEQ; // 用于存储数据包长度的变量,初始值为数据包中第一个数据的索引
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 将引脚写为0表示开始传输数据
// 设置数据包的各个字段
EnOceanTelegramBuf[SYNC_BYTE_SEQ] = SYNC_BYTE; // 同步字节
EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] = 0x00; // 数据包长度高位字节
EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] = 0x07; // 数据包长度低位字节
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] = 0x07; // 选项字段长度
EnOceanTelegramBuf[PACKET_TYPE_SEQ] = PACKET_TYPES_RADIO; // 数据包类型为无线电包
EnOceanTelegramBuf[HEADER_CRC8_SEQ] = GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN); // 头部的CRC校验和
// 数据字段
EnOceanTelegramBuf[datalen++] = EN_DEVICE_RORG; // EnOcean设备RORG
EnOceanTelegramBuf[datalen++] = SwitchStatus; // 开关状态0表示关闭1表示打开
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = TCM310F_BaseID[i]; // 发送者ID
}
EnOceanTelegramBuf[datalen++] = 0xA0; // 状态
// 选项数据
EnOceanTelegramBuf[datalen++] = 0x03; // 子电报号
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = 0xFF; // 目标ID
}
EnOceanTelegramBuf[datalen++] = 0xFF; // dBm发送情况FF
EnOceanTelegramBuf[datalen++] = 0x00; // 安全级别0表示电报未加密
// 计算并设置数据包的校验和
EnOceanTelegramBuf[datalen] = GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen - FIRST_DATA_SEQ);
// 检查数据包长度是否符合预期
if (CONVERT_UINT16(EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], EnOceanTelegramBuf[DATA_LENGTH_L_SEQ]) +
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] == datalen - FIRST_DATA_SEQ) {
ENOCEAN_UARTSend(EnOceanTelegramBuf, BASE_PACKET_LEN + (datalen - FIRST_DATA_SEQ)); // 发送数据包
}
else return 1; // 如果数据包长度不符合预期,返回错误代码
// 等待数据包接收完成
while (!EnOceanTelegramRxflags);
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount); // 将接收到的数据复制到发送缓冲区
EnOceanRxCount = 0; // 重置接收缓冲区计数
EnOceanTelegramRxflags = 0; // 重置数据包接收完成标志
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); // 将引脚写为1表示数据传输完成
// 检查接收到的数据包是否包含返回OK的标志
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == RET_OK) return 0; // 如果包含返回OK的标志返回成功代码
return 1; // 否则返回错误代码
}
```
## 5. 实验步骤
### 5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 5.2. 步骤二 加载工程文件
加载Rocker_Switch工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.4Rocker_Switch\IAR_Files”目录下的“Rocker_Switch.eww”工程文件点击“打开”。
### 5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Rocker_Switch程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载EnOcean_Sniffer工程。
### 5.4. 步骤四 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Rocker_Switch程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Rocker_Switch程序的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
## 6. 实验结果
按下烧有Rocker_Switch工程的OURS-EnOcean模块的S3、S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。
按下S3键表示关闭开关发送数据包的Data为固定值00按下S4键表示打开开关发送数据包的Data为固定值10。
<img src="p2.png" alt="p2" style="zoom:67%;" />
## 7. 实验感想
通过这次开关状态检测实验我们进一步掌握了EnOcean无线通信模块的使用方法。我们学习了如何模拟开关的打开和关闭状态,按照EnOcean协议要求组装无线数据包。在Sniffer端成功捕获了发送的开关状态数据验证了无线传输的正确性。
这个实验让我们意识到,在物联网时代,各种智能设备之间的通信变得越来越重要。了解和掌握设备的通信协议和控制方式,可以帮助我们更好地理解和应用这些智能设备。这对于我今后在物联网领域的学习和研究将会非常有帮助。
本次实验我们小组分工明确,合作顺畅。通过合理的分工,提高了实验效率。我们会在今后的项目中,继续提升团队协作能力,以适应更复杂的系统开发。

View File

@@ -0,0 +1,309 @@
![cover](cover.png)
---
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 详细解读了实验文件代码,具体分析了实验的含义与功能,分析了代码实现的功能对现实的映射,对实验的具体问题如信号的含义,模块的学习方式进行了分析与测试,并撰写实验报告的主要部分。 |
| 李桦炅 | 21281282 | 完成实验的具体操作部分,协助分析模块的学习方式,通过对不同操作方式进行测试分析模块学习的具体方式。 |
| 王子励 | 21281292 | 协助了实验操作与实验报告撰写,并协助进行二者之间的沟通,分析实验需求。 |
| 李志民 | 20281146 | 对实验过程中发现的问题与实验结果进行记录,并对实验内容进行总结,协助撰写实验报告。 |
# 实验六 易能森照明控制实验
## 1. 实验目的
学习通过开关控制Profile发送控制指令控制另一个设备上的LED实现模拟照明控制。
## 2. 工具/原料
- 计算机WINDOWS操作系统
- 2个OURS-EnOcean实验模块
- IAR for ARM 7.20软件
- J-link仿真器一个
- DolphinView软件
- 调试单板模块(转接板)一个
## 3. 预备知识
1. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
2. 与EnOcean一位翘板开关结合以实现智能控制LED灯的目的。
## 4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
int main(void) {
// 启用延迟堆栈,允许在中断处理程序中使用浮点指令,但会增加额外的堆栈使用。
ROM_FPULazyStackingEnable();
// 设置时钟运行在50MHz的PLL模式下
ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
// 启用系统滴答定时器
ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICK_PERIOD_MS - 1);
ROM_SysTickIntEnable();
ROM_SysTickEnable();
// 启用用于板载LED的GPIO端口
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_4);
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
// 启用用于其他设备的GPIO端口
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_7);
ROM_GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_7, GPIO_PIN_7);
// 启用处理器中断
ROM_IntMasterEnable();
// 初始化EEPROM
HW_Initeeprom();
// 初始化定时器0A
Timer0AInit();
// 初始化EnOcean UART
EnOcean_uart_Init();
// 初始化按键
InitKey();
// 初始化TCM310F设备
InitTCM310F();
while (1) {
// 处理LightLRNFlags标志该标志用于表示系统正在学习中
if (LightLRNFlags) {
// 启用定时器和禁用过滤器
ROM_TimerEnable(TIMER0_BASE, TIMER_A);
FilterEnable(0);
// 在LightLRNFlags标志被清除前持续处理EnOcean数据包
while (LightLRNFlags) {
// 处理EnOcean数据包的接收标志EnOceanTelegramRxflags
if (EnOceanTelegramRxflags) {
// 关闭LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
// 复制接收到的EnOcean数据包到缓冲区
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount);
EnOceanRxCount = 0;
EnOceanTelegramRxflags = 0; // 清除接收标志
// 检查数据包的CRC校验和和数据包类型
if (EnOceanTelegramBuf[HEADER_CRC8_SEQ] == GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN) &&
EnOceanTelegramBuf[PACKET_TYPE_SEQ] == PACKET_TYPES_RADIO) {
// 计算数据包的总长度
uint16_t datalen = (EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] << 8) + EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] + EnOceanTelegramBuf[OPTION_LENGTH_SEQ];
// 检查数据包的尾部CRC校验和
if (EnOceanTelegramBuf[BASE_PACKET_LEN + datalen - 1] == GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen)) {
// 检查数据包类型是否为EN_DEVICE_RORG
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == EN_DEVICE_RORG) {
// 提取设备ID
uint32_t DeviceID = (EnOceanTelegramBuf[FIRST_DATA_SEQ + 2] << 24) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 3] << 16) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 4] << 8) +
EnOceanTelegramBuf[FIRST_DATA_SEQ + 5];
// 检查设备ID是否需要被控制
if (PollControlDeviceID(DeviceID)) {
// 存储控制的设备ID然后切换灯的状态
ControlDeviceIDMsg.ControlDeviceID[ControlDeviceIDMsg.ControlDeviceIDNum % 32] = DeviceID;
ControlDeviceIDMsg.ControlDeviceIDNum += 1;
Light_Toggle(); // 切换灯的状态(开关)
}
}
}
}
// 打开LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
}
}
}
// 处理LightExitLRNFlags标志该标志用于表示系统学习结束
if (LightExitLRNFlags) {
// 禁用定时器、重置学习计时器、清除学习标志
ROM_TimerDisable(TIMER0_BASE, TIMER_A);
LRNTimeCount = 0;
LightLRNFlags = 0;
// 将控制设备ID的信息存储到EEPROM中
ROM_EEPROMProgram((uint32_t*)&ControlDeviceIDMsg, EEPROM_FLAGS_ADDR, sizeof(ControlDeviceIDMsg));
SetControlDevice(); // 设置控制设备
// 启用过滤器并关闭灯
FilterEnable(1);
Light_OFF(); // 关闭灯
LightExitLRNFlags = 0;
}
// 处理LightCLRFlags标志该标志用于表示需要清除控制设备ID的信息
if (LightCLRFlags) {
// 删除所有过滤器并启用新的过滤器
FilterDelAll();
FilterEnable(1);
// 清除控制设备ID的信息
ControlDeviceIDMsg.ControlDeviceIDNum = 0;
ROM_EEPROMProgram((uint32_t*)&ControlDeviceIDMsg, EEPROM_FLAGS_ADDR, sizeof(ControlDeviceIDMsg));
LightCLRFlags = 0;
}
// 处理EnOcean数据包
if (EnOceanTelegramRxflags) {
// 关闭LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
// 复制接收到的数据包到缓冲区
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount);
EnOceanRxCount = 0;
EnOceanTelegramRxflags = 0; // 清除接收标志
// 检查数据包的CRC校验和和数据包类型
if (EnOceanTelegramBuf[HEADER_CRC8_SEQ] == GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN) &&
EnOceanTelegramBuf[PACKET_TYPE_SEQ] == PACKET_TYPES_RADIO) {
// 计算数据包的总长度
uint16_t datalen = (EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] << 8) + EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] + EnOceanTelegramBuf[OPTION_LENGTH_SEQ];
// 检查数据包的尾部CRC校验和
if (EnOceanTelegramBuf[BASE_PACKET_LEN + datalen - 1] == GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen)) {
// 检查数据包类型是否为EN_DEVICE_RORG
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == EN_DEVICE_RORG) {
// 提取设备ID
uint32_t DeviceID = (EnOceanTelegramBuf[FIRST_DATA_SEQ + 2] << 24) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 3] << 16) +
(EnOceanTelegramBuf[FIRST_DATA_SEQ + 4] << 8) +
EnOceanTelegramBuf[FIRST_DATA_SEQ + 5];
// 检查设备ID是否需要被控制
if (!PollControlDeviceID(DeviceID)) {
// 提取数据包的信息,控制灯的状态
uint8_t data = EnOceanTelegramBuf[FIRST_DATA_SEQ + 1] & 0xf0;
if (data == 0x10 || data == 0x50) {
Light_ON(); // 打开灯
}
else if (data == 0x30 || data == 0x70) {
Light_OFF(); // 关闭灯
}
}
}
}
}
// 打开LED指示灯
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
}
}
}
```
主要实现的功能是:
- **学习模式**不断从接收到的数据包中提取设备ID然后将其存储到EEPROM中。
- **工作模式**不断从接收到的数据包中提取设备ID然后在EEPROM中检索设备ID如果检索到则亮灯。
## 5. 实验步骤
### 5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 5.2. 步骤二 加载工程文件
加载Light_Control工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.5Light_Control\IAR_Files”目录下的“Light_Control.eww”工程文件点击“打开”。
### 5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Light_Control程序的OURS-EnOcean模块电源用同样的方法向另外两块OURS-EnOcean模块加载Rocker_Switch工程。
### 5.4. 步骤四 实验结果
1. 长按Light_Control模块的S4按键至左上角LED灯闪烁一下清除EEPROM缓存的设备ID
1. 长按Light_Control模块的S3按键至右上角LED灯不断闪烁进入学习模式
1. 按下Rocker_Switch模块的S3按键向Light_Control模块发送数据包
1. 按一下Light_Control模块的S3按键结束学习模式进入工作模式
1. 按下Rocker_Switch模块的S3按键Light_Control模块右上角的LED会点亮按下Rocker_Switch模块的S4按键Light_Control模块右上角的LED会熄灭。
<img src="p3.jpg" alt="p3" style="zoom: 33%;" />
## 6. 实验结果
Light_Control模块学习到了收到的数据包的设备ID。
进入工作模式后再次接收到记录的设备ID的数据包后能够辨认该设备并且点亮/熄灭LED灯。
<img src="p4.jpg" alt="p4" style="zoom:33%;" />
## 7. 实验感想
通过这次灯光控制实验我们掌握了EnOcean无线通信的学习和控制模式。我们实现了存储控制设备ID并据此点亮和熄灭灯光。在Sniffer端成功捕获了整个过程的无线数据包验证了系统的正确运行。
在阅读代码时我们学习到了如何实现EnOcean设备的双向通信、数据存储和控制。这为我们后续开发基于EnOcean的智能照明控制系统奠定了基础。在配置和调用TM4C单片机外设的过程中进一步加深了对单片机编程的理解。
本次实验我们小组分工明确,合作顺畅。通过合理的分工,提高了实验效率。

View File

@@ -0,0 +1,185 @@
![cover](cover.png)
---
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 详细解读实验代码,分析信号中不同数据对应的含义,撰写实验报告。 |
| 李桦炅 | 21281282 | 完成实验的具体操作部分,协助分析数据含义。 |
| 王子励 | 21281292 | 协助实验操作与报告撰写工作,并协助二者间的沟通。 |
| 李志民 | 20281146 | 对实验过程中遇到的问题与实验结果进行记录,并协助完成报告和总结。 |
# 实验四 EnOcean门卡实验
## 1. 实验目的
学习易能森门卡Profile模拟一个门卡监测设备发送数据使用Sniffer进行抓包。
## 2. 工具/原料
- 计算机Windows操作系统
- IAR FOR ARM 7.20安装包
- TI-TM4C-SDK工具包
- DolphinView安装包
- J-link安装包
- 调试单板模块(转接板)一个
## 3. 预备知识
1. 门卡实验是通过记录是否刷卡,可以用于门禁卡的应用;
2. TCM310F工作于模式0单向模块将无线接收到的数据可以通过串口发送到外部主机TCM310F工作于模式1双向模块将无线接收到的数据可以通过串口发送到外部主机同时可将外部主机串口发送的数据或命令通过无线发射出去。
3. 利用DolphinView 可以实现是否刷门卡的检测。
## 4. 核心代码
大致阅读代码,将代码的大致思想写在下面的注释中。
```c
// CardStatus: 当卡插入时传参为0x70; 当卡拔出时传参为0x00
// main函数中会循环调用这个函数发送门卡状态且通过标志变量在每次门卡状态变化之后只发送1次
uint8_t SendCardStatus(uint8_t CardStatus) {
uint8_t datalen = FIRST_DATA_SEQ; // 用于存储数据包长度的变量,初始值为数据包中第一个数据的索引
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // 将引脚写为0表示开始传输数据
// 设置数据包的各个字段
EnOceanTelegramBuf[SYNC_BYTE_SEQ] = SYNC_BYTE; // 同步字节
EnOceanTelegramBuf[DATA_LENGTH_H_SEQ] = 0x00; // 数据包长度高位字节
EnOceanTelegramBuf[DATA_LENGTH_L_SEQ] = 0x07; // 数据包长度低位字节
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] = 0x07; // 选项字段长度
EnOceanTelegramBuf[PACKET_TYPE_SEQ] = PACKET_TYPES_RADIO; // 数据包类型为无线电包
EnOceanTelegramBuf[HEADER_CRC8_SEQ] = GetCheckSum(&EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], PACKET_HEADER_LEN); // 头部的CRC校验和
// 数据字段
EnOceanTelegramBuf[datalen++] = EN_DEVICE_RORG; // EnOcean设备RORG
EnOceanTelegramBuf[datalen++] = CardStatus; // 卡片状态
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = TCM310F_BaseID[i]; // 发送者ID
}
EnOceanTelegramBuf[datalen++] = 0xA0; // 状态
// 选项数据
EnOceanTelegramBuf[datalen++] = 0x03; // 子电报号
for (uint8_t i = 0; i < 4; i++) {
EnOceanTelegramBuf[datalen++] = 0xFF; // 目标ID
}
EnOceanTelegramBuf[datalen++] = 0xFF; // dBm发送情况FF
EnOceanTelegramBuf[datalen++] = 0x00; // 安全级别0表示电报未加密
// 计算并设置数据包的校验和
EnOceanTelegramBuf[datalen] = GetCheckSum(&EnOceanTelegramBuf[FIRST_DATA_SEQ], datalen - FIRST_DATA_SEQ);
// 检查数据包长度是否符合预期
if (CONVERT_UINT16(EnOceanTelegramBuf[DATA_LENGTH_H_SEQ], EnOceanTelegramBuf[DATA_LENGTH_L_SEQ]) +
EnOceanTelegramBuf[OPTION_LENGTH_SEQ] == datalen - FIRST_DATA_SEQ) {
ENOCEAN_UARTSend(EnOceanTelegramBuf, BASE_PACKET_LEN + (datalen - FIRST_DATA_SEQ)); // 发送数据包
}
else return 1; // 如果数据包长度不符合预期,返回错误代码
// 等待数据包接收完成
while (!EnOceanTelegramRxflags);
memcpy(EnOceanTelegramBuf, EnOceanRxBuffer, EnOceanRxCount); // 将接收到的数据复制到发送缓冲区
EnOceanRxCount = 0; // 重置接收缓冲区计数
EnOceanTelegramRxflags = 0; // 重置数据包接收完成标志
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); // 将引脚写为1表示数据传输完成
// 检查接收到的数据包是否包含返回OK的标志
if (EnOceanTelegramBuf[FIRST_DATA_SEQ] == RET_OK) return 0; // 如果包含返回OK的标志返回成功代码
return 1; // 否则返回错误代码
}
```
## 5. 实验步骤
### 5.1. 步骤一 连接模块
OURS-EnOcean模块的CN1接口和调试单板模块的CN2接口相连此实验需要给EnOcean-CORE下载程序。
给EnOcean-CORE下载用20PIN排线将J-Link与节点调试转接板上CORE接口相连。
### 5.2. 步骤二 加载工程文件
加载Key_Card工程打开IAR FOR ARM点击“File”->“Open”->“Workspace”选择本机中“EnOcean\EnOcean_CODE\1.3Key_Card\IAR_Files”目录下的“Key_Card.eww”工程文件点击“打开”。
### 5.3. 步骤三 编译并下载
**设置:**
执行以下步骤设置工程选项:
- 右键工程->“Options”在“General Options”->“Target”选择“TI TM4c123GH6PM”
- 点击“Debugger”->“Setup”选择Driver为“J-Link/J-Trace”
- 点击“J-Link/J-Trace”->“Connection”选择Interface为“JATG”
- 完成设置后点击“OK”。
**编译:**
点击菜单栏中“Project”->“Rebuild All”选项编译程序也可在工程上右键“Rebuild All”。
**烧录:**
编译没有错误后点击菜单栏“Project”->“DownLoad and Debug”。
**加载EnOcean_Sniffer工程**
点击工具栏的红叉退出调试拔掉下载Key_Card程序的OURS-EnOcean模块电源用同样的方法向另一块OURS-EnOcean模块加载EnOcean_Sniffer工程。
### 5.4. 步骤四 实验结果
1. 打开DolphinView软件正确选择串口与设备管理器中一致点击连接。
2. 将下载Key_Card程序的OURS_EnOcean模块用一根micro USB线和PC机相连用于供电
3. 摁下下载Key_Card程序的OURS_EnOcean模块S3/S4按键观察DolphinView软件的显示结果。
## 6. 实验结果
按下烧有Key_Card工程的OURS-EnOcean模块的S4按键观察到DolphinView窗口显示烧有EnOcean_Sniffer工程的OURS-EnOcean模块接收到数据包。
按下S4键模拟门卡插入发送数据包的Data为0x70松开S4键模拟门卡拔出发送数据包的Data为0x00。所以按一次S4按钮DolphinView窗口会显示收到两个数据包。
<img src="p1.png" alt="p1" style="zoom:67%;" />
## 7. 实验感想
通过这次门卡状态检测实验我们进一步理解和掌握了EnOcean无线通信模块的使用。我们模拟门卡插入和拔出的状态按照EnOcean协议格式组装数据并无线发送。同时模拟了一个门卡监测设备使用Sniffer进行抓包并在Sniffer端成功捕获了发送的门卡状态数据包验证了无线传输的正确性。这样可以监测和分析EnOcean门卡的通信数据。通过分析抓包数据我们可以了解门卡的工作状态、通信协议以及与其他设备的交互过程。这对于门卡系统的优化和故障排查非常有帮助。通过这个实验我们对EnOcean技术有了更深入的了解。
本次实验我们小组分工明确,合作顺畅。通过合理的分工,我们提高了实验效率。

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

@@ -0,0 +1,405 @@
<img src="222.png" alt="cover" style="zoom: 150%;" />
---
# 目录
[TOC]
---
# 实验分工
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 负责实验代码的解读,分析了代码的整体思想与运行流程,设计了最后的展示成果。 |
| 李桦炅 | 21281282 | 协助进行实验代码解读分析了LCD屏幕显示图像的代码格式。 |
| 王子励 | 21281292 | 撰写实验报告,与小组成员积极沟通,记录实验进程。 |
| 李志民 | 20281146 | 参与报告撰写,记录实验当中遇到的问题并总结。 |
# 实验一 LCD控制实验
## 1. 实验目的
简易的GUI的相关函数的使用LCD的点阵的原理和应用。通过LCD的控制实验学会利用LCD显示数字、英文和中文并在后续实验中使用LCD显示从传感节点得到的部分数据。
## 2. 工具/原料
- 装有IAR的PC机一台
- 2530仿真器,USB线(A型转B型)
- 无线节点模块,带LCD的智能主板。
## 3. 预备知识
1. 在S012864FPD-14ASBE(3S)点阵图形液晶模块(ST7565P)驱动程序的基础上学习一个简易的GUI(图形用户接口),如画点,线,矩形,矩形填充,显示一幅128*64的图画以及汉字显示等。其中IO分配为
| SCL | SID | A0 | CSn | RESETn |
| ---- | ---- | ---- | ---- | ------ |
| P1.5 | P1.6 | P1.7 | P1.4 | P2.0 |
2. 128\*64点阵型LCD简介
128\*64是一种图形点阵液晶显示器它主要由行驱动器/列驱动器及128\*64全点阵液晶显示器组成。可完成图形显示,也可以显示8\*4个(16\*16点阵)汉字。所谓128\*64全点阵就是有128\*64个点组成当给相应的点通高电平(即1)时点变亮,通低电平(即0)时点不亮。显示汉字也是一样的道理通过对16\*16点阵的设计得到对应汉字。
3. 该实验程序主要分为3部分第一部分为LCM的几个函数主要实现的是对LCD显示的初始化对于硬件编程很重要有兴趣的同学可以了解下这里不作为重点。第二部分为GUI的一系列函数是本次实验的重点主要实现画点、线、矩形、矩形填充显示字等显示功能。前两部分程序都在LCD.c程序中。第三部分是GUIDemo.c主要包含主函数和一些点阵显示内容的定义以及change清屏函数。
## 4. 核心代码
### 4.1. GUI_Init()
在该函数中,首先调用了`LCM_Init()`
1. 设置IO需要的引脚的方向为输出
2. 设置`P2_0`为低电平等待一会儿后再置为高电平这里猜测是在操作LED指示灯
3. 向开发板发送命令开启LCD显示
4. 向开发板发送命令,设置其他参数
然后调用`GUI_ClearScreen()`向缓冲区全写0最后调用`LCM_Refresh()`输出缓冲区内容。
(限于篇幅,这里不贴源代码)
### 4.2. GUI_SetColor()
```c
void GUI_SetColor(UINT8 color1, UINT8 color2)
{
GUI_CopyColor(&disp_color, color1); // 设置显示色
GUI_CopyColor(&back_color, color2); // 设置背景色
}
```
实现了显示色和背景色的设置。
### 4.3. GUI_LoadBitmap()
此函数和`GUI_PutHZ()`的实现是一样的。
```c
void GUI_LoadBitmap(UINT8 x, UINT8 y, UINT8 *dat, UINT8 hno, UINT8 lno)
{
UINT8 i;
for(i=0; i<lno; i++)
{
GUI_LoadLine(x, y, dat, hno); // 输出一行数据
y++; // 显示下一行
dat += (hno>>3); // 计算下一行的数据
if( (hno&0x07)!=0 ) dat++;
}
}
```
这个函数实现了循环调用`GUI_LoadLine()`显示`dat`图像中的每一行。
跟踪`GUI_LoadLine()`
```c
UINT8 GUI_LoadLine(UINT8 x, UINT8 y, UINT8 *dat, UINT8 no)
{
UINT8 bit_dat;
UINT8 i;
UINT8 bakc;
/* 参数过滤 */
/*===========================================================================*/
if(x>=128) return(0); // x坐标越界返回0
if(y>=64) return(0); // y坐标越界返回0
/*===========================================================================*/
for(i=0; i<no; i++)
{
/* 判断是否要读取点阵数据 */
if( (i%8)==0 ) bit_dat = *dat++;
/* 设置相应的点为color或为back_color */
if( (bit_dat&DCB2HEX_TAB[i&0x07])==0 ) GUI_CopyColor(&bakc, back_color);
else GUI_CopyColor(&bakc, disp_color);
GUI_Point(x, y, bakc);
if( (++x)>=128 ) return(0);
}
return(1);
}
```
这个函数执行以下逻辑:
1. 判断要显示的内容坐标有没有越过LCD显示屏的边界
2. 如果`(i%8)==0`读取下一个8位
3. 使用位屏蔽码读取当前8位中的每一位如果为0则用背景色打印在LCD上否则用显示色打印在LCD上
4. 判断要显示的内容坐标有没有越过LCD显示屏的边界
5. 跳转回2继续循环直至打印完毕。
跟踪`GUI_Point()`
```c
UINT8 GUI_Point(UINT8 x, UINT8 y, UINT8 color)
{
UINT8 bak;
if(x>=128) return(0); if(y>=64) return(0); // 参数判断出错返回0
//x=x+4;
/* 设置指定点为1或0 */
/*===========================================================================================*/
bak = ReadByteFromDisplayBuffer(x,y); // 从显示缓冲区读取指定点的1字节数据
if(0==color) // 若让该点灭
{
bak &= (~DEC_HEX_TAB[y&0x07]); // 该点对应的位复位而其他7位不变
}
else // 若让该点亮
{
bak |= DEC_HEX_TAB[y&0x07]; // 该点对应的位置位而其他7位不变
}
WriteByteToDisplayBuffer(x, y, bak); // 向LCM12864指定点对应的显示缓冲区写一字节数据
/*===========================================================================================*/
return(1); // 操作成功返回1
}
```
这个函数执行以下逻辑:
1. 判断要显示的点坐标有没有越过LCD显示屏的边界
2. 读取该点原来的信息;
3. 通过参数color使用与或操作将该点置为亮或灭
4. 将修改后的该点信息写入缓冲区。
### 4.4. GUI_Rectangle()
```c
void GUI_Rectangle(UINT8 x0, UINT8 y0, UINT8 x1, UINT8 y1, UINT8 color)
{
GUI_HLine(x0, y0, x1, color);
GUI_HLine(x0, y1, x1, color);
GUI_RLine(x0, y0, y1, color);
GUI_RLine(x1, y0, y1, color);
}
```
即画出4条边横边用`GUI_HLine()`,竖边用`GUI_RLine()`
跟踪`GUI_HLine()`
```c
void GUI_HLine(UINT8 x0, UINT8 y0, UINT8 x1, UINT8 color)
{
UINT8 bak;
if(x0>x1) {bak = x1;x1 = x0; x0 = bak;} // 对x0、x1大小进行排列以便画图
/* 逐点显示,描出水平线 */
/*==========================*/
do
{
GUI_Point(x0, y0, color);
x0++;
}while(x1>=x0);
/*==========================*/
}
```
实际上就是在循环向缓冲区写入线上的点,`GUI_RLine()`也如此,就不再赘述了。
同理,`GUI_RectangleFill()`就是在画出矩形边框的基础上在中间空白区域用`GUI_HLine()``GUI_RLine()`填充线。
### 4.5. 自主设计的main()函数
```c
void main(void) {
UINT8 i;
GUI_Init(); // GUI初始化
GUI_SetColor(1, 0); // 显示色为亮点,背景色为暗点
while (1) {
GUI_PutHZ(8, 0, (UINT8*)YUANSHEN, 80, 64);
LCM_Refresh(); // 将显示缓冲区中的数据刷新到SO12864FPD-13ASBE(3S)上显示
halWait(200);
GUI_PutHZ(88, 24, (UINT8*)QIDONG, 48, 16);
LCM_Refresh();
change(); // 延时大约2秒后清屏
}
}
```
其中,`YUANSHEN`是一副图像的Bitmap`QIDONG`是三个汉字字符“启动”的Bitmap但实际上这两个变量的实质都是将要显示的内容m*n个像素点中要点亮的设置为1相反则设置为0转换成16进制数存储如下图所示
![p2](p2.png)
<img src="p3.png" alt="p3" style="zoom:40%;" />
代码中使用的两个Bitmap见附录。
## 5. 实验步骤
1. 步骤一给智能主板供电。
2. 步骤二 将一个无线节点模块插入到带LCD智能主板的相应位置。
3. 步骤三 将`CC2350`仿真器的一端通过USB线连接到PC机另一端通过10Pin下载线连接到智能主板的`CC2350`JTAG口。
4. 将智能主板上电源开关拨动开位置,按下仿真器的按钮,仿真器上的指示灯为绿色时,表示连接成功。
5. 仔细分析工程中已有的函数,搞清功能后完成自己的程序,实现显示汉字功能。
6. 通过线上工具将图片或者汉字转换为LCD编码后直接加入代码后在LCD板上完成显示。
## 6. 实验结果
在LCD板上显示自己喜欢的图样并且加入了两幅图像间的显示延迟不再是单一的汉字显示更像是艺术字也属于我们将热爱与实验结合的表现。
<img src="111.jpg" alt="cover" style="zoom:33%;" />
## 7. 实验感想
本次LCD控制实验让我们对LCD的显示原理有了更深入的了解。通过学习GUI相关的函数`GUI_Init()``GUI_SetColor()``GUI_LoadBitmap()`我们理解了LCD的显示是通过逐点控制来实现的。另外需要将要显示的内容先转换为点阵表示的Bitmap然后再逐行扫描输出到LCD上这样的显示流程很有启发意义。
在编写`main()`函数时我们尝试将一副图片和几个汉字字符转换为Bitmap数据并加载显示出来。这个过程让我体会到了将设计转换为代码的乐趣。通过添加必要的延时实现了一个循环显示、切换效果使展示更丰富。
总体来说通过这个实验我们对LCD显示的软硬件原理有了更直观的了解也锻炼了独立设计并实现的能力。这是一次收获颇丰的实验。
## 8. 附录
`YUANSHEN`Bitmap
```c
UINT8 YUANSHEN[] =
{
/*-- 宽x高=80x64 --*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xf0, 0x00,
0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xf0, 0x00,
0x00, 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0xf0, 0x00,
0x00, 0xe0, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0xf8, 0x00,
0x03, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xfc, 0x00,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0x00,
0x07, 0xf8, 0x00, 0xc0, 0x00, 0x3f, 0x80, 0x07, 0xfe, 0x00,
0x03, 0xf0, 0x01, 0xe0, 0x00, 0x0f, 0x00, 0x01, 0xf8, 0x00,
0x03, 0xf0, 0x01, 0xe0, 0x00, 0x06, 0x40, 0x00, 0xe0, 0x00,
0x01, 0xf3, 0x01, 0xe0, 0xc0, 0x04, 0xe3, 0x80, 0xe0, 0x70,
0x01, 0xf3, 0xe1, 0xc3, 0xf0, 0x05, 0xf3, 0xe0, 0x61, 0xfc,
0x01, 0xf3, 0xff, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xff, 0xfe,
0x01, 0xf3, 0xe0, 0x01, 0xf0, 0x0f, 0xfb, 0xf0, 0x60, 0xfc,
0x01, 0xf3, 0xe0, 0x01, 0xf1, 0xcf, 0xfb, 0xf0, 0xe0, 0xf8,
0x01, 0xf3, 0xe0, 0x01, 0xf1, 0xcf, 0x03, 0xf1, 0xf0, 0xf8,
0x01, 0xf3, 0xff, 0xf9, 0xf1, 0xcf, 0x03, 0xf3, 0xf8, 0xf8,
0x01, 0xf3, 0xf7, 0xf1, 0xf1, 0xcf, 0x7b, 0xff, 0xff, 0xf8,
0x01, 0xf3, 0xe0, 0x01, 0xf1, 0xcf, 0x7b, 0xff, 0xff, 0xf8,
0x01, 0xf3, 0xe0, 0x01, 0xf1, 0xcf, 0x7b, 0xf3, 0xf8, 0xf8,
0x01, 0xf3, 0xe0, 0x01, 0xf1, 0xcf, 0x7b, 0xf1, 0xf0, 0xf8,
0x01, 0xf3, 0xff, 0xff, 0xf1, 0xcf, 0x7b, 0xf0, 0xe0, 0xf8,
0x01, 0xf3, 0xc3, 0xf1, 0xf1, 0xcf, 0x7b, 0xf0, 0x60, 0xf8,
0x03, 0xf3, 0x83, 0xf1, 0xc1, 0xcf, 0x7b, 0xff, 0xff, 0xf8,
0x03, 0xe0, 0x03, 0xf0, 0x01, 0xcf, 0x73, 0xf0, 0x61, 0xf8,
0x03, 0xe0, 0xe3, 0xf1, 0xc1, 0xcf, 0x63, 0xe0, 0x60, 0xf8,
0x03, 0xc7, 0xe3, 0xf3, 0xf9, 0xcf, 0x43, 0xc0, 0xe0, 0x78,
0x07, 0x9f, 0xfb, 0xf7, 0xff, 0xcf, 0x03, 0x81, 0xf0, 0x18,
0x07, 0xbf, 0xfb, 0xf7, 0xff, 0x8f, 0x00, 0x07, 0xfc, 0x00,
0x0f, 0x3f, 0x03, 0xf0, 0x3f, 0x8f, 0x00, 0x1f, 0xff, 0x00,
0x1c, 0x3c, 0x03, 0xf0, 0x0f, 0x0f, 0x00, 0x0f, 0xfe, 0x00,
0x18, 0x0c, 0x03, 0xf0, 0x0e, 0x0f, 0x00, 0x07, 0xfc, 0x00,
0x20, 0x03, 0x83, 0xe0, 0x70, 0x0f, 0x00, 0x03, 0xf8, 0x00,
0x00, 0x00, 0x03, 0xe0, 0x00, 0x0e, 0x00, 0x01, 0xf8, 0x00,
0x00, 0x00, 0x03, 0xc0, 0x00, 0x0c, 0x00, 0x01, 0xf0, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x24, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x20, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xe0, 0x00,
0x00, 0x24, 0x28, 0x11, 0x05, 0x00, 0x08, 0x00, 0x60, 0x00,
0x00, 0x24, 0x20, 0x10, 0x45, 0x00, 0x08, 0x00, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
```
`QIDONG`Bitmap
```c
UINT8 QIDONG[] =
{
/*-- 宽x高=48x16 --*/
0x01, 0xc0, 0x7f, 0x70, 0x38, 0x00,
0x7f, 0xff, 0x00, 0x70, 0x38, 0x00,
0x70, 0x07, 0x01, 0xff, 0x38, 0x00,
0x70, 0x07, 0x00, 0x77, 0x18, 0x00,
0x7f, 0xff, 0xff, 0xf7, 0x18, 0x00,
0x70, 0x07, 0x38, 0x77, 0x18, 0x00,
0x70, 0x00, 0x38, 0x77, 0x18, 0x00,
0x70, 0x00, 0x3e, 0x67, 0x18, 0x00,
0x7f, 0xfe, 0x77, 0xe7, 0x00, 0x00,
0x7c, 0x06, 0x6f, 0xe7, 0x00, 0x00,
0x6c, 0x06, 0xfb, 0xc7, 0x3c, 0x00,
0xec, 0x06, 0x01, 0xc7, 0x3c, 0x00,
0xef, 0xfe, 0x03, 0xbe, 0x00, 0x00,
0xcc, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
```
图片或文字转Bitmap网站https://www.zhetao.com/fontarray.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

View File

@@ -0,0 +1,207 @@
<img src="222.png" alt="cover" style="zoom: 150%;" />
---
[TOC]
---
**实验分工**
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 负责实验代码的解读,分析了代码的整体思想与运行流程,设计了最后的报警展示效果。 |
| 李桦炅 | 21281282 | 协助进行实验代码解读分析了LCD可实行的温湿度阈值使得可以展示出实验效果。 |
| 王子励 | 21281292 | 撰写实验报告,与小组成员积极沟通,记录实验进程。 |
| 李志民 | 20281146 | 参与报告撰写,记录实验当中遇到的问题并总结。 |
# 实验二 传感层数据收集实验
## 1. 实验目的
学习使用CC2530及相应的模块采集温湿度光电信号 并针对温湿度电传感器的编程通过Zigbee网络将传感器节点与协调器连接协调器通过Zigbee网络收集传感器的数据将部分收集到的数据显示在LCD上以显示成功收集数据。
## 2. 工具/原料
- 装有IAR的PC机一台。
- 22530仿真器usb线A型转B型
- 无限节点模块带LCD的智能主板温湿度传感器模块。
## 3. 实验原理及其说明
本实验将使用 CC2530 读取温湿度传感器 SHT10 的温度和湿度数据,并通过 CC2530 内部的 ADC 得到光照传感器的数据。最后将采样到的数据转换然后在 LCD 上显示。其中对温湿度的读取是利用 CC2530 的 I/OP1.0 和 P1.1)模拟一个类 IIC 的过程。对光照的采集使用内部的 AIN0 通道。光照和温湿度传感器
SHT10 是一款高度集成的温湿度传感器芯片, 提供全标定的数字输出。它采用专利的 CMOSens 技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容性聚合体测湿敏感元件、一个用能隙材料制成的测温元件,并在同一芯片上,与 14 位的 A/D 转换器以及串行接口电路实现无缝连接。
**SHT10 引脚特性如下:**
1. VDDGND SHT10 的供电电压为 2.4~5.5V。传感器上电后,要等待 11ms 以越过“休眠”状态。在此期间无需发送任何指令。电源引脚VDDGND之间可增加一个 100nF 的电容,用以去耦滤波。
2. SCK 用于微处理器与 SHT10 之间的通讯同步。由于接口包含了完全静态逻辑,因而不存在最小 SCK 频率。
3. DATA 三态门用于数据的读取。DATA 在 SCK 时钟下降沿之后改变状态,并仅在 SCK 时钟上升沿有效。数据传输期间,在 SCK 时钟高电平时DATA 必须保持稳定。为避免信号冲突,微处理器应驱动 DATA 在低电平。需要一个外部的上拉电阻例如10kΩ将信号提拉至高电平。上拉电阻通常已包含在微处理器的 I/O 电路中。
**向 SHT10 发送命令:**
用一组“ 启动传输”时序,来表示数据传输的初始化。它包括:当 SCK 时钟高电平时 DATA 翻转为低电平,紧接着 SCK 变为低电平,随后是在 SCK 时钟高电平时 DATA 翻转为高电平。后续命令包含三个地址位目前只支持“000”和五个命令位。SHT10 会以下述方式表示已正确地接收到指令:在第 8 个 SCK 时钟的下降沿之后,将 DATA 拉为低电平ACK 位)。在第 9 个 SCK 时钟的下降沿之后,释放 DATA恢复高电平
**测量时序(RH 和 T)**
发布一组测量命令00000101表示相对湿度 RH00000011表示温度 T控制器要等待测量结束。这个过程需要大约 11/55/210ms分别对应 8/12/14bit 测量。确切的时间随内部晶振速度最多有±15%变化。SHTxx 通过下拉 DATA 至低电平并进入空闲模式,表示测量的结束。控制器在再次触发 SCK 时钟前,必须等待这个“数据备妥”信号来读出数据。检测数据可以先被存储,这样控制器可以继续执行其它任务在需要时再读出数据。接着传输 2 个字节的测量数据和 1 个字节的CRC 奇偶校验。uC 需要通过下拉DATA 为低电平,以确认每个字节。所有的数据从 MSB 开始,右值有效(例如:对于 12bit 数据,从第 5 个 SCK 时钟起算作 MSB 而对于 8bit 数据, 首字节则无意义)。用 CRC 数据的确认位,表明通讯结束。如果不使用 CRC-8 校验,控制器可以在测量值 LSB 后,通过保持确认位 ack 高电平, 来中止通讯。在测量和通讯结束后SHTxx 自动转入休眠模式。
**通讯复位时序:**
如果与 SHTxx 通讯中断,下列信号时序可以复位串口:当 DATA 保持高电平时,触发 SCK 时钟 9 次或更多。在下一次指令前,发送一个“传输启动”时序。这些时序只复位串口,状态寄存器内容仍然保留。更多 SHT10 信息,请参考相应文档。
**光照强度采集:**
光照采集主要是通过用 CC2530 内部的 ADC 来得到 OURS-CC2530 开发板上的光照传感器输出电压。传感器输出电压(连接到 CC2530 的 AIN0)。
## 4. 核心代码
### 4.1. MAIN函数
```c
void main()
{
SET_MAIN_CLOCK_SOURCE(CRYSTAL); // 设置系统时钟源为32MHz晶体振荡器
GUI_Init(); // GUI初始化
GUI_SetColor(1, 0); // 显示色为亮点,背景色为暗点
int t = 0, h = 0;
int t_threshold = 27, h_theshold = 40;
while (1) {
th_read(&t, &h);
char t_string[40] = {0};
char h_string[40] = {0};
sprintf(t_string, "Temperature = %d", t);
sprintf(h_string, "Humidity = %d", h);
// 当任意监控的值超过阈值,设置警报
if (t > t_threshold || h > h_theshold) GUI_ExchangeColor(); // 警报为将显示的背景颜色设置为深色
// 在LCD屏幕上显示温湿度
GUI_PutString5_7(0, 0, t_string);
GUI_PutString5_7(0, 15, h_string);
LCM_Refresh();
if (t > t_threshold || h > h_theshold) GUI_ExchangeColor();
}
}
```
实现逻辑为:
1. 初始化LCD屏幕
2. 设置温湿度报警阈值;
3. 调用`th_read()`读取温湿度;
4. 将温湿度信息写进字符串;
5. 判断温湿度是否超过了阈值。若是,调用`GUI_ExchangeColor()`将背景颜色设置为深色,表示报警;否则不变;
6. 在LCD屏幕上显示温湿度信息字符串调用函数接口`GUI_PutString5_7()`
7. 结束本轮循环,如果设置了报警,将深色反转回来;
8. 返回3重复循环。
### 4.2. th_read函数
本函数为读取传感器的温湿度的函数。
```c
void th_read(int* t, int* h)
{
unsigned char error, checksum; // 定义错误标志和校验和变量
float humi, temp; // 定义存储原始湿度和温度数据的临时变量
int tmp; // 用于临时存储用于四舍五入计算的变量
initIO(); // 初始化输入输出接口
s_connectionreset(); // 启动传输,准备接收数据
error = 0; // 清除错误标志
error += s_measure(&checksum, 5); // 读取湿度数据并进行校验,错误计数会增加如果有错误发生
humi = d1 * 256 + d2; // 将读取的数据转换为湿度值
error += s_measure(&checksum, 3); // 读取温度数据并进行校验
temp = d1 * 256 + d2; // 将读取的数据转换为温度值
if (error != 0) // 如果有错误发生
s_connectionreset(); // 通信复位,准备重新读取数据
else { // 如果读取成功
// 对温度和湿度数据进行转换和计算,得到最终的值
temp = temp * 0.01 - 44.0;
humi = (temp - 25) * (0.01 + 0.00008 * humi) - 0.0000028 * humi * humi + 0.0405 * humi - 4;
if (humi > 100) humi = 100;
if (humi < 0.1) humi = 0.1;
}
// 对温度值进行四舍五入处理
tmp = (int)(temp * 10) % 10;
if (tmp > 4) temp = temp + 1;
*t = (int)temp; // 返回处理后的温度值
// 对湿度值进行四舍五入处理
tmp = (int)(humi * 10) % 10;
if (tmp > 4) humi = humi + 1;
*h = (int)humi; // 返回处理后的湿度值
}
```
此函数负责读取温度和湿度数据。它初始化通信接口,读取并校验从传感器获得的数据,然后计算出温度和湿度的正确值。
如果数据读取失败,它会重置通信连接。最后,函数通过指针参数返回处理后的温度和湿度值。
## 5. 实验步骤
1. 给智能主板供电。
2. 将一个无线节点模块插入到带LCD的智能主板的相应位置
3. 将温湿度传感器模块插入到智能主板的传感及控制扩展口位置
4. 将CC2530仿真器的一端通过USB线A型转B型连接到PC机另一端通过10Pin下载线连接到智能主板的CC2530 JTAG口J203
5. 将智能主板上电源开关拨至开位置。按下仿真器上的按钮,仿真器上的指示灯为绿色时表示连接成功
6. 将自己改好的程序编译下载到板子上运行,观察现象。
7. 改变温湿度可以向温湿度传感器吹气或将手指按压在传感器上观察LCD上温湿度的变化。
## 6. 实验结果
在LCD板上显示了温湿度的实时测量数据可自行设置阈值来使得lcd板的颜色反转来实现警示的作用。
温湿度正常情况下的显示:
<img src="111.jpg" alt="cover" style="zoom: 25%;" />
温湿度异常,报警的显示:
<img src="666.jpg" alt="cover" style="zoom: 25%;" />
## 7. 实验感想
通过这次的传感层数据收集实验,我深刻体会到了物联网技术在实际应用中的重要性和潜力。实验过程不仅加深了我的理论知识,更重要的是,它提高了我的实践能力和问题解决能力。
一方面实验中使用的CC2530及相关模块为我提供了一个直观的平台让我能够亲手操作和观察温湿度信号的采集过程。这种实践操作使我们对传感器的工作原理和数据通信过程有了更深入的了解。
另一方面团队合作在这次实验中发挥了关键作用。我们每个人都有自己的分工但实验的成功依赖于团队成员之间的有效沟通和协作。在实验过程中我们遇到了一些挑战比如如何优化LCD的显示效果。通过团队讨论和共同努力我们不仅解决了这些问题还增进了团队协作和沟通能力。
总的来说,这次实验不仅让我们对物联网技术有了更深刻的认识,还锻炼了我们的实践操作能力和团队合作能力。我们相信这些经验和技能将在未来学习和职业生涯中发挥重要作用。

BIN
Lab/5_FaceDetection/111.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

BIN
Lab/5_FaceDetection/222.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
Lab/5_FaceDetection/333.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 KiB

View File

@@ -0,0 +1,184 @@
![cover](222.png)
---
# 目录
[TOC]
---
**实验分工**
| 姓名 | 学号 | 分工 |
| :----: | :------: | :----------------------------------------------------------- |
| 柯劲帆 | 21281280 | 负责完成实验代码的主要部分,对模型做细节化调整,设计识别方法与显示效果。检查修正报告。 |
| 李桦炅 | 21281282 | 在实验中协同各个成员进行沟通,确保成员间协作和报告的完成与优化。 |
| 王子励 | 21281292 | 参与实验部分代码的修改调整,撰写实验报告。 |
| 李志民 | 20281146 | 参与报告撰写,记录实验中的问题并总结。 |
# 1. 实验目的
通过互联网等方式对计算机视觉Computer Vision中的Face Detection方向进行自主学习。并进行实践进一步深入理解。
获取摄像头的信息数据使用视频数据实现实时Face Detection任务。人脸检测Face Detection就是给一幅图像找出图像中的所有人脸位置通常用一个矩形框框起来。
# 2. 工具/原料
- PC机一台。
# 3. 实验任务
1.调取本机个人PC摄像头模组。
2.不限编程语言不限算法实现Face Detection任务。
# 4. 实验内容
1.在PC机上通过程序获取无线摄像头的视频数据。
2.在视频数据上做实时的人脸跟踪。实时输出的数据可以各组通过不同算法来实现如多人检测id标志性别等内容
# 5. 核心代码
**配置环境**
```sh
pip install facenet-pytorch opencv-python
```
**运行代码**
```python
import cv2
from facenet_pytorch import MTCNN
# 设置输入图像的大小
image_size = (480, 480)
# 使用MTCNN创建人脸检测流水线
mtcnn = MTCNN(image_size=image_size, keep_all=True)
# 打开摄像头
cap = cv2.VideoCapture(0) # 0 表示默认摄像头,可以根据需要更改为其他数字
# 检查摄像头是否成功打开
if not cap.isOpened():
print("Error: Could not open camera.")
exit()
# 设置窗口名称
cv2.namedWindow("Face Detection", cv2.WINDOW_NORMAL)
while True:
# 读取视频流的帧
ret, frame = cap.read()
# 检查帧是否成功读取
if not ret:
print("Error: Could not read frame.")
break
# 裁剪图像使其成为正方形
min_dim = min(frame.shape[0], frame.shape[1])
start_x = (frame.shape[1] - min_dim) // 2
start_y = (frame.shape[0] - min_dim) // 2
cropped_frame = frame[start_y:start_y+min_dim, start_x:start_x+min_dim]
# 人脸检测
boxes, probs = mtcnn.detect(cropped_frame)
# 绘制人脸边界框
if boxes is not None:
for box in boxes:
# 在原始帧上绘制边界框
cv2.rectangle(frame,
(int(box[0] + start_x), int(box[1] + start_y)),
(int(box[2] + start_x), int(box[3] + start_y)),
(0, 255, 0), 4)
# 在窗口中显示帧
cv2.imshow("Face Detection", frame)
# 检测按键,如果是'q',退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放摄像头资源
cap.release()
# 关闭所有窗口
cv2.destroyAllWindows()
```
代码主要功能模块是MTCNN。
MTCNN的工作原理是通过级联的方式利用多个卷积神经网络来实现人脸检测和对齐。
![cover](111.png)
1. 首先通过P-NetProposal Network粗略地识别出可能包含人脸的区域
2. 然后使用R-NetRefine Network对候选框进行进一步的筛选
3. 最后通过O-NetOutput Network精细化地定位人脸关键点和提取人脸特征。
MTCNN可以同时完成人脸位置的精准定位、人脸对齐和特征提取从而在人脸识别应用中发挥关键作用。
# 6. 实验结果
通过对相关知识的学习后小组成员们最后完成了使用python语言在自己的pc机上完成了调取摄像头画面并框选人脸的任务。不过不尽人意的是由于条件的限制不能够识别框选出侧脸。
<img src="333.png" alt="cover" style="zoom: 33%;" />
# 7. 实验感想
通过实现人脸识别项目,我们深刻体会到了团队合作的重要性和技术创新的挑战。在实验过程中,我们遇到了多种技术难题,例如算法优化和数据处理。通过共同努力,我们克服了这些难关,实现了高效的人脸识别。这个过程不仅提升了我们的编程能力和问题解决技巧,也让我们更深刻地理解了人脸识别技术的潜力与局限。