MAC桌面程序開發之 USB串口調試助手開發

本次主要講解,如何在Mac電腦上開發,如今流行的電腦桌面程序,因爲我們在做互聯網/智能化設備的時候,無疑或許會用到MAC來進行調試;

重點如下:

  1. 如何在MAC電腦上創建桌面程序;
  2. 在項目中添加usb協議庫。如:HID,ORSSerialPort;
  3. 項目內容主要分爲:串口名,波特率,開/關串口,發送數據,接收設備數據,上傳文件;
  4. 此文章用的USB協議是《ORSSerialPort》,目前也就基本是這個對接硬件設備,相互鏈接進行收發數據的。
  5. 邏輯:電腦監聽usb接口~是否有設備鏈接~一旦有鏈接就進行讀取名稱~設置波特率~打開串口~上傳固件文件(這塊就需要與硬件工程師對接協議了)~發送字節數據~接收設備數據;

該具備的硬件與軟件:

  1. MAC電腦一臺,鍵盤,鼠標;
  2. Xcode編譯器;
  3. 終端設備,開發板一塊,如:stm32;
  4. USB數據線一根;
  5. 準備好一個文件,有一個升級的功能;

一:創建桌面程序

1,打開xcode編譯器,選擇fiie-New-Probject-macos-app-next;
在這裏插入圖片描述
2,創建項目名稱了,這個自己定義了哦,下面的默認不要管。
在這裏插入圖片描述
3,桌面程序項目創建完成,這是我的總項目架構;
在這裏插入圖片描述
二:USB接口開發

1.上面就講了,用的ORSSerialPort協議,如果有不瞭解的,也可以網上看看這個協議。

#import <Cocoa/Cocoa.h>
#import "CustomProgress.h"
#import "MIDIManager.h"
#import "ORSSerialPort.h"

@class ORSSerialPortManager;

@interface ViewController : NSViewController <ORSSerialPortDelegate,MidiGetDataDelegate, NSUserNotificationCenterDelegate,NSTextViewDelegate,NSTableViewDelegate>
@property (weak) IBOutlet NSArrayController *DeviceArray;

@property (weak) IBOutlet NSButton *OpenOrClose;

@property (weak) IBOutlet NSTextField *StatusText;
@property (weak) IBOutlet NSTextField *PassageD;

@property (weak) IBOutlet NSTextField *TextNameH;

//@property (weak) IBOutlet NSTextField *RXCounter;
//@property (nonatomic, assign) long RXNumber;

@property (nonatomic, strong) NSData * sendData;

//@property (weak) IBOutlet NSTextField *TXCounter;
//@property (nonatomic, assign) long TXNumber;

@property (weak) IBOutlet NSTextField *filePathTF;
@property (weak) IBOutlet NSButton *OpenBut;
@property (weak) IBOutlet NSButton *UpdateBut;
@property (weak) IBOutlet CustomProgress *processView;

@property (unsafe_unretained) IBOutlet NSTextView *RXDataDisplayTextView;

@property (unsafe_unretained) IBOutlet NSTextView *TXDataDisplayTextView;
@property (weak) IBOutlet NSMatrix *stringType;
@property (weak) IBOutlet NSMatrix *stringType_TX;

@property (weak) IBOutlet NSTextField *TimeInternel;
@property (weak) IBOutlet NSTextField *countOfSend;
@property (weak) IBOutlet NSButton *SendButton;

@property (nonatomic, assign) BOOL isRXHexString;

@property (nonatomic, assign) BOOL isTXHexString;

@property (nonatomic, assign) BOOL isRXGBKString;
@property (nonatomic, assign) BOOL isTXGBKString;

@property (nonatomic, strong) ORSSerialPortManager *serialPortManager;
@property (nonatomic, strong) ORSSerialPort *serialPort;//ORSSerialPort
@property (nonatomic, strong) NSArray *availableBaudRates;
@property (weak) IBOutlet NSTableView *tableviewFordevices;

@property (nonatomic,strong) NSSavePanel*  panel;
@property (nonatomic, assign) BOOL isLoopSend;
@property (nonatomic, assign) BOOL isWorkInSend;
@property (nonatomic, assign) BOOL isOnlyDisplayRxData;
@property (assign,nonatomic) int sendCount;
@property (assign,nonatomic) NSTimer *timer;
@property (nonatomic, strong) NSWindow *MyMoneyWindow;
@end

2,設置打開串口的代碼

- (IBAction)openComPort:(id)sender {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        self.serialPort.isOpen ? [self.serialPort close] : [self.serialPort open];
    });
}

3.發送數據

