58、iOS 手势识别:从基础到高级应用

iOS 手势识别:从基础到高级应用

1. 手动检测滑动手势

在开发中,我们可以通过代码手动检测滑动手势。以下是一段检测水平和垂直滑动的代码示例:

if (deltaX >=kMinimumGestureLength && deltaY <= kMaximumVariance) {
    self.label.text = @"Horizontal swipe detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.label.text = @""; });
} else if (deltaY >=kMinimumGestureLength &&
           deltaX <= kMaximumVariance){
    self.label.text = @"Vertical swipe detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.label.text = @""; });
}

操作步骤如下:
1. 编写上述代码来判断滑动方向。
2. 编译并运行应用程序。
3. 如果点击和拖动没有可见结果,耐心尝试垂直或水平拖动,直到掌握滑动操作。

2. 自动手势识别

iOS 提供了 UIGestureRecognizer 类来简化手势识别的过程。以滑动手势为例,我们可以使用 UISwipeGestureRecognizer 来实现。

2.1 修改 Swipes 应用

步骤如下:
1. 复制 Swipes 项目文件夹。
2. 打开 ViewController.m ,删除 touchesBegan:withEvent: touchesMoved:withEvent: 方法。
3. 添加以下新方法:

- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer {
    self.label.text = @"Horizontal swipe detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                            dispatch_get_main_queue(),
                           ^{ self.label.text = @""; });
}

- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer {
    self.label.text = @"Vertical swipe detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                            dispatch_get_main_queue(),
                            ^{ self.label.text = @""; });
}
  1. 修改 viewDidLoad 方法:
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc]
                         initWithTarget:self action:@selector(reportVerticalSwipe:)];
    vertical.direction = UISwipeGestureRecognizerDirectionUp |
                         UISwipeGestureRecognizerDirectionDown;
    [self.view addGestureRecognizer:vertical];

    UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc]
                           initWithTarget:self action:@selector(reportHorizontalSwipe:)];
    horizontal.direction = UISwipeGestureRecognizerDirectionLeft |
                           UISwipeGestureRecognizerDirectionRight;
    [self.view addGestureRecognizer:horizontal];
}
  1. 可以进一步删除 ViewController.m gestureStartPoint 属性的声明和两个常量值。
  2. 构建并运行应用程序,测试新的手势识别器。

2.2 两种方法对比

方法 代码复杂度 理解难度 扩展性
手动检测 较高 较难 较差
手势识别器 较低 较易 较好

使用手势识别器的代码更易于理解和编写,而且 Apple 的手势识别系统具有可扩展性。

3. 实现多手指滑动

在 Swipes 应用中,之前只处理了单手指滑动。现在我们可以使用手势识别器来处理多手指滑动。

3.1 修改 Swipes 项目

步骤如下:
1. 再次复制 Swipes 项目文件夹。
2. 编辑 ViewController.m ,修改 viewDidLoad 方法:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the
    // view, typically from a nib.
    for (NSUInteger touchCount = 1; touchCount <= 5; touchCount++) {
        UISwipeGestureRecognizer *vertical;
        vertical = [[UISwipeGestureRecognizer alloc]
                    initWithTarget:self action:@selector(reportVerticalSwipe:)];
        vertical.direction = UISwipeGestureRecognizerDirectionUp |
                             UISwipeGestureRecognizerDirectionDown;
        vertical.numberOfTouchesRequired = touchCount;
        [self.view addGestureRecognizer:vertical];

        UISwipeGestureRecognizer *horizontal;
        horizontal = [[UISwipeGestureRecognizer alloc]
                     initWithTarget:self action:@selector(reportHorizontalSwipe:)];
        horizontal.direction = UISwipeGestureRecognizerDirectionLeft |
                               UISwipeGestureRecognizerDirectionRight;
        horizontal.numberOfTouchesRequired = touchCount;
        [self.view addGestureRecognizer:horizontal];
    }
}
  1. 添加 descriptionForTouchCount: 方法:
- (NSString *)descriptionForTouchCount:(NSUInteger)touchCount {
    switch (touchCount) {
        case 1:
            return @"Single";
        case 2:
            return @"Double";
        case 3:
            return @"Triple";
        case 4:
            return @"Quadruple";
        case 5:
            return @"Quintuple";
        default:
            return @"";
    }
}
  1. 修改两个滑动报告方法:
- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer {
    self.label.text = @"Horizontal swipe detected";
    self.label.text = [NSString stringWithFormat:@"%@ Horizontal swipe detected",
                      [self descriptionForTouchCount:[recognizer numberOfTouches]]];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.label.text = @""; });
}

- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer {
    self.label.text = @"Vertical swipe detected";
    self.label.text = [NSString stringWithFormat:@"%@ Vertical swipe detected",
                      [self descriptionForTouchCount:[recognizer numberOfTouches]]];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.label.text = @""; });
}
  1. 编译并运行应用程序,尝试触发不同手指数量的滑动。

3.2 注意事项

  • 手指之间不要太靠近,否则可能会被识别为单手指触摸。
  • 不建议在重要手势中使用四指或五指滑动,因为很多人手指太大,难以有效执行这些滑动。
  • 在 iPad 上,一些四指和五指手势在系统级别默认开启,用于切换应用和返回主屏幕,可以在设置中关闭,但最好避免在自己的应用中使用这些手势。

4. 检测多次点击

在处理多次点击时,需要考虑不同点击次数触发不同操作的情况。

4.1 问题分析

当用户进行多次点击时,会收到多个点击通知。例如,用户进行三次点击,会依次收到单次点击、双次点击和三次点击的通知。如果要对双次点击和三次点击执行不同操作,需要解决通知冲突的问题。

4.2 解决方案

Apple 提供了一种机制,让多个手势识别器可以协同工作。通过设置一个手势识别器的触发条件,即只有在其他手势识别器无法触发时才触发自己的方法。

4.3 示例代码

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]
                                      initWithTarget:self
                                      action:@selector(doSingleTap)];
singleTap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:singleTap];

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]
                                      initWithTarget:self
                                      action:@selector(doDoubleTap)];
doubleTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:doubleTap];

[singleTap requireGestureRecognizerToFail:doubleTap];

4.4 创建 TapTaps 项目

步骤如下:
1. 在 Xcode 中创建一个新的 Single View Application 项目,命名为 TapTaps,选择 Universal 设备。
2. 打开 ViewController.m ,修改类接口:

#import "ViewController.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *singleLabel;
@property (weak, nonatomic) IBOutlet UILabel *doubleLabel;
@property (weak, nonatomic) IBOutlet UILabel *tripleLabel;
@property (weak, nonatomic) IBOutlet UILabel *quadrupleLabel;

@end
  1. 编辑 Main.storyboard ,添加四个标签,设置文本对齐方式和自动布局约束,并将标签连接到相应的属性。
  2. 修改 ViewController.m 中的代码:
@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UITapGestureRecognizer *singleTap =
              [[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(singleTap)];
    singleTap.numberOfTapsRequired = 1;
    singleTap.numberOfTouchesRequired = 1;
    [self.view addGestureRecognizer:singleTap];

    UITapGestureRecognizer *doubleTap =
              [[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(doubleTap)];
    doubleTap.numberOfTapsRequired = 2;
    doubleTap.numberOfTouchesRequired = 1;
    [self.view addGestureRecognizer:doubleTap];
    [singleTap requireGestureRecognizerToFail:doubleTap];

    UITapGestureRecognizer *tripleTap =
             [[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(tripleTap)];
    tripleTap.numberOfTapsRequired = 3;
    tripleTap.numberOfTouchesRequired = 1;
    [self.view addGestureRecognizer:tripleTap];
    [doubleTap requireGestureRecognizerToFail:tripleTap];

    UITapGestureRecognizer *quadrupleTap =
            [[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(quadrupleTap)];
    quadrupleTap.numberOfTapsRequired = 4;
    quadrupleTap.numberOfTouchesRequired = 1;
    [self.view addGestureRecognizer:quadrupleTap];
    [tripleTap requireGestureRecognizerToFail:quadrupleTap];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)singleTap {
    self.singleLabel.text = @"Single Tap Detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.singleLabel.text = @""; });
}

- (void)doubleTap {
    self.doubleLabel.text = @"Double Tap Detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.doubleLabel.text = @""; });
}

- (void)tripleTap {
    self.tripleLabel.text = @"Triple Tap Detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.tripleLabel.text = @""; });
}

- (void)quadrupleTap {
    self.quadrupleLabel.text = @"Quadruple Tap Detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
                   dispatch_get_main_queue(),
                   ^{ self.quadrupleLabel.text = @""; });
}

@end

4.5 代码解释

viewDidLoad 方法中,我们创建了四个点击手势识别器,分别处理单次点击、双次点击、三次点击和四次点击。通过设置 requireGestureRecognizerToFail 方法,确保每个手势识别器在合适的时机触发。
编译并运行应用程序,无论进行单次、双次、三次还是四次点击,最终只会显示一个标签,约一秒半后标签会自动清除,可以再次尝试点击。

5. 检测捏合和旋转手势

捏合和旋转是常见的手势,分别使用 UIPinchGestureRecognizer UIRotationGestureRecognizer 进行检测。

5.1 创建 PinchMe 项目

步骤如下:
1. 在 Xcode 中创建一个新的 Single View Application 项目,命名为 PinchMe。
2. 将 yosemite - meadows.png 图片拖放到项目的 Images.xcassets 中。
3. 打开 ViewController.h ,修改代码:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIGestureRecognizerDelegate>

@end
  1. 打开 ViewController.m ,进行以下修改:
#import "ViewController.h"

@interface ViewController ()

@property (strong, nonatomic) UIImageView *imageView;

@end

@implementation ViewController
CGFloat scale, previousScale;
CGFloat rotation, previousRotation;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    previousScale = 1;

    UIImage *image = [UIImage imageNamed:@"yosemite-meadows"];
    self.imageView = [[UIImageView alloc] initWithImage:image];
    self.imageView.userInteractionEnabled = YES;
    self.imageView.center = self.view.center;
    [self.view addSubview:self.imageView];

    UIPinchGestureRecognizer *pinchGesture =
           [[UIPinchGestureRecognizer alloc]
                                    initWithTarget:self action:@selector(doPinch:)];
    pinchGesture.delegate = self;
    [self.imageView addGestureRecognizer:pinchGesture];

    UIRotationGestureRecognizer *rotationGesture =
           [[UIRotationGestureRecognizer alloc]
                                    initWithTarget:self action:@selector(doRotate:)];
    rotationGesture.delegate = self;
    [self.imageView addGestureRecognizer:rotationGesture];
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
                 shouldRecognizeSimultaneouslyWithGestureRecognizer:
                               (UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

- (void)transformImageView {
    CGAffineTransform t = CGAffineTransformMakeScale(scale * previousScale,
                                                     scale * previousScale);
    t = CGAffineTransformRotate(t, rotation + previousRotation);
    self.imageView.transform = t;
}

- (void)doPinch:(UIPinchGestureRecognizer *)gesture {
    scale = gesture.scale;
    [self transformImageView];
    if (gesture.state == UIGestureRecognizerStateEnded) {
        previousScale = scale * previousScale;
        scale = 1;
    }
}

- (void)doRotate:(UIRotationGestureRecognizer *)gesture {
    rotation = gesture.rotation;
    [self transformImageView];
    if (gesture.state == UIGestureRecognizerStateEnded) {
        previousRotation = rotation + previousRotation;
        rotation = 0;
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

5.2 代码解释

  • viewDidLoad 方法中,创建了一个 UIImageView 用于显示图片,并添加了捏合和旋转手势识别器。
  • gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 方法返回 YES ,允许捏合和旋转手势同时工作。
  • transformImageView 方法根据当前的缩放和旋转值更新图片视图的变换。
  • doPinch: doRotate: 方法分别处理捏合和旋转手势,在手势结束时更新之前的缩放和旋转值。

通过以上步骤,我们可以实现对捏合和旋转手势的检测,并根据手势对图片进行缩放和旋转操作。

6. 手势识别总结

6.1 不同手势识别器对比

手势类型 对应识别器类 特点
滑动 UISwipeGestureRecognizer 可配置单指或多指滑动,检测水平和垂直方向滑动
点击 UITapGestureRecognizer 可配置点击次数,通过设置依赖关系避免点击冲突
捏合 UIPinchGestureRecognizer 连续手势识别器,根据手指距离改变缩放比例
旋转 UIRotationGestureRecognizer 连续手势识别器,根据手指旋转角度改变旋转值

6.2 手势识别流程

graph LR
    A[用户进行手势操作] --> B{手势类型判断}
    B --> |滑动| C(UISwipeGestureRecognizer)
    B --> |点击| D(UITapGestureRecognizer)
    B --> |捏合| E(UIPinchGestureRecognizer)
    B --> |旋转| F(UIRotationGestureRecognizer)
    C --> G[触发对应滑动方法]
    D --> H[触发对应点击方法]
    E --> I[触发捏合方法,更新缩放值]
    F --> J[触发旋转方法,更新旋转值]

这个流程图展示了用户进行手势操作后,系统根据手势类型选择相应的手势识别器,并触发对应的处理方法。

6.3 开发建议

  • 选择合适的识别器 :根据实际需求选择合适的手势识别器,避免手动处理复杂的手势逻辑。
  • 处理冲突 :当存在多个手势识别器可能冲突时,使用 requireGestureRecognizerToFail 方法进行处理。
  • 考虑用户体验 :在设计手势时,要考虑用户的操作习惯和手指大小,避免使用过于复杂或难以执行的手势。

7. 实际应用案例分析

7.1 图片浏览应用

在图片浏览应用中,常见的手势有滑动切换图片、捏合缩放图片、旋转图片等。以下是一个简单的图片浏览应用的实现思路:
1. 滑动切换图片 :使用 UISwipeGestureRecognizer 检测水平滑动,根据滑动方向切换到上一张或下一张图片。

UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(showNextImage)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:leftSwipe];

UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(showPreviousImage)];
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:rightSwipe];
  1. 捏合缩放图片 :使用 UIPinchGestureRecognizer 检测捏合手势,根据缩放比例调整图片大小。
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
[self.imageView addGestureRecognizer:pinchGesture];

- (void)handlePinch:(UIPinchGestureRecognizer *)gesture {
    CGFloat scale = gesture.scale;
    self.imageView.transform = CGAffineTransformScale(self.imageView.transform, scale, scale);
    gesture.scale = 1;
}
  1. 旋转图片 :使用 UIRotationGestureRecognizer 检测旋转手势,根据旋转角度旋转图片。
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)];
[self.imageView addGestureRecognizer:rotationGesture];

