基于MAC OSX的串口助手源代码讲解(上)
来源:互联网 发布:python gui wxpython 编辑:程序博客网 时间:2024/05/24 02:20
网上对于mac的资料相对于windows和linux来比杯水车薪,博主在大学是从单片机学到了linux的应用开发,刚刚工作,主要方向是mac系统上的应用开发。博主是菜鸡一枚,但是愿意分享我写的代码,有大神来交流我很是欢迎。话不多说,先说一些基础的东西。首先mac osx和linux都属于从unix系统演变而来的,那么博主当时学习linux的时候看的书是《UNIX环境高级编程》,那么这里隐含的一个意思就是,书里面的大部分posix接口都是可以用的,最简单的open read write也是可以用的,并且OC里面的有的开源串口库的底层写函数也是用的write,由此可见,大部分的OC库里面也大量的封装了这些接口。底层部分不难实现,只是对于串口的一些配置,这部分的代码,我直接用的网上的现成代码,以前在linux写过,这里懒了就直接copy了。那么我先展示一下我在XCODE写串口助手的文件架构。![文件架构](http://img.blog.csdn.net/20170925184816913?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzMzMjQ4Nzg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)在有界面的编程世界中,MVC模式是流行的,也就是说,界面部分只负责处理控件。也就是MVC里的V,也就是view。而真正的难点在于contreller部分。这部分是负责界面控件与你底层数据结构之间的通讯。所以我的文件架构,就是底层的数据结构放在support文件里,而appdelete部分是界面部分的处理。前面也说了我底层代码这一部分是基于网上的代码改的,由于第一天发博客不知道怎么引用,所以这里跟原创道个歉。代码如下:
//// SeriportSetting.h// SerialPort//// Created by gdlocal on 19/09/2017.// Copyright © 2017 yang. All rights reserved.//#import <Foundation/Foundation.h>#import <stdio.h> /*标准输入输出定义*/#import <stdlib.h> /*标准函数库定义*/#import <unistd.h> /*Unix 标准函数定义*/#import <sys/types.h>#import <sys/stat.h>#import "string.h"#import <fcntl.h> /*文件控制定义*/#import <termios.h> /*PPSIX 终端控制定义*/#import <errno.h> /*错误号定义*/@interface SeriportSetting : NSObject{@public int SerialPort_fd; NSString*DevName; int speed; int databits; int stopbits; char parity;}int OpenDev(char *DevName);void set_speed(int fd, int speed);int set_Parity(int SerialPort_fd,int databits,int stopbits,int parity);@end上面这部分代码我用的是OC与C的混合,定义了SeriportSetting类其实就是串口的底层函数封装。 //// SeriportSetting.m// SerialPort//// Created by gdlocal on 19/09/2017.// Copyright © 2017 yang. All rights reserved.//#import "SeriportSetting.h"//#define FALSE -1//#define TRUE 0int SerialPort_fd;@implementation SeriportSetting-(id)init{ self=[super init]; if(self) { } return self;}int OpenDev(char *DevName){ SerialPort_fd = open(DevName, O_RDWR | O_NOCTTY ); //| O_NOCTTY | O_NDELAY if (-1 == SerialPort_fd) { perror("Can't Open Serial Port"); return -1; } else return SerialPort_fd;}int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };void set_speed(int fd, int speed){ int i; int status; struct termios Opt; tcgetattr(SerialPort_fd, &Opt); for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr[i]); cfsetospeed(&Opt, speed_arr[i]); status = tcsetattr(SerialPort_fd, TCSANOW, &Opt); if (status != 0) { perror("tcsetattr fd1"); return; } tcflush(SerialPort_fd,TCIOFLUSH); } }}int set_Parity(int SerialPort_fd,int databits,int stopbits,int parity){ struct termios options; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ options.c_oflag &= ~OPOST; /*Output*/ if ( tcgetattr(SerialPort_fd,&options) != 0) { perror("SetupSerial 1"); return 0; } options.c_cflag &= ~CSIZE; switch (databits) /*设置数据位数*/ { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: // fprintf(stderr,"Unsupported data size/n"); return 0; } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB;break; default: //fprintf(stderr,"Unsupported parity/n"); return 0; } /* 设置停止位*/ switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: // fprintf(stderr,"Unsupported stop bits/n"); return 0; } /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK; tcflush(SerialPort_fd,TCIFLUSH); options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(SerialPort_fd,TCSANOW,&options) != 0) { perror("SetupSerial 3"); return 0; } return 1;}@end.m文件在OC里的意思是OC与C的混合文件,由于OC是完全兼容C的,所以熟悉C的朋友可以很快的上手。底层这部分代码主要是设置波特率,数据位,停止位,奇偶校验位。以及串口的打开操作,这部分只要是懂linux得朋友基本都能看懂,网上关于这部分的代码也是非常之多的。那么底层文件写完之后最主要的部分来了,就是界面部分。那么我先把我的xib文件的界面布局用图片表示出来。![界面布局](http://img.blog.csdn.net/20170925192849790?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzMzMjQ4Nzg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 介绍完界面布局,我们重点来讲解一下界面是如何实现的。//// AppDelegate.h// SerialPort//// Created by gdlocal on 19/09/2017.// Copyright © 2017 yang. All rights reserved.//#import <Cocoa/Cocoa.h>#import "SeriportSetting.h"#import <CoreLib/SerialportEx.h>@interface AppDelegate : NSObject<NSApplicationDelegate> IBOutlet NSComboBox * Stopbits; IBOutlet NSComboBox * Databits; IBOutlet NSComboBox * Burrate; IBOutlet NSButton * Check; IBOutlet NSButton *Open; IBOutlet NSComboBox * Device; IBOutlet NSButton *Close; IBOutlet NSButton *Send; IBOutlet NSTextField * Sendbuffer; IBOutlet NSButton *Add; IBOutlet NSButton *RepelyReceive; IBOutlet NSTextView *My_textView; IBOutlet NSComboBox *AddComBox; IBOutlet NSButton *add; NSMutableDictionary *dicConfiguration; SeriportSetting *My_Com; NSMutableDictionary *dic; SerialportEx* My_Scom;}-(IBAction)SetStopbits:(id)sender;-(IBAction)SetBuratte:(id)sender;-(IBAction)Close:(id)sender;-(IBAction)Send:(id)sender;-(IBAction)RepelyReceive:(id)sender;-(void)My_textView;-(IBAction)Open:(id)sender;-(IBAction)Setdatabit:(id)sender;-(IBAction)add:(id)sender;@end
网上串口助手的界面布局有很多,可以看出在所有的界面之中,波特率,停止位,数据位,校验位大多数都是以选择形式来提供的,所以这几个的控件我选的combox控件。开始,关闭,发送,加末尾换行符这些控件我选择了按钮,如果各位看官想直接COPY我代码去自己试试的时候一定要把 SerialportEx* My_Scom注释掉,这部分涉及的功能可以先不写。用的是闭源的库。NSTextField控件表示得是文本编辑区,发送功能可以用这个控件,但是接收就不可以用了,因为一般的串口助手在接收的时候是要显示所有你收到的数据的,如果你再用NSTextField控件的话,你会发现在你收到第二次数据的时候,就会把第一次的数据覆盖了,但是OC的控件是丰富的。 NSTextView控件完美的解决了这个问题。以后会讲。至于上面h文件的方法部分,都是设置以及action,方法名字也都是见名知意。所以就不多说了。下面来看实现的m文件。
#import "AppDelegate.h"#import "SeriportSetting.h"NSInteger addstate=0;@interface AppDelegate ()@property (weak) IBOutlet NSWindow *window;@end@implementation AppDelegate-(instancetype)init{ self=[super init]; if(self) { My_Com = [[SeriportSetting alloc]init]; dicConfiguration=[[NSMutableDictionary alloc]init]; My_Scom = [[SerialportEx alloc]init]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; } return self;}- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{}- (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application}-(IBAction)SetStopbits:(id)sender{ NSInteger stopbits = [Stopbits intValue]; My_Com->stopbits = stopbits;}-(IBAction)Setdatabit:(id)sender{ NSInteger databits = [Databits intValue]; My_Com->databits=databits;}-(IBAction)SetBuratte:(id)sender{ NSInteger burrate = [Burrate intValue]; My_Com->speed =burrate ;}-(void)threadDemo{ ssize_t nread; char buffer[1024]; BOOL notstop=true; while (notstop) { memset(buffer, 0, sizeof(buffer)); nread = read(My_Com->SerialPort_fd, buffer, 1024); if (nread>0) { NSString * str = [NSString stringWithUTF8String:buffer]; [self performSelectorOnMainThread: @selector(view:) withObject:str waitUntilDone:NO]; } [NSThread sleepForTimeInterval:0.01]; }}-(IBAction)Open:(id)sender{ My_Com->DevName=[Device stringValue]; if([My_Com->DevName length]==0) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:[NSString stringWithUTF8String:"Please Input your Seriport Name"]]; [alert setInformativeText:[NSString stringWithFormat:@"name is nil"]]; [alert setAlertStyle:NSAlertStyleWarning]; [alert runModal]; return; } My_Com->SerialPort_fd=OpenDev([My_Com->DevName UTF8String]); if(My_Com->SerialPort_fd==-1) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:[NSString stringWithUTF8String:"Open Serial error"]]; [alert setInformativeText:[NSString stringWithFormat:@"Unkown error"]]; [alert setAlertStyle:NSAlertStyleWarning]; [alert runModal]; return; } My_Com->parity='o'; set_speed(My_Com->SerialPort_fd, My_Com->speed); set_Parity(My_Com->SerialPort_fd,My_Com->databits,My_Com->stopbits,My_Com->parity); NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadDemo) object:nil]; [thread start];}-(IBAction)Send:(id)sender{ NSString *str=[Sendbuffer stringValue]; if([str length]==0) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:[NSString stringWithUTF8String:"Please Input "]]; [alert setInformativeText:[NSString stringWithFormat:@"Unkown error"]]; [alert setAlertStyle:NSAlertStyleWarning]; [alert runModal]; return; } if(addstate==1) { if([[AddComBox stringValue] isEqualToString:@"\\n"]) { NSString *str1=[str stringByAppendingString:@"\n"]; NSData* data = [str1 dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger dataLen = [data length]; const char *dataBytes = (const char*)[data bytes]; write(My_Com->SerialPort_fd, dataBytes, dataLen); } else if ([[AddComBox stringValue] isEqualToString:@"\\r\\n"]) { NSString *str1=[str stringByAppendingString:@"\r\n"]; NSData* data = [str1 dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger dataLen = [data length]; const char *dataBytes = (const char*)[data bytes]; write(My_Com->SerialPort_fd, dataBytes, dataLen); } else if ([[AddComBox stringValue] isEqualToString:@"\\r"]) { NSString *str1=[str stringByAppendingString:@"\r"]; NSData* data = [str1 dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger dataLen = [data length]; const char *dataBytes = (const char*)[data bytes]; write(My_Com->SerialPort_fd, dataBytes, dataLen); } else{ NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger dataLen = [data length]; const char *dataBytes = (const char*)[data bytes]; write(My_Com->SerialPort_fd, dataBytes, dataLen); } }}-(IBAction)Close:(id)sender{ int fd=close(My_Com->SerialPort_fd); if(fd==-1) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:[NSString stringWithUTF8String:"Close error "]]; [alert setInformativeText:[NSString stringWithFormat:@"Unkown error"]]; [alert setAlertStyle:NSAlertStyleWarning]; [alert runModal]; return; }}-(IBAction)add:(id)sender{ if([sender state]) { addstate=1; }}-(IBAction)Scanf:(id)sender{ [Device removeAllItems] ; NSEnumerator *enumerator = [AMSerialPortList portEnumerator]; AMSerialPort *aPort; while (aPort = [enumerator nextObject]) { [Device addItemWithObjectValue:[aPort bsdPath]]; } return ;}-(void)view:(NSString*)str{ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy/MM/dd HH:mm:ss.SSS : "]; NSUInteger length = 0; NSAttributedString *theString; NSRange theRange; theString = [[NSAttributedString alloc] initWithString:str]; [[My_textView textStorage] appendAttributedString: theString]; length = [[My_textView textStorage] length]; theRange = NSMakeRange(length, 0); [My_textView scrollRangeToVisible:theRange];}@end
界面部分的代码明天再讲,今天有点累了。谢谢各位看官!
阅读全文
1 0
- 基于MAC OSX的串口助手源代码讲解(上)
- Mac串口助手源代码详解(下)
- 基于CSerialPort修改类的串口调试助手源代码(支持中文、自动保存等)
- 基于CSerialPort修改类的串口调试助手源代码(支持中文、自动保存等)
- 基于CSerialPort修改类的串口调试助手源代码(支持中文、自动保存等)
- Mac OSX上的python
- Mac OSX上的python
- 基于QT4的linux串口助手
- mac osx上有趣的工具
- 基于AT89C52和串口通信助手的串口通信
- 串口调试助手(MSCOMM)源代码
- VB 串口调试助手源代码
- 串口调试助手---VB源代码
- 【嵌入式-qt】 发个自己写的 BCOM串口调试助手(附源代码)
- 基于API函数的串口通信(方法讲解)
- 打造最漂亮的串口调试助手(基于WPF + .NET C# VS2013)附源码!
- 打造最漂亮的串口调试助手(基于WPF + .NET C# VS2013)附源码!
- 基于wince WEB技术的串口调试助手
- 派生类的构造方法以及修饰符的作用
- 谈谈开源(一)
- 线性表(C++)
- java算法之选择排序
- PAT 乙级练习题1018. 锤子剪刀布 (20)
- 基于MAC OSX的串口助手源代码讲解(上)
- spring boot之统一错误异常处理
- MongoDB学习笔记之 第4章 MongoDB整合Spring
- spring boot整合mybatis
- sizeof与strlen的区别
- 算法竞赛入门经典第3章习题
- php中的json_encode()和json_decode()编码与反编码
- JZOJsenior3484.【NOIP2013模拟联考10】密码(substring)
- MINI2440裸机实验之SDRAM