tag 标签: ble

相关帖子
相关博文
  • 2025-3-14 17:08
    179 次阅读|
    0 个评论
    万物互联时代,全屋智能正从概念走向现实,而蓝牙低功耗(BLE)技术凭借独特优势,已成为构建智慧家庭生态的核心驱动力之一。作为一项成熟且持续创新的无线通信协议,BLE技术不仅以“低功耗”定义行业标准,更凭借Mesh组网能力打破场景疆界,为智能家居设备提供了灵活、可靠、可扩展的解决方案,有力推动了全屋智能的落地应用。 据中商产业研究院整理数据显示,2023年我国智能家居市场规模为7257亿元,预计到2024年将达7848亿元,到2025年将达到8526亿元,同比增长率约为10%。随着未来新房建设和老房改造的需求增多,以及物联网、云计算、人工智能等技术的更新迭代,智能家居市场将呈上升态势持续发展,市场渗透率亦有望逐步提高,市场潜力巨大。 BLE 技术,推动智能家居发展的 “重要引擎” BLE技术在继承传统蓝牙功能的同时,将功耗大幅降低,是专为传感器、智能门锁、温控器等对功耗要求苛刻、数据传输量小、需要长期稳定运行的小型终端设备而设计。其可通过优化的协议栈设计、LE Power Control(功率控制)功能与休眠算法等能力,大幅提升这些小型终端设备在电池供电条件下的使用寿命,是各种小型智能家居设备理想的无线连接解决方案。 BLE设备工作在2.4GHz的ISM频段,该频段共划分了40个信道(信道带宽为2MHz)。其中,3 个Advertising信道(37、38、39)用于设备的发现和连接请求等操作,37 个Data信道用于数据传输。 BLE设备可以周期性地通过Advertising信道发送广播数据包,其他设备则可通过扫描操作监听广播数据包以发现可连接的 BLE 设备。例如:当一个BLE设备发现另一个BLE设备并希望建立连接时,它会发送连接请求,如果目标设备接受请求,双方就会建立起一个点对点的连接。连接建立后,设备之间可以进行数据的双向传输,从而实现各种智能控制功能。 BLE技术采用了快速连接和断开机制,BLE设备在大部分时间可处于休眠状态,仅在需要传输数据时才被短暂激活,如智能手表与手机连接后,平时可处于低功耗监听模式,有数据交互时才唤醒工作,大大降低了能耗。 此外,BLE技术还具有成熟的开发工具和软件协议栈,开发者可利用丰富的开源资源和示例代码,缩短开发周期,降低开发成本与技术门槛。同时,BLE技术还采用了先进的纠错和重传机制,在有干扰的环境中也能保证数据传输的准确性,如在信道拥挤的环境中,BLE设备仍能准确传输数据。 BLE Mesh技术,推动单品互联到全屋智能 随着智能家居市场的持续发展,蓝牙设备进行一对一、一对多的数据通信已逐渐难以满足众多智能家居设备互联互通的连接需求,而蓝牙低功耗网状网络(BLE Mesh)技术支持多对多网络拓扑(类似网状结构),多个蓝牙设备可以互相发送消息并可作为中继点将消息转发到网络中的其他设备,从而扩展了网络的覆盖范围,让智能家居设备之间可以自由交流、协同工作,是推动单品互联到全屋智能的重要技术驱动力之一。 BLE Mesh网络协议栈 图源:SIG BLE Mesh技术是建立在BLE协议基础上的一种通信协议,旨在为BLE设备创建一个多节点、多跳的网状网络,使设备之间能够进行高效、可靠的通信。其利用了蓝牙技术广泛的市场接受度和低功耗特性,将蓝牙的应用场景从传统的一对一或一对多连接扩展到了大规模的设备网络。 接入BLE Mesh网络中的所有设备都可以被称为节点,而所有节点都能够在Mesh网络中发送并接收消息。此外,一些节点(如传感器)的电池有可能会被耗尽,而其他节点(如照明设备、制造机械和安防摄像机)则会通过主电网来获取电力,不同节点的处理能力会存在差异,因此不同节点在mesh网络中可扮演不同的角色,主要表现出上表的四个节点特征(Features)。 BLE mesh网络拓扑结构简示图 如上图所示,当BLE节点1(手机、平板)需要向低功耗节点1(传感器)传输信息时,会通过GATT Bearer向中继节点2发送信息,中继节点则通过ADV Bearer在广播信道转发BLE节点1(手机、平板)的信息,而朋友节点1、普通节点3和中继节点2都在其无线信号覆盖范围内并接收到消息,朋友节点1作为低功耗节点1(传感器)的好友会储存接收到的信息,而低功耗节点1(传感器)会在唤醒后查询朋友节点1的储存信息来取得BLE节点1(手机、平板)发送给它的消息并做相应的处理。 在万物互联的时代发展背景下,各种传感器、温控器与湿度计等小型终端已被广泛嵌入至智能家居系统之中,它们依靠电池供电且需要长时间稳定的运行,还必须周期性地向控制中心汇报监测信息,而BLE Mesh 技术凭借网状网络架构、低功耗特性与低成本优势,完美契合大量低功耗设备的互联需求,可为智能家居系统的高效运作提供坚实支撑。 值得一提的是,当BLE Mesh技术为全屋智能成功搭建起设备互通的网络骨架时,如何将各种家居设备完美接入网络中就成为了行业关注的焦点,而这则需要底层BLE芯片在通信性能、功耗控制与功能集成等维度上通过设计实现。 例如,CMT4531就是一款超低功耗物联网蓝牙无线通信芯片,搭载 32 位 ARM®Cortex™-M0 内核,最高工作主频64MHz,配备48KB SRAM与256KB FLASH,具有超低功耗、高性能和无线多模的特点,支持无线数据透传功能、全双工双向通讯,最低波特率9600bps。 CMT4531 产品框图 CMT4531 支持BLE高速数据吞吐,包括BLE 2Mbps PHY协议与长度扩展功能;同时,CMT4531还可完全支持BLE Mesh协议下的Friend、LowPower、Proxy、Relay等多种节点特性,是打造智能家居BLE Mesh网络的理想选择之一。 展望未来,随着技术的不断进步和创新,BLE 技术在智能家居中的应用前景将更加广阔。它将不断拓展新的应用场景,与其他前沿技术深度融合,为智能家居的发展注入源源不断的动力,引领我们迈向更加智能、美好的未来生活。
  • 热度 3
    2024-5-20 20:00
    475 次阅读|
    0 个评论
    1. mesh介绍: http://doc.iotxx.com/BLE-Mesh%E6%8A%80%E6%9C%AF%E6%8F%AD%E7%A7%98 2. mesh协议分析: 参考a. https://blog.csdn.net/zhoutaopower/category_9083143.html 参考b.https://blog.csdn.net/wang_yunpeng/category_9665374.html 3. mesh 1.1全新功能介绍: a. https://mp.weixin.qq.com/s/DwnuqqCMV1U_h7Up_-7_PQ b. https://mp.weixin.qq.com/s/sai4OKe0nkfw4tO0WkFIng 4. mesh profile和protocol: 参考蓝牙官网:https://www.bluetooth.com/
  • 热度 4
    2024-1-16 19:14
    654 次阅读|
    0 个评论
    什么是BLE BLE:低功耗蓝牙,采用蓝牙4.0技术具有低成本,短距离特点。可以用于电子手环,蓝牙门锁等场景。 BLE如何进行通信 广播 BLE分为:中心设备和外设设备。 外设设备用GAP协议以广播形式告知中心设备,本机蓝牙可以被链接。中心设备可选择对发送过来的广播数据回复。回复的内容有设备名称,设备地址。也可不回复。 连接建立后就以client-server方式联系 中心设备(手机)作为client 外设设备(手环)作为serve GATT协议 链接建立后,中心设备与外设设备用GATT协议通信 蓝牙应用层的协议,以profile文件的形式存储。 Profile文件结构如下 Service1 Characterisitic1 Characterisitic2 Service2 Characterisitic …. 每个profile包含若干个service,每个service包含若干个characteristic 而characteristic包含Properties ,value。 Properties 规定了cilent应以怎样的方式处理characteristic的内容 Properties的属性如下 属性名称 描述 read 支持 read 操作 write 支持 write 操作 notify 支持 notify 操作 indicate 支持 indicate 操作 当service端的蓝牙 characteristicr是Indicate 属性 客户端就必须要以indicate方式来读写characteristic 不能用其他三种。 无论是service还是characteristic最后都被封装成(Attribute )att数据包。 ATT协议包括三部分 handle ,type,value Handle: Attribute句柄。Client要访问Server的Attribute,都是通过这个句柄来访问的 在蓝牙数据包中一般都有这个值 Type :由UUID来定义。蓝牙联盟有统一的UUID设备标识。 具体使用使用时可以自定义也可用蓝牙联盟的。 Value:蓝牙数据包具体携带的值。 EFR32的BLE配置工具 到此我们只关心三件事情。 1.创建我们自定义的service和characteristic 2.用自定义的的characteristic向client发送数据 3.client接收数据 而GAP 和GATT都由EFR32的蓝牙SDK完成。 为了方便起见,我们首先分析一下EFR32的温度传感器例程代码。 在使用IDE的配置工具配置自定义的BLE任务 EFR32把蓝牙程序分成了两部分,一部分是bootloader,另一部分是蓝牙程序。 在下载蓝牙例程,需要先下载蓝牙的bootloader 导入一个蓝牙温度的例程 下载 https://www.silabs.com/documents/public/software/android-efr-connect.apk 如图所示 打开串口 打开IDE 看到有BLE组件 EFR32开发 蓝牙工程分析及自定义一个蓝牙任务发送数据蓝牙工程分析 先来找蓝牙发送函数 搜索字符串“Temperature:”在工程中位置 在app.c的app_periodic_ timer_cb函数里 这个函数是定时器的回调函数 周期性的获取温度值,并通过app_log_info和sl_bt_ht_temperature_measurement_indicate发送到串口与蓝牙。 sl_sensor_rht_get是温度获取函数 那么谁来调用 app_periodic_timer_cb函数呢? 在app.的 sl_bt_ht_temperature_measurement_indication_changed_cb 函数里调用用了app_periodic_timer_cb 通过源码可知,这个函数是在蓝牙连接建立后,client访问server中characteristic中的temperature_measurement子项时调用的。 调用方式是indicate。意思是server端发送完成后,client需要回复确认收到。 在sl_bt_ht_temperature_measurement_indication_changed_cb 进行了开启定时器,绑定回调函数操作 那sl_bt_ht_temperature_measurement_indication_changed_cb 是谁在调用? 是sl_bt_ht_on_event在调用 sl_bt_ht_on_event是蓝牙温度测量事件函数。 这个函数完成了温度测量的 characteristic从开始发送到发送完成关闭定时器的操作。 关心这几个部分。 sl_bt_gatt_server_write_attribute_value 在本地 GATT 数据库中写入属性值。如果本地 GATT 数据库中的属性具有指示或通知属性,且客户端已启用通知或指示功能,则写入该属性的值不会触发向远程 GATT 客户端发送通知或指示。 gattdb_temperature_measurement case sl_bt_evt_gatt_server_characteristic_status_id: *@brief表示本地客户端特征配置 *描述符被远程GATT客户端更改,或者来自的确认 *远程GATT客户端在成功接收 *指示 * 来梳理下sl_bt_ht_on_event完成的事情 刚开始进入蓝牙温度任务 先执行health_thermometer_init(); 往蓝牙gatt数据库中写入 temperature_type的属性。 温度数据发送都是按照这个属性(att)发送的 之后case sl_bt_evt_gatt_server_characteristic_status_id 说temperature_type的属性的蓝牙通信建立。 data.evt_gatt_server_characteristic_status.characteristic 判断蓝牙句柄拿到的uuid是否是gatt数据库中有的 data.evt_gatt_server_characteristic_status.status_flags 客户端的characteristic已经改变 执行sl_bt_ht_temperature_measurement_indication_changed_cb 当蓝牙温度att通信关闭执行 case sl_bt_evt_connection_closed_id: data.evt_connection_closed.reason, data.evt_connection_closed.connection); break; 接下来看看sl_bt_ht_on_event是由谁调用 在sl_bluebooth.c的sl_bt_process_event里调用。 这是处理蓝牙任务函数包括 sl_bt_in_place_ota_dfu_on_event(evt); sl_gatt_service_device_information_on_event(evt); sl_bt_ht_on_event(evt); sl_bt_on_event(evt);//这是个虚函数里面没有代码 与配置工具对应 在在sl_bluebooth.c的 sl_bt_step里调用。 sl_bt_step轮询蓝牙堆栈中的事件并进行处理 在sl_event_handler.c的sl_stack_process_action调用sl_bt_step 在sl_system_process_action.c的 sl_system_process_action调用sl_stack_process_action sl_system_process_action进行系统初始化和操作处理 *此函数调用一组自动生成的函数,这些函数位于`autogen/sl_event_handler.c`中。 可以使用事件处理程序组件提供的事件处理程序API为以下事件注册处理程序: sl_platform_init() sl_driver_init() sl_service_init() sl_stack_init() sl_internal_app_init() sl_system_process_action()在main函数while中调用 到这里已经把应用相关代码过了一遍 如图 我们只需要关心 修改sl_bt_ht_on_event函数变成我们自己的 仿照修改即可 接下来看看发送函数 sc = sl_bt_ht_temperature_measurement_indicate( app_connection, temperature, false); app_connection,蓝牙句柄 temperature温度值 false是摄氏度/true是华氏温度 在sl_bt_ht_temperature_measurement_indicate里进行了温度的数据封装操作 temperature_measurement_val_to_buf 把温度数据封装到五个字节的数据包里 第一个字节是温度类型 其余是温度值 uint32_t tmp_value = ((uint32_t)value & 0x00ffffffu) \ | ((uint32_t)(-3) << 24); buffer = fahrenheit ? TEMPERATURE_MEASUREMENT_FLAG_UNITS : 0; buffer = tmp_value & 0xff; 8) & 0xff; 16) & 0xff; 24) & 0xff; 要转回去 a= (data <<8)|data ; a=(a<<8)|data ; a=(a<<8)|data ; a=a&0xffffff; 用最底层sl_bt_gatt_server_send_indication发送 sc = sl_bt_gatt_server_send_indication( connection, gattdb_temperature_measurement, sizeof(buf), buf); connection句柄 gattdb_temperature_measurement gatt的属性 sizeof(buf),数据包大小 buf数据包 是一个指针类型const uint8_t* value 自定义GATT的service characteristic 并发送 进入blue配置工具 配置GATT数据库 如图 GATT数据库 再添加一个 接下 修改即可 在Health_Thermometer添加 void demo_init () { } void sl_bt_demo_on_event (sl_bt_msg_t *evt) { // Handle stack events switch header)) { case sl_bt_evt_system_boot_id: demo_init(); break ; case sl_bt_evt_connection_closed_id: data.evt_connection_closed.reason, data.evt_connection_closed.connection); break ; case sl_bt_evt_gatt_server_characteristic_status_id: if data.evt_gatt_server_characteristic_status.characteristic) { // client characteristic configuration changed by remote GATT client if ( sl_bt_gatt_server_client_config data.evt_gatt_server_characteristic_status.status_flags) { sl_bt_demo_indication_changed_cb( data.evt_gatt_server_characteristic_status.connection, data.evt_gatt_server_characteristic_status.client_config_flags); } // confirmation of indication received from remove GATT client else if ( sl_bt_gatt_server_confirmation data.evt_gatt_server_characteristic_status.status_flags) { sl_bt_demo_indication_confirmed_cb( data.evt_gatt_server_characteristic_status.connection); } else { } } break ; default : break ; } } App.c里添加 //demo code #include "gatt_db.h" static app_timer_t app_periodic_timer1; static uint8_t app_connection1 = 0; void demo_timer_cb () {printf("demo_timer_cb()"); uint8_t c=10; sl_bt_gatt_server_send_indication( app_connection1, gattdb_test,//要发送数据的characteristic 1, &c); } /**************************************************************************//** demo * Indication changed callback * * Called when indication of temperature measurement is enabled/disabled by * the client. *****************************************************************************/ void sl_bt_demo_indication_changed_cb (uint8_t connection, sl_bt_gatt_client_config_flag_t client_config) { app_connection1 = connection; // Indication or notification enabled. if ( sl_bt_gatt_disable != client_config) { // Start timer used for periodic indications. app_timer_start(&app_periodic_timer1, 1 * 1000, demo_timer_cb, NULL, true); // Send first indication. demo_timer_cb(); } // Indications disabled. else { // Stop timer used for periodic indications. ( void )app_timer_stop(&demo_timer_cb); } } void sl_bt_demo_connection_closed_cb (uint16_t reason, uint8_t connection) { ( void )reason; ( void )connection; sl_status_t sc; // Stop timer. sc = app_timer_stop(&app_periodic_timer1); } 并在 sl_bt_process_event添加sl_bt_demo_on_event 结果如图 主要参考 Silabs的蓝牙demo文档 UG103.14: Bluetooth® LE Fundamentals (silabs.com) QSG169: Bluetooth® Quick-Start Guide for SDK v3.x and Higher (silabs.com) ug434-bluetooth-c-soc-dev-guide-sdk-v3x.pdf (silabs.com) 博客园 夜行过客 专栏 https://www.cnblogs.com/yongdaimi/category/1543239.html 龙言飞语 https://zhuanlan.zhihu.com/p/346972549
  • 热度 3
    2024-1-15 10:46
    776 次阅读|
    0 个评论
    创建工程 选择 New project wizard 点击next 双击empty c project。 选择copy contents 点finish 进入software component,添加外设组件。 外设VCOM install swo usart Automatic Device Initialization Services: IO Stream: USARTInstall 创建一个vcom实例 Services :IO Stream: Retarget STDIOInstall 导入以下头文件到app.c #include #include #include "em_chip.h" #include "sl_iostream.h" #include "sl_iostream_init_instances.h" #include "sl_iostream_handles.h" const char str1[] = "IOstream USART example\r\n\r\n"; sl_iostream_write(sl_iostream_vcom_handle, str1, strlen (str1)); 这样就可以用l_iostream_write写入数据到串口 Printf 重定向 在software component搜索tiny printf tiny printf GPIOLed Platform:driver:led:Generic LED API 点击install 点击done创建一个实例 #include "sl_simple_led.h" 里是led的功能函数 sl_simple_led_init(&simple_led0_context);初始化 sl_simple_led_turn_on点灯 sl_simple_led_turn_off关灯 sl_simple_led_toggle反转 sl_simple_led_get_state获取灯的状态 typedef struct { GPIO_Port_TypeDef port; ///< LED port uint8_t pin; ///< LED pin sl_led_polarity_t polarity; ///< Initial state of LED } sl_simple_led_context_t;//LED初始化结构体 底层头文件 #include "em_gpio.h GPIO_PinOutClear() Set bits in DOUT register for a port to 0. GPIO_PortOutSet Set bits GPIO data out register to 1. GPIO_PortOutToggle Toggle pins in GPIO port data out register. GPIO_PinOutGet Get current setting for a pin in a GPIO port data out regisl_simple_led_context_t *led = context;ster. 初始化过程 sl_simple_led_context_t simple_led0_context = { .port = SL_SIMPLE_LED_LED0_PORT, .pin = SL_SIMPLE_LED_LED0_PIN, .polarity = SL_SIMPLE_LED_LED0_POLARITY, };初始化结构体 sl_simple_led_context_t *led = context; CMU_ClockEnable( cmuClock_GPIO , true);//时钟使能 port, pin, gpioModePushPull , polarity); 配置引脚 Button Platform:driver:led:Generic LED button API 创建一个button实例 void button_init () { CMU_ClockEnable( cmuClock_GPIO , true); GPIO_PinModeSet( gpioPortB , 2, gpioModeInput , 0); //初始化输入模式 //浮空输入 gpioModeInput , gpioModeInputPull,上来下拉由第四个参数决定 1上拉/0下拉 } GPIO_PinInGet( gpioPortB ,2)获取b2的输入电平 time sleeptimer service:time:sleeptimer Sleepimer驱动程序使用低频实时时钟外设提供软件定时器、延迟、计时和日期功能。睡眠定时器使用一个硬件定时器并创建多个软件定时器实例。睡眠定时器可用于创建与电源管理紧密集成的定时器。电源管理器需要精确的计时,以使所有时钟按时准备就绪,因此唤醒发生得更早一点,为系统在正确的时间做好准备。 sl_sleeptimer_init();//初始化睡眠定时器 sl_sleeptimer_timer_handle_t handle; sl_sleeptimer_start_periodic_timer(&handle,1000,timecallback,NULL,0,true);开启定时周期回调 void timecallback ()//回调函数 { printf("1"); printf("sl_simple_button_get_state %d\r\n",GPIO_PinInGet( gpioPortB ,2)); } Silicon lab的定时器有用了app_timer封装了一层sleeptime使用 用法一样只不过少了初始化步骤 static app_timer_t app_periodic_timer; sc = app_timer_start(&app_periodic_timer, SL_BT_HT_MEASUREMENT_INTERVAL_SEC * 1000, app_periodic_timer_cb, NULL, true);//开启定时器 app_periodic_timer_cb(&app_periodic_timer, NULL);//重写写定时回调函数 执行定时任务 temp platform:driver:tempdev 温度驱动器使用一些EFR32和EFM32设备上的EMU内部温度传感器测量温度。特定于应用程序的回调函数可以注册,并将在给定的温度阈值上调用。EMU内部温度传感器在EM0-EM4H中运行,能够在温度变化时唤醒核心。EMU温度传感器连续运行,每250毫秒进行一次测量。对于适用勘误表EMU_E201的设备,温度驱动器执行一种变通方法,根据测量的温度调整EMU设置。有关此勘误表解决方法的更多信息,请参阅应用说明AN1027。 导入 #include "tempdrv.h" TEMPDRV_Init(); printf("TEMPDRV_GetTemp %d\r\n",TEMPDRV_GetTemp());
  • 热度 2
    2024-1-12 11:30
    695 次阅读|
    0 个评论
    EFR32MG24开发板介绍及IDE使用
    板卡如图 板上的资源有 EFR32MG24无线SOC,Jlinlk调试器(可用作虚拟串口),两颗用户按键,两颗LED灯,板载天线。 片上资源有 包含:32个GPIO,其中20个GPOIO通过排座引出。1536kb的flash,256kb的ram。8通道dma控制器。一个可配置为UART/SPI/SmartCard (ISO 7816)/IrDA/I2S的通信接口。2个EUSART增强型的usart。2个支持SMBus的I2C接口。9个定时器包含2个32位定时器,3个16位定时器,1个24位的低功耗定时器,1个32位RTC定时器,一个32位极低功耗的定时器用于从能量模式唤醒,2个看门狗定时器。1个增强型ADC最高16位 76.9ksps,12位 1Msps采样率。2个模拟比较器。2个12位500 ksps采样率的DAC。内置温度传感器。支持jtag/swd调试。 基于ARM cm33内核,时钟72Mhz 开发工具介绍 EFR32支持MDK,IAR,Silicon IDE开发,其中官方例程只有IAR和Silicon IDE版本。Silicon IDE功能非常强大,首先IDE基于Eclipse开发的,内置芯片的软件包software component,可直接从IDE下载芯片的SDK以及无线分析工具。 开始界面 在debug adapters窗口会发现所连接的芯片。 点击INSTALL按钮 选择install by connecting device 后会自动下载芯片支持的SDK。包括蓝牙SDK和外设库文件,BLE网络配置器,网络分析仪用于抓包,BLE GATT 配置器,GNU ARM工具链等。 当在welcome界面点击start后会进入如下界面。 包含四部分 Overview Example Document Component tools Overview 介绍了所连接调试器类型,mcu类型,sdk版本。 芯片相关的文档。 开发板下相关的文档 exampe 1.包含无线连接的例程 2.没有无线连接的例程 3.组网协议相关的例程 zigbe,buletooth mesh等 4.用户开发用的demo例程 5.有关低功耗,蓝牙通信解决方案的例程 3.document 1.芯片相关:数据手册,应用指南,电气规范,快速开始等 2.技术相关:蓝牙,zigbee组网协议,bootloader等 4.component tools 提供网络强度,数据抓包,flash下载,能耗分析等 工程模板导入及编译下载 点击create new project,在example里搜索blink bare metal。无通信的Led的例程。点击next 到如图 填写合适的工程名称,选择一个工程创建位置,最后一个选择以怎样的方式使用SDK的库文件。 选择copy所需的库文件以及所需的文件到工程目录。 点击finish完成创建。 右击工程目录,或者 菜单栏 的project Build project 生成可执行文件,bin,hex,elf文件等。 点击RUN AS下载程序 也可使用simplicity commder下载程序 在selec kit选择440322824 选择flash选项 Browse选择bin文件,点击flash即可。重启开发板 Hex文件在C:\Users\18739\SimplicityStudio\v5_workspace\blink_baremetal\GNU ARM v12.2.1 - Default\blink_baremetal\GNU ARM v12.2.1 - Default下 结果如图 LED闪烁
相关资源