- (void)handleRotation:(UIRotationGestureRecognizer *)gesture {
    CGFloat rotation = gesture.rotation;
    self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation);
    gesture.rotation = 0;
}

7.2 地图应用

在地图应用中,滑动可以移动地图视野,捏合可以缩放地图级别,双指旋转可以旋转地图方向。以下是一个简单的地图应用的实现思路:
1. 滑动移动地图 :使用 UIPanGestureRecognizer 检测滑动手势,根据滑动距离移动地图视野。

UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[self.mapView addGestureRecognizer:panGesture];

- (void)handlePan:(UIPanGestureRecognizer *)gesture {
    CGPoint translation = [gesture translationInView:self.mapView];
    [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(self.mapView.centerCoordinate.latitude - translation.y / 1000, self.mapView.centerCoordinate.longitude + translation.x / 1000)];
    [gesture setTranslation:CGPointZero inView:self.mapView];
}
  1. 捏合缩放地图 :使用 UIPinchGestureRecognizer 检测捏合手势,根据缩放比例调整地图级别。
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
[self.mapView addGestureRecognizer:pinchGesture];

- (void)handlePinch:(UIPinchGestureRecognizer *)gesture {
    CGFloat scale = gesture.scale;
    MKZoomScale currentZoomScale = self.mapView.zoomScale;
    self.mapView.zoomScale = currentZoomScale * scale;
    gesture.scale = 1;
}
  1. 旋转地图 :使用 UIRotationGestureRecognizer 检测旋转手势,根据旋转角度旋转地图方向。
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)];
[self.mapView addGestureRecognizer:rotationGesture];