//如果串口沒打開,不能發生數據
-(void)sendDataWithPort{
    
    if (!self.serialPort.isOpen) {
        self.StatusText.stringValue = @"The serial port is not open and cannot send data.";
        return;
    }

        if(_sendData){
               if([self.serialPort sendData:_sendData]){
                   self.StatusText.stringValue = @"發送HEX數據成功";
                  // self.TXCounter.stringValue = [NSString stringWithFormat:@"%@",_sendData];
               }else{
                   self.StatusText.stringValue = @"發送HEX數據失敗";
                   return;
               }
           }

4.打開串口,關閉串口;

#pragma mark - ORSSerialPortDelegate Methods

- (void)serialPortWasOpened:(ORSSerialPort *)serialPort
{
    self.OpenOrClose.title = @"Close the serial port";
    self.StatusText.stringValue = @"Serial port is open";
}

- (void)serialPortWasClosed:(ORSSerialPort *)serialPort
{
    self.OpenOrClose.title = @"Open serial port";
    self.StatusText.stringValue = @"Serial port is closed";
}

5.程序啓動的時候,讀取到usb插入的設備;

#pragma mark - Properties

- (void)setSerialPort:(ORSSerialPort *)port
{
    if (port != _serialPort)
    {
//      [_serialPort close];
        _serialPort.delegate = nil;
        _serialPort = port;
        _serialPort.delegate = self;
        self.OpenOrClose.title = self.serialPort.isOpen ? @"Close the serial port" : @"Open serial port";
        NSString *tmp=[NSString stringWithFormat:@"%@%@",_serialPort.name,(self.serialPort.isOpen ? @"Serial port is open" : @"Serial port is closed")];
        self.StatusText.stringValue = tmp;
    }
}

6,點擊上傳的按鈕

- (IBAction)GDeviceFile:(NSButton *)sender {
    NSLog(@"我選擇了 : OpenBut");
    [self openFinder];
}

- (void)openFinder{
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    
    [panel setCanChooseFiles:YES];  //是否能選擇文件file
    
    [panel setCanChooseDirectories:YES];  //是否能打開文件夾
    
    [panel setAllowsMultipleSelection:NO];  //是否允許多選file
    
    NSInteger finded = [panel runModal];   //獲取panel的響應
    
    if (finded == NSModalResponseOK) {
        
        for (NSURL *url in [panel URLs]) {
            
            NSLog(@"文件路徑--->%@",url);
            _filePathTF.stringValue = [NSString stringWithFormat:@"%@",url];
            self.TextNameH.stringValue = [NSString stringWithFormat:@"%@",url];
            //同時這裏可以處理你要做的事情 do something
            
            // 獲取文件內容
            NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingFromURL:url error:nil];
            _sendData = [fileHandle readDataToEndOfFile];
            NSLog(@"內容 ==  %@",_sendData);
            
        }
    }
}

7,當設備(開發版)斷開的時候,監測;

- (void)postUserNotificationForDisconnectedPorts:(NSArray *)disconnectedPorts
{
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_7)
    if (!NSClassFromString(@"NSUserNotificationCenter")) return;
    
    NSUserNotificationCenter *unc = [NSUserNotificationCenter defaultUserNotificationCenter];
    for (ORSSerialPort *port in disconnectedPorts)
    {
        NSUserNotification *userNote = [[NSUserNotification alloc] init];
        userNote.title = NSLocalizedString(@"偵測到串口線斷開", @"偵測到串口線斷開");
        NSString *informativeTextFormat = NSLocalizedString(@"串口設備 %@ 已從你的 Mac電腦斷開物理連接.", @"Serial port disconnected user notification informative text");
        userNote.informativeText = [NSString stringWithFormat:informativeTextFormat, port.name];
        userNote.soundName = nil;
        [unc deliverNotification:userNote];
    }
#endif
}

8,當設備(開發版)重鏈接的時候,監測;

- (void)postUserNotificationForConnectedPorts:(NSArray *)connectedPorts
{
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_7)
    if (!NSClassFromString(@"NSUserNotificationCenter")) return;
    
    NSUserNotificationCenter *unc = [NSUserNotificationCenter defaultUserNotificationCenter];
    for (ORSSerialPort *port in connectedPorts)
    {
        NSUserNotification *userNote = [[NSUserNotification alloc] init];
        userNote.title = NSLocalizedString(@"偵測到串口線連接", @"偵測到串口線連接");
        NSString *informativeTextFormat = NSLocalizedString(@"串口設備 %@ 已經連接到你的 Mac電腦.", @"Serial port connected user notification informative text");
        userNote.informativeText = [NSString stringWithFormat:informativeTextFormat, port.name];
        userNote.soundName = nil;
        [unc deliverNotification:userNote];
    }
#endif
}

9.把核心的代碼以上闡述了,點擊運行,看圖:
在這裏插入圖片描述
在這裏插入圖片描述
10.把寫好的桌面程序,打包成dmg,可以參考此文章:打包項目的鏈接

此文章先描述到此爲止了,希望能幫助到更多的看官初學者,如果有任何疑問可以留言,相互學習,謝謝,一起努力,下期見~~

源碼:

本項目的Demo,詳細的源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章