LED 驱动电路图
下面我们来看一下本次实验所用到的控制寄存器中每一位的取值所对应的意义:
P1DIR (P1 方向寄存器,P0DIR 同理)
P1SEL (P1 功能选择寄存器, P0SEL 同理)
寄存器的设置:
将控制寄存器的某一位置 1:
例: P1DIR |= 0X02;
解释:”|=“表示按位或运算,0X02 为十六进制数,转换成二进制数为 0000 0010 ,若 P1DIR 原 来的值为 0011 0000,或运算后 P1DIR 的值为 0011 0010。根据上面给出的取值表可知, 按位与运 算后 P1_1 的方向改为输出,其他 I/O 口方向保持不变。
将控制寄存器某一位清 0:
例: P1DIR &= ~0X02;
解释:”&=“表示按位与运算,”~“运算符表示取反,0X02 为 0000 0010,即~0X02 为 1111 1101。 若 P1DIR 原来的值为 0011 0010,与运算后 P1DIR 的值为 0011 0000。
1.4 实验内容
通过上述实验原理得知,要实现 D6、D7 的点亮熄灭只需配置 P1_0、P1_1 口引脚即可, 然后将引脚适当的输出高低电平则可实现 D6、D7 的闪烁控制。 下面是源码实现的解析过程:
/\* 主函数 \*/
void main(void){
xtal\_init();
led\_init();
uart0\_init(0x00, 0x00); //初始化串口
lcd\_dis(); //在LCD上显示实验内容、MAC地址等相关信息
while(1){
led\_test();
}
}
主函数中主要实现了以下步骤:
1)初始化 LED 灯即 led_init():设置 P1.0 和 P1.1 为普通 I/O 口, P1 方向为输出,关闭 D6、D7 灯。
2)在主函数中使用 while(1) 等待 LED 灯开关的测试即可。
通过下面的代码来解析 LED 灯的初始化:
/\* led初始化 \*/
void led\_init(void){
P1SEL &= ~0x03; //P1.0和P1.1为普通I/O口
P1DIR |= 0x03; //输出
D7 = 1; //关LED
D6 = 1;
}
上述代码实现了 P1 选择寄存器和方向寄存器的设置,并将 LED 灯的电平置为高电平,即初始 状态下 LED 灯灭。接下来就只需要实现 LED 灯的轮流闪烁了, 通过下面的代码来解析 LED 灯开关的测试:
/\* led闪烁函数 \*/
void led\_test(void){
D7 = 0;
D6 = 1;
Uart\_Send\_String("{data=D6=OFF;D7=ON}"); //在LCD上更新LED状态信息
halWait(250);
halWait(250);
halWait(250);
halWait(250);
D7 = 1;
D6 = 0;
Uart\_Send\_String("{data=D6=ON;D7=OFF}"); //在LCD上更新LED状态信息
halWait(250);
halWait(250);
halWait(250);
halWait(250);
}
上述代码中,通过改变 LED 灯的电平高低来实现灯的亮与灭,即每隔 1s 让 LED 灯闪烁一次, 并在 LCD 上显示当前的 LED 状态。 为了增加实验效果,也可以手动更改闪烁时间。其中, 延时函数的代码如下:
/\* 延时函数 \*/
void halWait(unsigned char wait){
unsigned long largeWait;
if(wait == 0){
return;
}
largeWait = ((unsigned short) (wait << 7));
largeWait += 114 \* wait;
largeWait = (largeWait >> CLKSPD);
while(largeWait--);
return;
}
下图 2.2.2 是本节 LED 实验的流程图:
LED灯实验流程图
通过图 2.2.2 流程图可得知,实现 D6、D7 的轮流闪烁, 会经过系统时钟初始化的过程,而且系 统时钟初始化是必须的, 8051 微处理器的正常运行,必须要经过系统初始化,也就是 xtal_init () 方法,该方法在 sys_init.c 源文件中定义。而在 main.c 中并没有看到调用系统时钟初始化的方法, 这是因为官方库文件已经将系统时钟初始化的方法的调用过程写进启动文件中了。 (在后面的所有章 节中也需要涉及到系统时钟的初始化, 将不再重复说明)
1.5 实验步骤
- 正确连接 SmartRF04 仿真器到 PC 机和 ZXBee CC2530 节点板,确定按照第一章 1.2 节 设置节点板跳线为模式一, 打开 ZXBee CC2530 节点板电源(上电)。
- 打开实验工程: 在文件夹“05-实验例程\第 2 章\2.2-LED”下双击打开工程 LEDs.eww,选 择 Project->Rebuild All 重新编译工程。
- 将连接好的硬件平台上电(CC2530 务必按下开关上电),然后按下 SmartRF04 仿真器上 的复位按键。接下来选择 Project->Download and debug 将程序下载到 CC2530 节点板。
- 下载完后将 CC2530 重新上电或者按下复位按钮,观察两个 LED 的闪烁情况和 LCD 上的 显示内容。
- 修改延时函数,可以改变 LED 小灯的闪烁间隔时间。
1.6 实验结果
LED
2 实验名称——温湿度传感器实验
温湿度传感器实验
2.1 实验目的
- 掌握 DHT11 温湿度传感器的使用
- 通过 CC2530 读取 DHT11 的温湿度数据,并通过串口显示出来
2.2 实验环境
- 硬件:ZXBee CC2530 节点板一块,温湿度传感器板一块,USB 接口 SmartRF04 仿真器,调试转接板, PC 机,USB mini 线
- 软件: Windows XP/Windows 7/8/10 ,IAR 集成开发环境,串口调试工具(超级终端)
2.3 实验原理
本实验中通过 CC2530 IO 口模拟 DHT11 的读取时序,读取 DHT11 的温湿度数据。
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器 。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个 DHT11 传感器都在极为精确的 湿度校验室中进行校准。校准系数以程序的形式储存在 OTP 内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达 20 米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。使用 4 针单排引脚封装。连接方便。
温湿度模块与 CC2530 部分接口电路如下图 3.2.1 所示:
温湿度模块与CC2530 部分接口电路
下面介绍一下 DHT11 的获取温湿度值的原理:
DHT11 的串行接口
DATA 用于微处理器与 DHT11 之间的通讯和同步,采用单总线数据格式,一次通讯时间 4ms 左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为 零。操作流程如下:
一次完整的数据传输为 40bit ,高位先出。
数据格式:8bit 湿度整数数据 +8bit 湿度小数数据 +8bit 温度整数数据 +8bit 温度小数数据+8bit 校验和数据传送正确时校验和数据等于“ 8bit 湿度整数数据 +8bit 湿度小数数据+8bit 温度整数数 据 +8bit 温度小数数据 ” 所得结果的末 8 位。 CC2530 发送一次开始信号后, DHT11 从低功耗模 式转换到高速模式, 等待主机开始信号结束后,DHT11 发送响应信号,送出 40bit 的数据,并触 发一次信号采集, 用户可选择读取部分数据。从模式下, DHT11 接收到开始信号触发一次温湿度采 集, 如果没有接收到主机发送开始信号, DHT11 不会主动进行温湿度采集。采集数据后转换到低速 模式。
通讯过程如下所示:
通讯过程(一)
总线空闲状态为高电平,主机把总线拉低等待 DHT11 响应,主机把总线拉低必须大于 18 毫秒,保证 DHT11 能检测到起始信号。 DHT11 接收到主机的开始信号后, 等待主机开始信号结束,然后发送 80us 低电平响应信号。主机发送开始信号结束后,延时等待 20-40us 后,读取 DHT11 的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。
通讯过程(二)
总线为低电平, 说明 DHT11 发送响应信号, DHT11 发送响应信号后, 再把总线拉高 80us,准 备发送数据,每一 bit 数据都以50us 低电平时隙开始,高电平的长短定了数据位是 0 还是 1 。 格 式见下面图示。如果读取响应信号为高电平,则 DHT11 没有响应, 请检查线路是否连接正常。当最 后一 bit 数据传送完毕后, DHT11 拉低总线 50us , 随后总线由上拉电阻拉高进入空闲状态。
数字 0 信号表示方法如下图所示:
通讯过程(三)
数字 1 信号表示方法如下图所示:
通讯过程(四)
2.4 实验内容
本实验通过 CC2530 IO 口模拟 DHT11 的读取时序,读取 DHT11 的温湿度数据,读取到温湿 度之后通过串口打印出来。
根据温湿度传感器 DHT11 的工作原理以及温湿度数据读取时序,通过编程实现温湿度值的采集,下面是源码实现的解析过程:
void main(void){
xtal\_init();
led\_init();
dht11\_io\_init();
uart0\_init(0x00, 0x00); //初始化串口
#ifdef SPI\_LCD //如果宏定义了SPI\_LCD
lcd\_dis(); //在屏幕上显示相关信息
#endif
while(1){
halWait(250);
halWait(250);
halWait(250);
halWait(250);
dht11\_update();
D7 = !D7;
}
}
主函数中主要实现了以下步骤:
- 初始化系统时钟 xtal_init():选用 32MHz 晶体振荡器。
- 初始化 LED led_init() :设置 P1.0 和 P1.1 为普通 I/O 口,设置 P1 方向为输出,然后关闭 D6、D7 灯。
- 初始化温湿度传感器 dht11_io_init():配置 P1.5 I/O 口。
- 初始化串口 uart0_init() :配置 I/O 口、设置波特率、奇偶校验位和停止位。
- 函数中使用 while(1) 每隔 1s 更新温湿度的值并让 D7 灯闪烁。
上述代码实现了获取温湿度的值并将数据从串口打印输出,每更新一次数据, D7 灯闪烁一次, 其中,初始化温湿度传感器的代码如下:
/\* 初始化温湿度传感器 \*/
void dht11\_io\_init(void){
P0SEL &= ~0x20; //P1为普通I/O口
COM_OUT;
COM_SET;
}
函数 dht11_update()实现每隔 1s 更新传感器的数值,代码如下:
/\* 更新数值 \*/
void dht11\_update(void){
int flag = 1;
unsigned char dat1, dat2, dat3, dat4, dat5, ck;
//主机拉低 18ms
COM_CLR;
halWait(18);
COM_SET;
flag = 0;
while (COM_R && ++flag);
if (flag == 0) return;
//总线由上拉电阻拉高 主机延时 20us
//主机设为输入 判断从机响应信号
//判断从机是否有低电平响应信号 如不响应则跳出, 响应则向下运行
flag = 0;
while (!COM_R && ++flag);
if (flag == 0) return;
flag = 0;
while (COM_R && ++flag);
if (flag == 0) return;
dat1 = dht11\_read\_byte();
dat2 = dht11\_read\_byte();
dat3 = dht11\_read\_byte();
dat4 = dht11\_read\_byte();
dat5 = dht11\_read\_byte();
ck = dat1 + dat2 + dat3 + dat4;
if (ck == dat5) {
sTemp = dat3;
sHumidity = dat1;
}
#ifdef SPI\_LCD //如果宏定义了SPI\_LCD
char dbuf[20] = {0};
sprintf(dbuf,"{A0=%u,A1=%u}",dat1,dat3); //A0 表示湿度,A1 表示温度
Uart\_Send\_String(dbuf);
#else
printf("湿度: %u.%u%% 温度: %u.%u℃ \r\n", dat1,dat2, dat3,dat4);
#endif
}
温湿度实验流程图
2.5 实验步骤
- 准备好带有温湿度传感器的 CC2530 射频板, 确定按照第一章 1.2 节设置节点板跳线为模式一,将 SmartRF04 仿真器连接到该 CC2530 射频板上,接上出厂电源。
- 通过 USB mini 线和调试转接板,正确的连接 PC 和 ZXBee CC2530 无线节点板 (第一次连接需要安装驱动)。
- 打开例程“05-实验例程\第 3 章\3.2-HumiTemp-DHT11”,双击 dht11.eww,打开本实验工程文件。
- 选择 Project->Rebuild All 重新编译工程。
- 上电 CC2530 节点板, 然后按下连接好的 SmartRF04 仿真器的复位按键;接下来点击 IAR 菜单 Project->Download and debug,将程序下载程序到 CC2530 射频板上。
- 在 PC 上打开超级终端或串口调试助手, 设置波特率为 38400,8 数据位, 1 停止位, 无硬 件流控。
- 将 CC2530 射频板上电并复位,运行刚才下载的程序。观察 PC 机串口中输出的温度、湿 度实验数据。
2.6 实验结果
程序运行后串口输出当前的温湿度值。 并且在节点的 LCD 上会有温湿度值的显示。
温湿度实验图
温湿度结果图
3 实验名称——人体红外传感器实验
人体红外传感器实验
3.1 实验目的
- 了解人体红外传感器原理;
- 通过 CC2530 和人体红外传感器实现人体检测。
3.2 实验环境
- 硬件: ZXBee CC2530 节点板一块,人体传感器板一块,USB 接口 SmartRF04 仿真器,调试转接板, PC 机,USB mini 线;
- 软件: Windows XP/Windows 7/8/10,IAR 集成开发环境。
3.3 实验原理
普通人体会发射 10um 左右的特定波长红外线,用专门设计的传感器就可以针对性的检测这种红外线的存在与否,当人体红外线照射到传感器上后,因热释电效应将向外释放电荷,后续电路经检测处理后就能产生控制信号。
热释电效应同压电效应类似,是指由于温度的变化而引起晶体表面荷电的现象。热释电传感器是对温度敏感的传感器。它由陶瓷氧化物或压电晶体元件组成,在元件两个表面做成电极,在传感器监测范围内温度有ΔT的变化时,热释电效应会在两个电极上会产生电荷ΔQ,即在两电极之间产生一微弱的电压ΔV。由于它的输出阻抗极高,在传感器中有一个场效应管进行阻抗变换。热释电效应所产生的电荷ΔQ 会被空气中的离子所结合而消失,即当环境温度稳定不变时,ΔT=0,则传感器无输出。当人体进入检测区,因人体温度与环境温度有差别,产生ΔT,则有ΔT 输出;若人体进入检测区后不动,则温度没有变化,传感器也没有输出了。所以这种传感器检测人体或者动物的活动传感。由实验证明,传感器不加光学透镜(也称菲涅尔透镜),其检测距离小于 2m,而加上光学透镜后,其检测距离可大于 7m。
红外线传感器是利用红外线的物理性质来进行测量的传感器。红外线又称红外光,它具有反射、折射、散射、干涉、吸收等性质。任何物质,只要它本身具有一定的温度(高于绝对零度),都能辐射红外线。红外线传感器测量时不与被测物体直接接触,因而不存在摩擦,并且有灵敏度高,反应快等优点。
红外线传感器包括光学系统、检测元件和转换电路。光学系统按结构不同可分为透射式和反射式两类。检测元件按工作原理可分为热敏检测元件和光电检测元件。热敏元件应用最多的是热敏电阻。热敏电阻受到红外线辐射时温度升高,电阻发生变化(这种变化可能是变大也可能是变小,因为热敏电阻可分为正温度系数热敏电阻和负温度系数热敏电阻),通过转换电路变成电信号输出。光电检测元件常用的是光敏元件,通常由硫化铅、硒化铅、砷化铟、砷化锑、碲镉汞三元合金、锗及硅掺杂等材料制成。
红外线传感器常用于无接触温度测量,气体成分分析和无损探伤,在医学、军事、空间技术和环境工程等领域得到广泛应用。例如采用红外线传感器远距离测量人体表面温度的热像图,可以发现温度异常的部位,及时对疾病进行诊断治疗(见热像仪);利用人造卫星上的红外线传感器对地球云层进行监视,可实现大范围的天气预报;采用红外线传感器可检测飞机上正在运行的发动机的过热情况等。
具有红外传感器的望远镜可用于军事行动,林地战探测密林中的敌人,城市战中探测墙后面的敌人,以上均利用了红外线传感器测量人体表面温度从而得知敌人所在地。
人体红外传感器检测到有人体活动时,其输出的 IO 值发生变化。当传感器模块检测到有人入侵时,会返回一个高电平信号,无人入侵时,返回一个低电平信号, 通过读取 io 口的状态判断是否有人体活动。
通过查看人体红外传感器的电路原理图(出厂光盘 01-文档资料\01-原理图\传感器目录下的 Infrared - 人体红外.pdf 文件)得知, 人体红外传感器模块与CC2530 开发板部分接口电路如下:
人体红外模块与 CC2530 的接口原理图
根据 CC2530 开发板的电路原理图得知,图 3.8.1 中的 GPIO 连接到 CC2530 的 P0_5 口,因此通过检测此 IO 口电平状态的变化,可判断是否检测到周围有人靠近。
3.4 实验内容
通过实验原理得知, 本实验的关键就是配置 P0_5 口,将其设置成输入模式来检测人体红外传感 器输出的电平变化。 下面是源码实现的解析过程:
/\*主函数
-------------------------------------------------------\*/
void main(void){
xtal\_init();
led\_init();
uart0\_init(0x00, 0x00); //初始化串口
#ifdef SPI\_LCD //如果宏定义了SPI\_LCD
lcd\_dis(); //在屏幕上显示相关信息
#endif
P0SEL &= ~0x20; //P0\_5 为普通io口
P0DIR &= ~0x20; //P0\_5 输入
while(1){
Infrared\_Test();
}
}
人体红外测试函数的源码解析如下:
/\*Infrared\_Test函数
-------------------------------------------------------\*/
void Infrared\_Test(void){
char Str[10];
int Value;
Value = P0_5; //P0\_5 与GPIO相连
#ifdef SPI\_LCD //如果宏定义了SPI\_LCD
char dbuf[20] = {0};
sprintf(dbuf,"{A0=%d}",Value);
Uart\_Send\_String(dbuf); //在屏幕上更新传感器的值
#else
char Str[10];
sprintf(Str,"%d\r\n",Value);
Uart\_Send\_String(Str); //串口发送数据
#endif halWait(250); //延时
D7=!D7; //标志发送状态
halWait(250);
halWait(250);
}
下面是本实验的流程图:
人体红外传感器实验流程图
3.5 实验步骤
- 准备好带有人体红外感应传感器的 CC2530 射频板,确定按照第一章 1.2 节设置节点板跳线为模式一,将SmartRF04 仿真器连接到该 CC2530 射频板上,接上出厂电源。通过 USB mini 线和调试转接板,正确的连接 PC 和 ZXBee CC2530 无线节点板(第一次连接需要安装驱动)。
- 打开例程“05-实验例程\第 3 章\3.8-Infrared”,双击 Infrared.eww,打开本实验工程文件。
- 选择 Project->Rebuild All 重新编译工程。
- 上电 CC2530 节点板,然后按下连接好的 SmartRF04 仿真器的复位按键;接下来点击 IAR 菜单 Project->Download and debug,将程序下载程序到 CC2530 射频板上。
- 在 PC 上打开超级终端或串口调试助手, 设置波特率为 38400 ,8 数据位, 1 停止位,无硬件流控。
- 将 CC2530 射频板上电并复位,运行刚才下载的程序。
- 人体靠近节点或者用手在节点面前晃动,观察 IO 值的变化;几秒后,人体远离节点 1 米左 右,观察 IO 值的变化。
3.6 实验结果
当检测到有人体活动时,串口显示 IO 值为 1 。在节点的 LCD 上也有相关显示。
人体红外传感器实验图
4 实验名称——点对点通信实验
点对点通信实验
4.1 实验目的
- 在 ZXBee CC2530 节点板上运行相应实验程序
- 熟悉通过射频通信的基本方法
- 练习使用状态机实现收发功能
4.2 实验环境
- 硬件: ZXBee CC2530 节点板 2 块、 USB 接口的 SmartRF04 仿真器 ,调试转接板 PC 机、USB mini 线
- 软件: Windows XP/Windows 7/8/10 、IAR 集成开发环境、串口监控程序
4.3 实验原理
ZigBee 的通讯方式主要有三种:点播、组播、广播。点播, 顾名思义就是点对点通信,也就是 2 个设备之间的通讯,不容许有第三个设备收到信息;组播,就是把网络中的节点分组,每一个组员发出的信息只有相同组号的组员才能收到;广播,最广泛的也就是一个设备上发出的信息所有设备都能接收到。这也是 ZigBee 通信的基本方式。
在点对点通信的过程中, 先将接收节点上电后进行初始化, 然后通过指令 ISRXON 开启射频接收器,等待接收数据,直到正确接收到数据为止,通过串口打印输出。发送节点上电后和接收节点进行相同的初始化,然后将要发送的数据输出到 TXFIFO 中,再调用指令 ISTXONCCA 通过射频前端发送数据。
4.4 实验内容
在本实验中,主要是实现 ZigBee 点播通信。发送节点将数据通过射频模块发送到指定的接收节点,接收节点通过射频模块收到数据后,再通过串口发送到 PC 机在串口调试助手中显示出来。如果发送节点发送的数据目的地址与接收节点的地址不匹配,接收节点将接收不到数据。 下面是源码实现的解析过程:
void main(void){
halMcuInit(); //初始化mcu
hal\_led\_init(); //初始化LED
hal\_uart\_init(); //初始化串口
lcd\_dis(); //在LCD上显示实验内容、 MAC地址等相关信息
if (FAILED == halRfInit()) { // halRfInit()为射频初始化函数
HAL\_ASSERT(FALSE);
}
// Config basicRF
basicRfConfig.panId = PAN_ID; //panId
basicRfConfig.channel = RF_CHANNEL; //通信信道
basicRfConfig.ackRequest = TRUE; //应答请求
#ifdef SECURITY\_CCM
basicRfConfig.securityKey = key; //安全秘钥
#endif
// Initialize BasicRF
#if NODE\_TYPE
basicRfConfig.myAddr = SEND_ADDR; //发送地址
#else
basicRfConfig.myAddr = RECV_ADDR; //接收地址
#endif
if(basicRfInit(&basicRfConfig)==FAILED) {
HAL\_ASSERT(FALSE);
}
#if NODE\_TYPE
rfSendData(); //发送数据
#else
rfRecvData(); //接收数据
#endif
}
主函数中主要实现了以下步骤:
- 初始化 mcu 即 halMcuInit() :选用 32k 时钟。
- 初始化 LED 灯 hal_led_init() :设置 P1.0、 P1.2 和 P1.3 为普通 I/O 口并将其作为输出, 设置 P2.0 为普通 I/O 口并将其作为输出。
- 初始化串口 hal_uart_init() :配置 I/O 口、设置波特率、奇偶校验位和停止位。
- 初始化射频模块 halRfInit() ,设置网络 ID、通信信道,定义发送地址和接收地址。
- 接收节点调用 rfRecvData()函数来接收数据, 发送节点调用 rfSendData()函数来发送数据。
通过下面的代码来解析射频模块的初始化:
uint8 halRfInit(void){
// Enable auto ack and auto crc
FRMCTRL0 |= (AUTO_ACK | AUTO_CRC);
// Recommended RX settings
TXFILTCFG = 0x09;
AGCCTRL1 = 0x15;
FSCAL1 = 0x00;
// Enable random generator -> Not implemented yet
// Enable CC2591 with High Gain Mode
halPaLnaInit();
// Enable RX interrupt
halRfEnableRxInterrupt();
return SUCCESS;
}
节点发送数据和接收数据的代码实现如下:
/\* 射频模块发送数据函数 \*/
void rfSendData(void){
//定义要发送的数据
char pTxData[30] = {'H', 'e', 'l', 'l', 'o', ' ', 'c', 'c', '2', '5', '3', '0',' '};
uint8 ret;
static unsigned int send_counter = 0; //发送次数计数器
// Keep Receiver off when not needed to save power
basicRfReceiveOff(); //关闭射频接收器
// Main loop
while (TRUE) { //点对点发送数据包
ret = basicRfSendPacket(RECV_ADDR, (uint8\*)pTxData, sizeof pTxData);
printf("{data=send node send %d times}",++send_counter); //在LCD上显示发送次数
if (ret == SUCCESS) {
hal\_led\_on(1);
halMcuWaitMs(100);
hal\_led\_off(1);
halMcuWaitMs(900);
} else {
hal\_led\_on(1);
halMcuWaitMs(1000);
hal\_led\_off(1);
}
}
}
/\* 射频模块接收数据函数 \*/
void rfRecvData(void){
uint8 pRxData[128];
int rlen;
static unsigned int rec_counter = 0; //接收次数计数器
printf("{data=recv node start up...}");
basicRfReceiveOn(); //开启射频接收器
// Main loop
while (TRUE) {
while(!basicRfPacketIsReady());
rlen = basicRfReceive(pRxData, sizeof pRxData, NULL);
if(rlen > 0) {
pRxData[rlen] = 0;
printf("{data="); //将收到的
printf((char \*)pRxData); //数据和
printf(" %d",++rec_counter); //接收到数据的次数
printf("}"); //在LCD上显示出来
}
}
}
接收节点和发送节点的程序流程图如下面两图所示:
接收节点程序流程图 发送节点程序流程图
4.5 实验步骤
- 准备两个 CC2530 无线节点板(参考 1.3 章节, 将无线节点板跳线设置为模式一),分别接上出厂电源;
- 在 PC 机上打开串口终端软件,设置好波特率为 38400,8 数据位, 1 停止位, 无硬件流控。
- 双击本实验程序“第 4 章\4.1-P2P”双击 p2p.eww ,打开本实验工程文件。
- 打开 main.c 文件,下面对一些定义进行介绍。 RF_CHANNEL 宏定义了无线射频通信时使用的信道,在实验室中,多个小组同时进行实验时建议每组选择不同时信道,即每个小组使用不同的 RF_CHANNEL 值(可按顺序编号)。但同一组实验中两个节点需要保证在同一信道, 才能正确通 信。
- PAN_ID 个域网 ID 标示,用来表示不同在网络,在同一实验中,接收和发送节点需要配置为相同的值,否则两个节点将不能正常通信。
SEND_ADDR 发送节点的地址;
RECV_ADDR 接收节点的地址。
6. NODE_TYPE 节点类型: 0-接收节点,1-发送节点。在进行实验时一个节点定义为发送节点用来发送数据,一个定义为接收节点用来接收数据。
7. 修改 main.c 文件中的 NODE_TYPE 的值为 0,保存, 然后选择 Project->Rebuild All 重新编译工程。
8. 将 SmartRF04 仿真器连接 到 串 口与 PC 机相连接 的 CC2530 节 点上,点击菜单 Project->Download and debug 下载程序到节点板。此节点以下称为接收节点。
9. 修改 main.c 文件中的 NODE_TYPE 的值为 1,然后点击保存,然后选择 Project->Rebuild All 重新编译工程。
10. 接下来将接收节点断电,取下 SmartRF04 仿真器连接到另外一个节点上,点击菜单 Project->Download and debug 下载程序到节点板。此节点板以下称为发送节点。
11. 通过 USB mini 线和调试转接板连接接收节点和 PC,打开串口终端软件。
12. 先将接收节点上电。查看 PC 机上的串口输出。接下来将发送节点上电。
13. 从 PC 机上串口调试助手观察接收节点收到的数据。
可以修改发送节点中发送数据的内容,然后编译并下载程序到发送节点,然后从串口调试助手 观察收到的数据。
可以修改接收节点的地址,然后重新编译并下载程序到接收节点,然后从发送节点发送数据, 观察接收节点能正确接收数据。
4.6 实验结果
发送节点将数据发送出去后,接收节点接收到数据, 并通过串口调试助手打印输出。发送数据的最大长度为 125 (加上发送的数据长度和校验,实际发送的数据长度为 128 字节)。在发送节点的 LCD 上会显示发送次数,在接收节点的屏幕上会显示收到的数据和收到数据的次数。
点对点通信实验图
点对点通信结果图
5 实验名称——广播通信实验
广播通信实验
5.1 实验目的
- 在 ZXBee CC2530 节点板上运行自己的程序
- 理解广播的实现方式
5.2 实验环境
- 硬件: ZXBee CC2530 节点板 3 块、USB 接口的 SmartRF04 仿真器,调试转接板,PC 机,USB mini 线
- 软件: Windows XP/Windows 7/8/10 、IAR 集成开发环境、串口监控程序
5.3 实验原理
ZigBee 协议中, 数据包能被单播传输、组播传输或者广播传输。
当应用程序需要将数据包发送给网络的每一个设备时使用广播模式 ,地址模式设置为 AddrBroadcast , 目标地址可以设置为下面广播地址的一种:
NWK_BROADCAST_SHORTADDR_DEVALL(0xFFFF) ——数据包将被传送到网络上的所有设备包括睡眠中的设备。对于睡眠中的设备数据包将被保留在其父亲节点直到查询到它或者消息超时(NWK_INDIRECT_MSG_TIMEO 在 f8wConifg.cfg 中)。
NWK_BROADCAST_SHORTADDR_DEVRXON(0xFFFD) ——数据包将被传送到网络上的所有的打开接收的空闲设备(RXONWHENIDLE) ,也就是除了睡眠中的所有设备。
NWK_BROADCAST_SHORTADDR_DEVZCZR(0xFFFC)——数据包发送给所有的路由器,包括协调器。
5.4 实验内容
在本实验中,主要是实现 ZigBee 广播通信。在发送节点中设置目的地址为广播地址,让发送节点发送数据,接收节点在接收到数据后对接收到的数据的目的地址进行判断,若目的地址为自己的地址或广播地址则接收数据,否则不接收数据。
广播通信实验在点对点射频通信实验的基础上做了如下修改:
- 在 main.c 文件中修改发送节点和接收节点的地址宏;
- 修改 basicRfSendPacket 函数的第一个参数,将其改为广播地址 0xFFFF 。修改如下:
ret = basicRfSendPacket(0xffff,pTxData,sizeof pTxData) ;
实验中一个节点通过射频向外广播数据"hello world!“,如果数据成功发送出去,则发送节点向串口打印"packet sent successfull!” ,否则打印"packet sent failed!";接收节点接收到数据后向串口打印输出"packet received!"和接收的数据内容。
下面是源码实现的解析过程:
void main(void){
halMcuInit(); //初始化mcu
hal\_led\_init(); //初始化LED
hal\_uart\_init(); //初始化串口
lcd\_dis();
if (FAILED == halRfInit()) { //halRfInit()为初始化射频模块函数
HAL\_ASSERT(FALSE);
}
// Config basicRF
basicRfConfig.panId = PAN_ID; //panID
basicRfConfig.channel = RF_CHANNEL; //通信信道
basicRfConfig.ackRequest = TRUE; //应答请求
#ifdef SECURITY\_CCM
basicRfConfig.securityKey = key; //安全秘钥
#endif
// Initialize BasicRF
#if NODE\_TYPE
basicRfConfig.myAddr = SEND_ADDR; //发送地址
#else
basicRfConfig.myAddr = RECV_ADDR; //接收地址
#endif
if(basicRfInit(&basicRfConfig)==FAILED) {
HAL\_ASSERT(FALSE);
}
#if NODE\_TYPE
rfSendData(); //发送数据
#else
rfRecvData(); //接收数据
#endif
}
主函数中主要实现了以下步骤:
- 初始化 mcu 即 halMcuInit():选用 32k 时钟。
- 初始化 LED 灯 hal_led_init():设置 P1.0、P1.2 和 P1.3 为普通 I/O 口并将其作为输出,设置 P2.0 为普通 I/O 口并将其作为输出。
- 初始化串口 hal_uart_init():配置 I/O 口、设置波特率、奇偶校验位和停止位。
- 初始化射频模块 halRfInit(),设置网络 ID、通信信道,定义发送地址和接收地址。
- 接收节点调用 rfRecvData()函数来接收数据, 发送节点调用 rfSendData()函数来发送数据。
通过下面的代码来解析射频模块的初始化:
/\* 初始化射频模块 \*/
uint8 halRfInit(void){
// Enable auto ack and auto crc
FRMCTRL0 |= (AUTO_ACK | AUTO_CRC);
// Recommended RX settings
TXFILTCFG = 0x09;
AGCCTRL1 = 0x15;
FSCAL1 = 0x00;
// Enable random generator -> Not implemented yet
// Enable CC2591 with High Gain Mode
halPaLnaInit();
// Enable RX interrupt
halRfEnableRxInterrupt();
return SUCCESS;
}
节点发送数据和接收数据的代码实现如下:
/\* 射频模块发送数据函数 \*/
void rfSendData(void){ //定义要发送的数据
char pTxData[30] = {'H', 'e', 'l', 'l', 'o', ' ', 'c', 'c', '2', '5', '3', '0',' '};
uint8 ret;
static unsigned int send_counter = 0; //发送次数计数器
// Keep Receiver off when not needed to save power
basicRfReceiveOff(); //关闭射频接收器
// Main loop
while (TRUE) {
printf("{data = "); //通过LCD显示
printf("Broadcast: %s", pTxData); //广播内容
printf(" for %d times}", ++send_counter); //和广播次数
ret = basicRfSendPacket(0xffff, (uint8\*)pTxData, sizeof pTxData);//广播发送数据包
if (ret == SUCCESS) {
hal\_led\_on(1);
halMcuWaitMs(100);
hal\_led\_off(1);
halMcuWaitMs(900);
} else {
hal\_led\_on(1);
halMcuWaitMs(1000);
hal\_led\_off(1);
}
}
}
/\* 射频模块接收数据函数 \*/
void rfRecvData(void){
uint8 pRxData[128];
int rlen;
static unsigned int rec_counter = 0; //接收次数计数器
basicRfReceiveOn(); //开启射频接收器
// Main loop
while (TRUE) {
while(!basicRfPacketIsReady());
rlen = basicRfReceive(pRxData, sizeof pRxData, NULL);
if(rlen > 0) {
pRxData[rlen] = 0;
printf("{data = "); //在LCD上显示
printf("My Address 0x%x,receive:", RECV_ADDR); //接收节点的地址
printf((char \*)pRxData); //和接收节点收到的数据
printf("for %d times}",++rec_counter); //以及接收到的广播包的次数
}
}
}
接收节点和发送节点的程序流程图如下面两图所示:
接收节点程序流程图 发送节点程序流程图
5.5 实验步骤
- 准备 3 个 CC2530 无线节点板(参考 1.3 章节,将无线节点板跳线设置为模式一),分别接上出厂电源。
- 打开光盘“第 4 章\4.2-BroadcastCommunication”,双击 p2p.eww,打开本实验工程文件。
- 按实验原理修改程序。先将 main.c 中的节点类型变量 NODE_TYPE 的值设置为 0 作为接收节点,然后选择 Project->Rebuild All 重新编译工程。
- 将 SmartRF04 仿真器连接到其中一个 CC2530 节点板,上电 CC2530 节点板,然后点击菜单 Project->Download and debug 下载程序到节点板。此节点以下称为接收节点 1。
- 修改 main.c 中的节点短地址 RECV_ADDR 的值为 0x2510,保存,然后选择 Project->Rebuild All 重新编译工程。接下来通过 SmartRF04 仿真器把程序下载到另外一个 CC2530 节点板中,称为接收节点 2。
- 将节点类型变量 NODE_TYPE 的值设置为 1,保存。然后选择 Project->Rebuild All 重新编译工程编译工程,并下载到 ZXBee CC2530 节点板中,作为发送节点。
- 将发送节点通过 USB mini 线和调试转接板连接到 PC 上,在 PC 机上打开串口调试助手,配置串口助手波特率为 38400,8 数据位,1 停止位,无硬件流控。
- 给发送节点重新上电,观察发送节点 LCD 上的显示内容。
- 将接收节点 1 和接收接点 2 上电,依次通过串口线连接到 PC 上,可以看到串口调试助手上打印出相关信息。
5.6 实验结果
实验中,只要节点为接收数据的节点,便能接收数据,实现了射频广播的功能,事实上,若不考虑收发数据的地址,即是广播。
在广播节点 LCD 上显示:Broadcast:Hello cc2530 for 12 times,其中 12 表示广播节点的广播次数。
在接收节点上显示 My Address 0x2520,receive:Hello cc2530 for 10 times。其中 0x2520 表示节点的地址,10 表示收到的广播包次数。不同的接收节点显示的节点地址不同。
广播通信实验图
广播通信结果图
6 实验名称——网络拓扑-星状网
网络拓扑-星状网
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!
s。其中 0x2520 表示节点的地址,10 表示收到的广播包次数。不同的接收节点显示的节点地址不同。
广播通信实验图
广播通信结果图
6 实验名称——网络拓扑-星状网
网络拓扑-星状网
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-iQxSlZrz-1715761367674)]
[外链图片转存中…(img-92aAbTzo-1715761367675)]
[外链图片转存中…(img-LVst8ycw-1715761367676)]
[外链图片转存中…(img-jNweQBHD-1715761367678)]
[外链图片转存中…(img-LbLoS4so-1715761367679)]
[外链图片转存中…(img-wHOBdo7e-1715761367680)]
[外链图片转存中…(img-OYbRlLrO-1715761367681)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!