- (void)handleRotation:(UIRotationGestureRecognizer *)gesture {
    CGFloat rotation = gesture.rotation;
    self.mapView.camera.heading += rotation * 180 / M_PI;
    gesture.rotation = 0;
}

通过以上案例可以看出,手势识别在实际应用中非常重要,可以大大提升用户体验。开发者可以根据不同的应用场景选择合适的手势识别器,并进行相应的处理。

8. 未来发展趋势

8.1 更复杂的手势支持

随着技术的发展,未来可能会支持更复杂的手势,如三指以上的复杂组合手势、动态手势等。这将为应用开发带来更多的创意和可能性。

8.2 与其他技术融合

手势识别可能会与虚拟现实(VR)、增强现实(AR)等技术融合,提供更加沉浸式的交互体验。例如,在 VR 应用中,用户可以通过手势进行物体的抓取、移动等操作。

8.3 智能化手势识别

未来的手势识别系统可能会更加智能化,能够根据用户的习惯和环境自动调整识别策略,提高识别的准确性和效率。

总之,手势识别技术在移动应用开发中具有重要的地位,并且有着广阔的发展前景。开发者需要不断学习和掌握新的手势识别技术,为用户提供更加优质的应用体验。

【博士论文复现】【阻抗建模、验证扫频法】光伏并网逆变器扫频与稳定性分析(包含锁相环电流环)(Simulink仿真实现)内容概要:本文档围绕“博士论文复现”主题,重点介绍了光伏并网逆变器的阻抗建模与扫频法稳定性分析,涵盖锁相环和电流环的Simulink仿真实现。文档旨在通过完整的仿真资源和代码帮助科研人员复现相关技术细节,提升对新能源并网系统动态特性和稳定机制的理解。此外,文档还提供了大量其他科研方向的复现资源,包括微电网优化、机器学习、路径规划、信号处理、电力系统分析等,配套MATLAB/Simulink代码与模型,服务于多领域科研需求。; 适合人群:具备一定电力电子、自动控制或新能源背景的研究生、博士生及科研人员,熟悉MATLAB/Simulink环境,有志于复现高水平论文成果并开展创新研究。; 使用场景及目标:①复现光伏并网逆变器的阻抗建模与扫频分析过程,掌握其稳定性判据与仿真方法;②借鉴提供的丰富案例资源,支撑博士论文或期刊论文的仿真实验部分;③结合团队提供的算法与模型,快速搭建实验平台,提升科研效率。; 阅读建议:建议按文档目录顺序浏览,优先下载并运行配套仿真文件,结合理论学习与代码调试加深理解;重点关注锁相环与电流环的建模细节,同时可拓展学习其他复现案例以拓宽研究视野。
内容概要:本文系统解析了嵌入式通信协议栈系列项目的实践路径,围绕通信原理与工程实现,阐述在资源受限的嵌入式环境中构建稳定、可扩展通信能力的方法。文章从通信基础模型出发,强调分层设计思想,涵盖物理层到应用层的职责划分,并依次讲解通信驱动、数据收发机制、帧格式解析、状态机控制、错误处理等核心技术环节。项目实践注重底层可靠性建设,如中断响应、缓冲区管理与数据校验,同时关注上层应用对接,确保协议栈支持设备配置、状态上报等实际业务。文中还突出性能优化与资源管理的重要性,指导开发者在内存与处理效率间取得平衡,并通过系统化测试手段(如异常模拟、压力测试)验证协议栈的健壮性。; 适合人群:具备嵌入式系统基础知识,有一定C语言和硬件接口开发经验,从事或希望深入物联网、工业控制等领域1-3年工作经验的工程师。; 使用场景及目标:①掌握嵌入式环境下通信协议栈的分层架构设计与实现方法;②理解状态机、数据封装、异常处理等关键技术在真实项目中的应用;③提升在资源受限条件下优化通信性能与稳定性的工程能力; 阅读建议:建议结合实际嵌入式平台动手实践,边学边调,重点关注各层接口定义与模块解耦设计,配合调试工具深入分析通信流程与异常行为,以全面提升系统级开发素养。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值