💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
* 导师视频讲解:[**去听课**](https://www.bilibili.com/video/BV1k34y1D7Vz?p=7) >[success] **技术支持说明:** >**1**.一般以自主学习为主 > **2**.可到官方问答社区中提问:[**去提问**](https://bbs.csdn.net/forums/zigbee) > **3**.工程师**会尽快**解答社区问题,但他们是一线开发,【**难以保证**】解答时效,解答辛苦,感谢理解! <br/> 接着上节课的内容,切换到LED工程,如图所示。 ![](https://img.kancloud.cn/9f/80/9f8022cdea4fc5e209e763698df0dc81_454x522.png =200x) <br/> ## **LED控制原理** #### **计算机的逻辑层与电路层** &emsp;&emsp;在计算机逻辑层中,一般是使用二进制数字0或1来控制对象或表示对象的状态。在计算机电路层中,一般是用高电平(3.3 v)来表示逻辑上的1,用低电平(0 v)来表示逻辑上的0。 ### #### **CPU的IO口** &emsp;&emsp;CPU的GPIO口,通常简称为IO口或引脚,可以理解为从CPU芯片里引出的一根导线,用于连接外部的设备。通俗地讲,一个CPU会有多个IO口,每个IO口有两种工作模式,分别是输出信号模式和接收信号模式。 ### 在输出信号模式时,开发者可以通过代码来控制这个IO口输出的电平,这个电平状态有高电平(3.3v)和低电平(0v)两种。在输入信号模式时,开发者可以通过代码来检测这个IO口是处于高电平还是低电平的状态。 #### **LED的原理分析** ZigBee开发板的LED原理图如图所示。 ![](https://img.kancloud.cn/f6/6e/f66ec236bfa6c38ad81e0cdca544dece_832x164.png =600x) 其中的D2表示LED,其右端接地(GND),因此右端的电压为0v。LED的左端依次连接着R12和IO\_LED。IO\_LED是CC2530的一个IO口,能够输出高电平(3.3v)或低电平(0v)。R12是一个稳压电阻,用于防止电路的电压过大而烧坏LED。当IO\_LED输出高电平时,LED左端电压为3.3v,右端电压为0v,左端和右端形成了3.3v的电压差,因此LED被点亮;反之,当IO\_LED输出低电平时,LED左端和右端电压均为0v,因此LED被熄灭。 >[danger] 如您因缺少硬件原理相关知识导致未能看懂电路图,需先补充相关知识。 <br/> ## **CC2530的引脚简介** CC2530 配备了40个IO口,如图所示。 ![](https://img.kancloud.cn/3b/23/3b234788608ef8733336d64b58fdea90_832x950.png =400x) 其中的P0\_0~P0\_7属于P0端口,P1\_0~P1\_7属于P1端口,P2\_0~P2\_5属于P2端口,这些IO口都可以通过编程的方式使用,接下来将会结合示例来讲解其使用方法。 <br/> ## **\* 查阅TI官方数据手册** 我们可以在本课程配套资源中找到CC2530数据手册,如图所示。 ![](https://img.kancloud.cn/de/d6/ded6b2d7b3a94417cad583928ba0d0ac_930x640.png =200x) * 下载地址:https://gitee.com/study-j/zigbee/tree/master/%E8%AF%BE%E5%A4%96%E8%B5%84%E6%96%99%E5%8F%82%E8%80%83/CC2530%E6%95%B0%E6%8D%AE%E6%89%8B%E5%86%8C ### 该数据手册的目录如下。 ![](https://img.kancloud.cn/9c/b6/9cb6dd696c1221b429429e3b719ece07_490x1262.png =250x) ### 展开《I/O端口》章节,其目录如下。 ![](https://img.kancloud.cn/e2/3a/e23a3b890a44292040b6289db904c625_478x724.png =250x) ### 此数据手册可以用作查阅工具书,供我们随时查阅CC2530的各个细节,例如使用GPIO时就可以找到《I/O 端口》这一小节,使用定时器时就可以找到定时器章节。 <br/> ## **IO口的使用方法** **相关寄存器简介** 可以通过配置相关寄存器的方式来使用IO口,例如配置指定的IO口为输出信号模式并控制其输出高/低电平。CC2530中与IO口配置相关的寄存器如下。 * P0:端口0配置寄存器 * P1:端口1配置寄存器 * P2 :端口2配置寄存器 * PERCFG:外设控制寄存器 * APCFG:模拟外设 I/O 配置寄存器 * P0SEL :端口 0 功能选择寄存器 * P1SEL :端口 1 功能选择寄存器 * P2SEL :端口 2 功能选择寄存器 * P0DIR :端口 0 方向寄存器 * P1DIR :端口 1 方向寄存器 * P2DIR :端口 2 方向寄存器 * P0INP :端口 0 输入模式寄存器 * P1INP :端口 1 输入模式寄存器 * P2INP :端口 2 输入模式寄存器 * P0IFG :端口 0 中断状态标志寄存器 * P1IFG :端口 1 中断状态标志寄存器 * P2IFG :端口 2 中断状态标志寄存器 * PICTL :中断边缘寄存器 * P0IEN :端口 0 中断掩码寄存器 * P1IEN :端口 1 中断掩码寄存器 * P2IEN :端口 2 中断掩码寄存器 * PMUX :掉电信号 Mux 寄存器 * OBSSEL0 :观察输出控制寄存器 0 * OBSSEL1 :观察输出控制寄存器 1 * OBSSEL2 :观察输出控制寄存器 2 * OBSSEL3 :观察输出控制寄存器 3 * OBSSEL4 :观察输出控制寄存器 4 * OBSSEL5 :观察输出控制寄存器 5 <br/> #### **使用P0_4 IO口** 在ZigBee开发板中,CC2530的 P0\_4与LED连接,因此可以通过CC2530的 P0\_4来控制LED的亮灭。可以对P0\_4相关的寄存器进行配置来控制P0\_4 的状态和行为。P0_4相关的寄存器及相应说明见表4-。 ### | 寄存器 | 说明 | | --- | --- | | P0 | 8位寄存器,8个位分别与P0\_0~P0\_7一一对应,分别用于设置或读取这8个IO口的电平状态 | | P0SEL | 8位寄存器,8个位分别与P0\_0~P0\_7一一对应,分别配置这8个IO口的功能。如果IO口对应的位为0,表示该IO口用于通用输入/输出;如果为1,表示用于特定的功能 | | P0DIR | 8位寄存器,8个位分别与P0\_0~P0\_7一一对应,分别配置这8个IO口的通信方向。如果IO口对应的位为0,表示该IO口处于输入信号模式;如果为1,表示处于输出信号模式 | <br/> 根据表格说明,可以按如下方式配置P0\_4的相关寄存器和控制其输出电平,代码如下: ``` // 把P0_4配置为通用输出IO口 P0SEL &= ~(1<<4); // 把P0SEL寄存器的第4位设置为0,表示把P0_4配置为通用IO口 P0DIR |= (1<<4); // 把P0DIR寄存器的第4位设置为1,表示把P0_4配置为输出信号模式 P0_4=0;//输出低电平 P0_4=1;//输出高电平 ``` 其中的P0_4是在头文件ioCC2530.h中定义的,在配置好相关寄存器后,给其赋0或1即可控制其输出电平状态。这里简单讲解一下向左位移运算符<<、取反运算符~、按位与运算符&和按位或运算符|,以便加深读者对代码的理解。 (1)向左位移运算符 << 把所有二进制数字向左移动指定的位数,高位的数字移出(舍弃),低位的空位补0。例如“1<<4”表示把0000 0001中的所有数字向左移动4位,并且高位的0移出舍弃,低位的空位补0,所以运算结果为0001 0000。 (2)取返运算符 ~ 把所有二进制数字取反,例如对0001 0000进行取反运算后的结果为1110 1111。 (3)按位与运算符& 按位与运算规则是把两边的数转换为二进值数,然后把两个数的对应位逐位进行与运算,与运算的规则为1&1=1、1&0=0、0&1=0和0&0=0,例如1101 1101和1110 1111进行按位与运算后的结果为1100 1101。 (4)按位或运算符| 按位或运算规则是把两边的数转换为二进值数,然后把两个数的对应位逐位进行或运算,或运算的规则为1&1=1、1&0=1、0&1=1和0&0=0,例如1101 1101和0001 0000进行按位与运算后的结果为1101 1101。 <br/> ## **编写LED控制代码** 学习了相关原理后,可以编写代码来控制LED,示例代码如下: ``` //51单片机入门/2.GPIO实验/Workspace/code/led/led.c #include "ioCC2530.h" #include <stdio.h> #include <stdint.h> //P0_4由头文件ioCC2530.h定义 #define LED P0_4 //定义LED的开关状态和对应的值 #define LED_ON 1 #define LED_OFF 0 static void delayMs(uint16_t nMs); static void initLed(void); void main() { initLed();//初始化LED while(1) { printf("Set led to on!\r\n"); LED = LED_ON;//开启LED delayMs(500);//延时0.5s后才继续往下执行程序 printf("Set led to off!\r\n"); LED = LED_OFF;//关闭LED delayMs(500);//延时0.5s后才继续往下执行程序 } /* while */ } /** * @fn delayMs * * @brief 让程序延后指定的时间才接着运行 * * @param nMs - 时间长度,以毫秒为单位,值范围:165535 * * @return none */ static void delayMs(uint16_t nMs) { uint16_t i,j; for (i = 0; i < nMs; i++) //经由实际测试可以得出执行535次循环耗时最接近1ms for (j = 0; j < 535; j++); } /** * @fn initLed * * @brief 初始化LED,完成P0_4相关寄存器的配置 */ static void initLed() { P0SEL &= ~(1<<4); P0DIR |= (1<<4); } ``` &emsp;&emsp;以上代码实现了闪烁LED的功能。程序首先通过 initLed对寄存器P0SEL和P0DIR进行初始化,然后对LED值进行定时反转,从而实现了闪烁LED的效果。 <br/> ## **仿真调试** >[danger] 在学习本节课前,需要先掌握基本的程序下载及仿真操作,参考:[程序下载及仿真](2482302) 1. 把开发板通过仿真器连接到电脑上。 2. 按一下仿真器的复位按键。 ![](https://img.kancloud.cn/a6/65/a66518b91448e99ee3e1594218f21591_1710x612.png =200x) ### 3. 打开本实验代码,编译链接通过后,点击“下载仿真”按钮,如图所示。 ![](https://img.kancloud.cn/13/f9/13f9b59478944be9567eb840f95108d4_1372x1204.png =300x) ### 4. 点击Go按钮,全速运行程序,可以观察到LED闪烁的效果,并且Terminal I/O不断输出对应的状态信息,如图所示。 ![](https://img.kancloud.cn/7e/b7/7eb78bc8b2723cfeaf2a58126c170732_2448x858.png =500x) ### 5. 点击如图所示按钮可以停止运行程序。 ![](https://img.kancloud.cn/eb/fc/ebfc0bd853cc4d11664c68d4a06983f8_2448x858.png =500x) <br/> <br/> ## **商务合作** 如有以下需求,可扫码添加管理员好友,注明“**商务合作**” * 项目定制开发,技术范围:**NB-IoT**、**CATn(4G)**、**WiFi**、**ZigBee**、**BLE Mesh**以及**STM32**、**嵌入式Linux**等; * 入驻平台,成为讲师; * 接项目赚外快; * 善学坊官网:[www.sxf-iot.com](https://www.sxf-iot.com/) ![](https://img.kancloud.cn/ca/73/ca739f92cab220a3059378642e3bd502_430x430.png =200x) * 非合作**勿扰**,此处**非**技术支持