一种简便获取iPhone IMEI 的方法

 

使用CoreTelephony库,它是一个公开的framework,但很多API没有出现在文档中

iPhone私有API跟电话相关的CoreTelephony 里面提到了很多API, 其中有些可能跟电话录音有关系.

其中 _CTServerConnectionCopyMobileIdentity 就是用来获取IMEI的

#import

struct CTServerConnection
{
int a;
int b;
CFMachPortRef myport;
int c;
int d;
int e;
int f;
int g;
int h;
int i;
};

struct CTResult
{
int flag;
int a;
};

struct CTServerConnection * _CTServerConnectionCreate(CFAllocatorRef, void *, int *);

void _CTServerConnectionCopyMobileIdentity(struct CTResult *, struct CTServerConnection *, NSString **);
保存为 CoreTelephony.h

#import "CoreTelephony.h"

struct CTServerConnection *sc=NULL;
struct CTResult result;

void callback() { }

int main()
{
sc = _CTServerConnectionCreate(kCFAllocatorDefault, callback, NULL);

NSString *imei;
_CTServerConnectionCopyMobileIdentity(&result, sc, &imei);

NSLog (@"zhiwei's IMEI is %@", imei);

return 0;
}

IMSI

// 需要 CoreTelephony framework
// 在文件开头加入
extern NSString* CTSIMSupportCopyMobileSubscriberIdentity();

+ (NSString*) getDeviceIMSI {
    return CTSIMSupportCopyMobileSubscriberIdentity();
}

 

本机电话号码

// 需要 CoreTelephony framework
// 在文件开头加入
extern NSString* CTSettingCopyMyPhoneNumber();

+ (NSString*) getPhoneCodeByCT {
    return CTSettingCopyMyPhoneNumber();
}

 

本文转自:http://blog.csdn.net/kingkong1024/article/details/8363726

获得通讯录中联系人的所有属性

ABAddressBookRef addressBook = ABAddressBookCreate();

    CFArrayRef results = ABAddressBookCopyArrayOfAllPeople(addressBook);

    for(int i = 0; i < CFArrayGetCount(results); i++)
    {
        ABRecordRef person = CFArrayGetValueAtIndex(results, i);
        //读取firstname
        NSString *personName = (NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
        if(personName != nil)
            textView.text = [textView.text stringByAppendingFormat:@"\n姓名:%@\n",personName];
        //读取lastname
        NSString *lastname = (NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
        if(lastname != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",lastname];
        //读取middlename
        NSString *middlename = (NSString*)ABRecordCopyValue(person, kABPersonMiddleNameProperty);
        if(middlename != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",middlename];
        //读取prefix前缀
        NSString *prefix = (NSString*)ABRecordCopyValue(person, kABPersonPrefixProperty);
        if(prefix != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",prefix];
        //读取suffix后缀
        NSString *suffix = (NSString*)ABRecordCopyValue(person, kABPersonSuffixProperty);
        if(suffix != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",suffix];
        //读取nickname呢称
        NSString *nickname = (NSString*)ABRecordCopyValue(person, kABPersonNicknameProperty);
        if(nickname != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",nickname];
        //读取firstname拼音音标
        NSString *firstnamePhonetic = (NSString*)ABRecordCopyValue(person, kABPersonFirstNamePhoneticProperty);
        if(firstnamePhonetic != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",firstnamePhonetic];
        //读取lastname拼音音标
        NSString *lastnamePhonetic = (NSString*)ABRecordCopyValue(person, kABPersonLastNamePhoneticProperty);
        if(lastnamePhonetic != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",lastnamePhonetic];
        //读取middlename拼音音标
        NSString *middlenamePhonetic = (NSString*)ABRecordCopyValue(person, kABPersonMiddleNamePhoneticProperty);
        if(middlenamePhonetic != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",middlenamePhonetic];
        //读取organization公司
        NSString *organization = (NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty);
        if(organization != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",organization];
        //读取jobtitle工作
        NSString *jobtitle = (NSString*)ABRecordCopyValue(person, kABPersonJobTitleProperty);
        if(jobtitle != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",jobtitle];
        //读取department部门
        NSString *department = (NSString*)ABRecordCopyValue(person, kABPersonDepartmentProperty);
        if(department != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",department];
        //读取birthday生日
        NSDate *birthday = (NSDate*)ABRecordCopyValue(person, kABPersonBirthdayProperty);
        if(birthday != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",birthday];
        //读取note备忘录
        NSString *note = (NSString*)ABRecordCopyValue(person, kABPersonNoteProperty);
        if(note != nil)
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",note];
        //第一次添加该条记录的时间
        NSString *firstknow = (NSString*)ABRecordCopyValue(person, kABPersonCreationDateProperty);
        NSLog(@"第一次添加该条记录的时间%@\n",firstknow);
        //最后一次修改該条记录的时间
        NSString *lastknow = (NSString*)ABRecordCopyValue(person, kABPersonModificationDateProperty);
        NSLog(@"最后一次修改該条记录的时间%@\n",lastknow);

        //获取email多值
        ABMultiValueRef email = ABRecordCopyValue(person, kABPersonEmailProperty);
        int emailcount = ABMultiValueGetCount(email);    
        for (int x = 0; x < emailcount; x++)
        {
            //获取email Label
            NSString* emailLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(email, x));
            //获取email值
            NSString* emailContent = (NSString*)ABMultiValueCopyValueAtIndex(email, x);
            textView.text = [textView.text stringByAppendingFormat:@"%@:%@\n",emailLabel,emailContent];
        }
        //读取地址多值
        ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty);
        int count = ABMultiValueGetCount(address);    

        for(int j = 0; j < count; j++)
        {
            //获取地址Label
            NSString* addressLabel = (NSString*)ABMultiValueCopyLabelAtIndex(address, j);
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",addressLabel];
            //获取該label下的地址6属性
            NSDictionary* personaddress =(NSDictionary*) ABMultiValueCopyValueAtIndex(address, j);        
            NSString* country = [personaddress valueForKey:(NSString *)kABPersonAddressCountryKey];
            if(country != nil)
                textView.text = [textView.text stringByAppendingFormat:@"国家:%@\n",country];
            NSString* city = [personaddress valueForKey:(NSString *)kABPersonAddressCityKey];
            if(city != nil)
                textView.text = [textView.text stringByAppendingFormat:@"城市:%@\n",city];
            NSString* state = [personaddress valueForKey:(NSString *)kABPersonAddressStateKey];
            if(state != nil)
                textView.text = [textView.text stringByAppendingFormat:@"省:%@\n",state];
            NSString* street = [personaddress valueForKey:(NSString *)kABPersonAddressStreetKey];
            if(street != nil)
                textView.text = [textView.text stringByAppendingFormat:@"街道:%@\n",street];
            NSString* zip = [personaddress valueForKey:(NSString *)kABPersonAddressZIPKey];
            if(zip != nil)
                textView.text = [textView.text stringByAppendingFormat:@"邮编:%@\n",zip];    
            NSString* coutntrycode = [personaddress valueForKey:(NSString *)kABPersonAddressCountryCodeKey];
            if(coutntrycode != nil)
                textView.text = [textView.text stringByAppendingFormat:@"国家编号:%@\n",coutntrycode];    
        }

        //获取dates多值
        ABMultiValueRef dates = ABRecordCopyValue(person, kABPersonDateProperty);
        int datescount = ABMultiValueGetCount(dates);    
        for (int y = 0; y < datescount; y++)
        {
            //获取dates Label
            NSString* datesLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(dates, y));
            //获取dates值
            NSString* datesContent = (NSString*)ABMultiValueCopyValueAtIndex(dates, y);
            textView.text = [textView.text stringByAppendingFormat:@"%@:%@\n",datesLabel,datesContent];
        }
        //获取kind值
        CFNumberRef recordType = ABRecordCopyValue(person, kABPersonKindProperty);
        if (recordType == kABPersonKindOrganization) {
            // it's a company
            NSLog(@"it's a company\n");
        } else {
            // it's a person, resource, or room
            NSLog(@"it's a person, resource, or room\n");
        }

        //获取IM多值
        ABMultiValueRef instantMessage = ABRecordCopyValue(person, kABPersonInstantMessageProperty);
        for (int l = 1; l < ABMultiValueGetCount(instantMessage); l++)
        {
            //获取IM Label
            NSString* instantMessageLabel = (NSString*)ABMultiValueCopyLabelAtIndex(instantMessage, l);
            textView.text = [textView.text stringByAppendingFormat:@"%@\n",instantMessageLabel];
            //获取該label下的2属性
            NSDictionary* instantMessageContent =(NSDictionary*) ABMultiValueCopyValueAtIndex(instantMessage, l);        
            NSString* username = [instantMessageContent valueForKey:(NSString *)kABPersonInstantMessageUsernameKey];
            if(username != nil)
                textView.text = [textView.text stringByAppendingFormat:@"username:%@\n",username];

            NSString* service = [instantMessageContent valueForKey:(NSString *)kABPersonInstantMessageServiceKey];
            if(service != nil)
                textView.text = [textView.text stringByAppendingFormat:@"service:%@\n",service];            
        }

        //读取电话多值
        ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
        for (int k = 0; k<ABMultiValueGetCount(phone); k++)
        {
            //获取电话Label
            NSString * personPhoneLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(phone, k));
            //获取該Label下的电话值
            NSString * personPhone = (NSString*)ABMultiValueCopyValueAtIndex(phone, k);

            textView.text = [textView.text stringByAppendingFormat:@"%@:%@\n",personPhoneLabel,personPhone];
        }

        //获取URL多值
        ABMultiValueRef url = ABRecordCopyValue(person, kABPersonURLProperty);
        for (int m = 0; m < ABMultiValueGetCount(url); m++)
        {
            //获取电话Label
            NSString * urlLabel = (NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(url, m));
            //获取該Label下的电话值
            NSString * urlContent = (NSString*)ABMultiValueCopyValueAtIndex(url,m);

            textView.text = [textView.text stringByAppendingFormat:@"%@:%@\n",urlLabel,urlContent];
        }

        //读取照片
        NSData *image = (NSData*)ABPersonCopyImageData(person);

        UIImageView *myImage = [[UIImageView alloc] initWithFrame:CGRectMake(200, 0, 50, 50)];
        [myImage setImage:[UIImage imageWithData:image]];
        myImage.opaque = YES;
        [textView addSubview:myImage];

    }

    CFRelease(results);
    CFRelease(addressBook);

 

ios实现通讯录的查询与删除

os提供了对通讯录操作的组建,其中一个是直接操作通讯录,另一个是调用通讯录的UI组建。实现方法如下:

添加AddressBook.framework到工程中。

1

代码实现:

    -(IBAction)onClickbutton:(id)sender
    {
        NSMutableArray* personArray =[[[NSMutableArray alloc] init] autorelease];
        ABAddressBookRef addressBook =ABAddressBookCreate();
        NSString*firstName,*lastName,*fullName;
        personArray =(NSMutableArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
        if([sender tag]==0){

            for(id *person in personArray)
            {
                firstName =(NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
                firstName =[firstName stringByAppendingFormat:@" "];
                lastName =(NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);   
                fullName =[firstName stringByAppendingFormat:@"%@",lastName];
                NSLog(@"===%@",fullName);
                ABMultiValueRef phones =(ABMultiValueRef)ABRecordCopyValue(person, kABPersonPhoneProperty);
                for(int i =0;i <ABMultiValueGetCount(phones); i++)
                { 
                    NSString*phone =(NSString*)ABMultiValueCopyValueAtIndex(phones, i);
                    NSLog(@"===%@",phone);
                }
                ABMultiValueRef mails =(ABMultiValueRef)ABRecordCopyValue(person, kABPersonEmailProperty);
                for(int i =0;i <ABMultiValueGetCount(mails); i++)
                { 
                    NSString*mail =(NSString*)ABMultiValueCopyValueAtIndex(mails, i);
                    NSLog(@"==%@",mail);
                }       
            }   
        }else{
            //删除信息
            //返回所有联系人到一个数组中
            CFArrayRef personArray =ABAddressBookCopyArrayOfAllPeople(addressBook);
            CFIndex personCount =ABAddressBookGetPersonCount(addressBook);
              for(int i =0;i<personCount;i++){
                  ABRecordRefref=CFArrayGetValueAtIndex(personArray, i);
                  CFStringRef firstName1 =ABRecordCopyValue(ref, kABPersonFirstNameProperty);
                  CFStringRef lastName1 =ABRecordCopyValue(ref, kABPersonLastNameProperty);
                  NSString*contactFirstLast =[NSString stringWithFormat: @"%@%@",(NSString*)firstName1,(NSString*)lastName1];
                if([contactFirstLast isEqualToString:@"徐梦"]){
                    //删除联系人
                    ABAddressBookRemoveRecord(addressBook,ref,nil);
                }
            }
            //保存电话本
            ABAddressBookSave(addressBook,nil);  
            //释放内存
            //CFRelease(personRef);
    //        CFRelease(addressbookRef); 
        }
    }

 

本文转自:http://blog.csdn.net/kingkong1024/article/details/8364037

ios6上读取通讯录的方法

ios升级到6.0以后的变化之一就是增加了通讯录的隐私设置,防止程序未通过许可就访问用户的通讯录。因此在app开发中,读取通讯录的方法也有了一些变化。上代码:

-(BOOL)isABAddressBookCreateWithOptionsAvailable {
return &ABAddressBookCreateWithOptions != NULL;
}

-(void)loadContacts {
ABAddressBookRef addressBook;
if ([self isABAddressBookCreateWithOptionsAvailable]) {

// ios6以上读取方法
CFErrorRef error = nil;
addressBook = ABAddressBookCreateWithOptions(NULL,&error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
// callback can occur in background, address book must be accessed on thread it was created on
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {

} else if (!granted) {

} else {
// access granted
AddressBookUpdated(addressBook, nil, (__bridge void *)(self));
CFRelease(addressBook);
}
});
});
} else {
// iOS 4/5
addressBook = ABAddressBookCreate();
AddressBookUpdated(addressBook, NULL, (__bridge void *)(self));
CFRelease(addressBook);
}
}

void AddressBookUpdated(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
ABAddressBookRevert(addressBook);
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
};

 

本文转自:http://bluevt.org/?p=41

用xcode 5 开发访问IOS 7上面的通讯录问题

NSMutableArray *addressBookTemp = [NSMutableArray array];ABAddressBookRef addressBooks = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBooks);

CFIndex nPeople = ABAddressBookGetPersonCount(addressBooks);

 

 

这段代码在IOS6是可以读取通讯录的,但在IOS7下面就不行,程序没报错,调试时候发现返回的都是nil,有木有朋友遇到这个问题?

找到原因了,原来IOS7需要隐私验证,调用通讯录里面API需要以下代码作为权限认证:

 __block BOOL accessGranted = NO;
 if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
  ABAddressBookRequestAccessWithCompletion(addressBooks, ^(bool granted, CFErrorRef error)
 {
   // First time access has been granted, add the contact 
   accessGranted = granted; });
 }
 else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
 {
  // The user has previously given access, add the contact 
  accessGranted = YES;
 }
 else
 {
 // The user has previously denied access
 // Send an alert telling user to change privacy setting in settings app
 }

不过IOS6好像没有,希望对其他朋友有帮助 – sfdux 2013-09-24 11:12 回复

Installing Cocos2d for iPhone Development

Coco2d is an SDK geared toward games development for iPhone and iTouch.   It was originally written for Phyton language.  It is licensed under GNU LGPL.

Where To Download:

http://code.google.com/p/cocos2d-iphone/

Requirements:

  • Mac running Mac OS that supports the iPhone SDK (mine is Mac OS 10.5.6)
  • Xcode version 3 or newer
  • iPhone SDK

For help on installing Xcode and iPhone SDK, and where to get them, see http://permadi.com/blog/?p=130.

Steps To Install

1. Download from http://code.google.com/p/cocos2d-iphone/downloads/list.

2. Extract and copy to the files your Library folder (can be any folder you want to designate).  I put mine on a Library folder.

1

Congratulations.  You have cocos2d installed.  Now comes the more difficult part (just because there’s no documentation).

Let’s try out the samples so we can see what cocos2d is capable of.

You can double click the project file (cocos2d-iPhone.xcodeproj) which should be located in the folder where you extracted cocos2d package.  Or you can run Xcode and do File->Open.

You should see the project window with the following Groups & Files:

2

If you do Build And Go now, either nothing happens or the iPhone simulator launches with a blank screen.  You should expand theTargets group instead.  When you do that, you’l see the list of exectables (Atlas Demo, AttachDemo, EaseDemo, and so on).  Control-Click (or right-click) on any of the demo and do Build on one of the “Demo.”

build1

After the selected demo is built, you can run it by expanding the Executables tree. You should see the demo that you build on the Executables tree. Control-Click (or right-click) on the item that has the same demo name as the one you built earlier.  (Note: If you don’t see the Start menu, then you have not built the executable.  Do the previous step first.)

startcocos2dexample1

Here’s what AccelViewportDemo looks like.

acceldemo

Try the other ones.  They are cool.

Make sure also to build the cocos2d library for your target platform, so you can use the libraries without having to recompile every time.  To do this, select the Active SDK and Active Build Configuration that you need (or build them all).  You can find the build result in abuild under the folder where you installed cocos2d.  Select cocos2d in the Targets group, and do Control-click, select build cocos2d.

cocos2dlib

 

To: Hello World Sample Appilcation

 

iBeacon技术,苹果迟迟不肯支持NFC原来是为了另立山头?

 121911tybphw6o0m0wzkib
虎嗅注:苹果发布会真正的闪光点常常被“杂音”淹没——9月10日的发布会上,iPhone 5C的五种颜色和高昂定价让很多人忽略A7处理器这款第一次被运用在智能手机上的64位ARM架构处理器,领先于高通、Nvidia和三星;而在今年6月的WWDC上,iOS 7的“扁平化”风格也使人们忽略了其中的一些重要的新特性,比如iBeacon技术——到现在为止还有很多人不知道这是什么。
最近,国外科技媒体Gigaom上有一篇文章,其中详细介绍了苹果用以对抗NFC(近场通讯)的iBeacon技术,并认为该技术将是苹果未来重点发展对象之一。本文由腾讯数码编译,大意如下:
在今年六月举行的WWDC上,作为iOS 7中最重要的新特性之一,苹果正式对外发布了iBeacon。同时,一家名为Estimote的公司日前也宣布将推出支持iBeacon技术的基站。
Estimote为什么要支持iBeacon技术?因为iBeacon技术不仅为诸如室内地图等新兴应用提供了发展平台,能够让互联网更容易地融入我们的日常生活,甚至还有可能击败目前最有希望成为无线支付方式的NFC技术。
iBeacon技术和低耗蓝牙技术
通过使用低功耗蓝牙技术(Bluetooth Low Energy,也就是通常所说的Bluetooth 4.0或者Bluetooth Smart),iBeacon基站可以创建一个信号区域,当设备进入该区域时,相应的应用程序便会提示用户是否需要接入这个信号网络。通过能够放置在任何物体中的小型无线传感器和低功耗蓝牙技术,用户便能使用iPhone来传输数据。
举个例子,假如你带着一部iPhone 5s(运行iOS 7并支持iBeacon)走入一家大型商场的店铺,同时这也意味着你已经进入了这家店铺的iBeacon信号区域。然后iBeacon基站便可以向你的iPhone传输各种信息,比如优惠券或者是店内导航信息,甚至当你走到某些柜台前面时,iBeacon还会提供个性化的商品推荐信息。也就是说在iBeacon基站的信息区域内,用户通过手中的智能手机便能够获取个性化的微型位置信息以及通知。
iBeacon不仅能够为用户提供他们所需要的信息,甚至和NFC技术一样,用户也能通过iBeacon来完成支付。除此之外,每个iBeacon基站内置有加速度计、闪存、ARM架构处理器以及蓝牙模块,而一小块纽扣电池便能为一个iBeacon基站提供长达两年的续航时间。
低功耗蓝牙技术的最大特点便在于低功耗,从而能使设备拥有更长的续航时间。不过低功耗蓝牙技术仅支持较低的文件传输速率,因此可以用于可穿戴式智能设备之间的信息传送,但却不能完成像传输音频这样的任务。从目前的状况来看,只有Android 4.3才支持低功耗蓝牙技术,因此这就是为什么老款Android机型不支持某些导航应用的原因。
传输范围广,成本低廉的iBeacon技术
从技术角度讲,更广的信息传输范围是iBeacon相比于NFC最大的优势。对于如今的NFC技术,虽然NFC标签的价格要比NFC芯片便宜得多,但是NFC标签的理论有效距离只有20cm,而最理想的使用距离只有4cm,范围可谓非常之小。
同时,手机等移动设备必须搭载NFC芯片才能支持NFC通讯;而iBeacon基站虽然要比NFC芯片的价格稍微昂贵一些,但是iBeacon的信息传输距离可达50m左右,而且如今几乎每部手机都支持蓝牙技术,但却不一定配备有NFC芯片。
让我们回到前面的那个例子中去,假设一家店铺的面积为16000平方米左右,而如果每个iBeacon基站的最远传输距离为50m的话,那么可以覆盖的面积大约在2500平方米左右,因此这家店铺只需要购买7个iBeacon基站便能够满足要求。
而从Estimote公司给出的价格来看,3个iBeacon基站的预购价格为99美元(约合人民币610元)。需要注意的是,虽然Estimote公司推出的iBeacon基站的最远传输距离为50m,但他们推荐在10m范围内的使用效果最好。如果按照Estimote公司给出的建议的话,每个iBeacon基站的覆盖范围是100平方米左右,那么总共需花费约5000美元左右。
如果使用NFC标签的话,按每个标签10美分(约合人民币0.61元)来计算的话,10万件商品就需要花费10000美元,是使用iBeacon基站的两倍。
或许将诞生一系列新应用
从iBeacon的特点来说,该技术很可能会促进一系列室内地图应用的诞生。由于在室内时,有各种障碍物的阻挡,因此GPS信号非常微弱,因此无法实现导航。这也是为什么虽然谷歌现在已经建立了部分地区的室内地图,但是还无法实现室内导航的原因。而这也正是iBeacon技术的优势所在。
借助智能手机,用户可以连接到最近的iBeacon基站,从而获得该基站的GPS位置信息,从而知道目前所处的地点。当用户进入或离开某个iBeacon基站的通信范围时都会收到相应的通知信息,从而实现导航的目的。
对抗NFC,低功耗蓝牙技术才是将网络带进现实的最好方法?
每次新款iPhone发布之前,外界都有人预测新款iPhone将会搭载NFC技术,不过事实证明这都只是外界一厢情愿的想法罢了。在iOS 7中,苹果增加了AirDrop无线分享功能,而苹果公司软件工程高级副总裁Craig Federighi认为“没有必要为了分享文件而走到某个人的面前,然后仅仅是为了触碰一下手机”,而这也是苹果对于NFC技术的看法。
为了让网络与现实世界结合到一起,各种传感器的起到了非常重要的作用。对于一个传感器来说,尺寸、价格、网络连接性都是很关键的指标。如果能够远程遥控各种传感器的话,那么传感器的用途可以说是无穷无尽的。比如在回家的路上开启家中的电源,根据天气控制冰箱的温度,通过手机控制房间的灯光等等。Estimote表示他们正在努力改进iBeacon基站以进一步缩减价格和体积,从而使iBeacon更加实用。
既然苹果能够通过使用低功耗蓝牙技术的iBeacon来解决数据的短距离传输问题,那么又有什么理由让人们互相触碰手机呢?而且相比于NFC技术来说,蓝牙能够提供NFC无法实现的功能。

揭开SVCHOST.exe进程之谜

svchost.exe是nt核心系统的非常重要的进程,对于2000、xp来说,不可或缺。很多病毒、木马也会调用它。所以,深入了解这个程序,是玩电脑的必修课之一。

大家对windows操作系统一定不陌生,但你是否注意到系统中“svchost.exe”这个文件呢?细心的朋友会发现windows中存在多个 “svchost”进程(通过“ctrl+alt+del”键打开任务管理器,这里的“进程”标签中就可看到了),为什么会这样呢?下面就来揭开它神秘的面纱。

发现

在基于nt内核的windows操作系统家族中,不同版本的windows系统,存在不同数量的“svchost”进程,用户使用“任务管理器”可查看其进程数目。一般来说,win2000有两个svchost进程,winxp中则有四个或四个以上的svchost进程(以后看到系统中有多个这种进程,千万别立即判定系统有病毒了哟),而win2003 server中则更多。这些svchost进程提供很多系统服务,如:rpcss服务(remote procedure call)、dmserver服务(logical disk manager)、dhcp服务(dhcp client)等。

如果要了解每个svchost进程到底提供了多少系统服务,可以在win2000的命令提示符窗口中输入“tlist -s”命令来查看,该命令是win2000 support tools提供的。在winxp则使用“tasklist /svc”命令。

svchost中可以包含多个服务

深入

windows系统进程分为独立进程和共享进程两种,“svchost.exe”文件存在于“%systemroot% system32”目录下,它属于共享进程。随着windows系统服务不断增多,为了节省系统资源,微软把很多服务做成共享方式,交由 svchost.exe进程来启动。但svchost进程只作为服务宿主,并不能实现任何服务功能,即它只能提供条件让其他服务在这里被启动,而它自己却不能给用户提供任何服务。那这些服务是如何实现的呢?

原来这些系统服务是以动态链接库(dll)形式实现的,它们把可执行程序指向 svchost,由svchost调用相应服务的动态链接库来启动服务。那svchost又怎么知道某个系统服务该调用哪个动态链接库呢?这是通过系统服务在注册表中设置的参数来实现。下面就以rpcss(remote procedure call)服务为例,进行讲解。

从启动参数中可见服务是靠svchost来启动的。

实例

以windows xp为例,点击“开始”/“运行”,输入“services.msc”命令,弹出服务对话框,然后打开“remote procedure call”属性对话框,可以看到rpcss服务的可执行文件的路径为“c:\windows\system32\svchost -k rpcss”,这说明rpcss服务是依靠svchost调用“rpcss”参数来实现的,而参数的内容则是存放在系统注册表中的。

在运行对话框中输入“regedit.exe”后回车,打开注册表编辑器,找到[hkey_local_machine systemcurrentcontrolsetservicesrpcss]项,找到类型为“reg_expand_sz”的键“magepath”,其键值为“%systemroot%system32svchost -k rpcss”(这就是在服务窗口中看到的服务启动命令),另外在“parameters”子项中有个名为“servicedll”的键,其值为“% systemroot%system32rpcss.dll”,其中“rpcss.dll”就是rpcss服务要使用的动态链接库文件。这样 svchost进程通过读取“rpcss”服务注册表信息,就能启动该服务了。

解惑

因为svchost进程启动各种服务,所以病毒、木马也想尽办法来利用它,企图利用它的特性来迷惑用户,达到感染、入侵、破坏的目的(如冲击波变种病毒“w32.welchia.worm”)。但windows系统存在多个svchost进程是很正常的,在受感染的机器中到底哪个是病毒进程呢?这里仅举一例来说明。

假设windows xp系统被“w32.welchia.worm”感染了。正常的svchost文件存在于“c:\windows\system32”目录下,如果发现该文件出现在其他目录下就要小心了。“w32.welchia.worm”病毒存在于“c:\windows\system32wins”目录中,因此使用进程管理器查看svchost进程的执行文件路径就很容易发现系统是否感染了病毒。windows系统自带的任务管理器不能够查看进程的路径,可以使用第三方进程管理软件,如“windows优化大师”进程管理器,通过这些工具就可很容易地查看到所有的svchost进程的执行文件路径,一旦发现其执行路径为不平常的位置就应该马上进行检测和处理。

由于篇幅的关系,不能对svchost全部功能进行详细介绍,这是一个windows中的一个特殊进程,有兴趣的可参考有关技术资料进一步去了解它。

 

来自:天极网

 

 

四元数与欧拉角之间的转换

在3D图形学中,最常用的旋转表示方法便是四元数和欧拉角,比起矩阵来具有节省存储空间和方便插值的优点。本文主要归纳了两种表达方式的转换,计算公式采用3D笛卡尔坐标系:

121309_1044_1

图1 3D Cartesian coordinate System (from wikipedia)

定义121309_1044_2分别为绕Z轴、Y轴、X轴的旋转角度,如果用Tait-Bryan angle表示,分别为Yaw、Pitch、Roll。

121309_1044_3

图2 Tait-Bryan angles (from wikipedia)

一、四元数的定义

121309_1044_4

通过旋转轴和绕该轴旋转的角度可以构造一个四元数:

121309_1044_5

其中121309_1044_6是绕旋转轴旋转的角度,121309_1044_7为旋转轴在x,y,z方向的分量(由此确定了旋转轴)。

二、欧拉角到四元数的转换

121309_1044_8

三、四元数到欧拉角的转换

121309_1044_9

       arctanarcsin的结果是121309_1044_10,这并不能覆盖所有朝向(对于121309_1044_11121309_1044_12的取值范围已经满足),因此需要用atan2来代替arctan

121309_1044_13

四、在其他坐标系下使用

在其他坐标系下,需根据坐标轴的定义,调整一下以上公式。如在Direct3D中,笛卡尔坐标系的X轴变为Z轴,Y轴变为X轴,Z轴变为Y轴(无需考虑方向)。

121309_1044_14

五、示例代码

http://www.cppblog.com/Files/heath/Euler2Quaternion.rar
Demo渲染两个模型,左边使用欧拉角,右边使用四元数,方向键Up、Left、Right旋转模型。

参考文献:
[1] http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
[2] Ken Shoemake, Animating Rotation with Quaternion Curves, 1985

 

本文转自:http://www.cppblog.com/heath/archive/2009/12/13/103127.html

 

在C#中调试C++的DLL

“我的小伙伴们都惊呆了!”

今天才发现,其实C#是可以跟进C++代码的!!!在VS2012里的做法是:

在C#项目上右键点击,在右键菜单上选择“属性” –> 调试–>启用调试器–>勾选“启用本机代码调试(T)”

这样之后,就可以直接在C++项目里的C++代码上直接打断点调试了!

如下图所示:

1、在项目上右键,然后在右键菜单中选择属性

2、勾选启用本机代码调试

能调试到C++代码,还有啥好担心的??? :)

 

 

 

 

四元数及其平滑处理

最近做camera 的 AI,需要对四元数,欧拉角等要有一定的了解,把前面学习的整理了一下:

1。四元数的优势

 三维空间的旋转完全可以由4元数来胜任。传统意义上需要3×3矩阵来进行向量的旋转(4×4矩阵的第四列表示平移)。所以四元数更节省空间,运算速度更快。既然四元数能方便的表示3D旋转,那么对他们进行插值就能产生平滑的旋转效果。

劣势可能是比较抽象,不大好理解。而且据说顶点变换还是矩阵效率更高(涉及到平移)。

2。四元数的物理意义

Q( x, y, z, w)来表示向量 绕轴 A(ax, ay,az) 旋转alpha

则: x = sin(alpha/2)*ax;

y =   sin(alpha/2)*ay;

z =  sin(alpha/2)*az;

w = cos(alpha/2);

 

3。四元素的数学意义

我们知道 复数的表示为 a+bi; 其中i*i = -1;

四元数 q = w + xi + yi +zi;

复数的运算法则为四元数的数学运算提供了规则基础。比如说乘法,加法等。

4。四元数和矩阵间的转换

QX =0; QY=1;QZ=2;QW=3;

void quat_ConvertFromMatrix(float *pQuat, const float mat[4][4])
{
 float diag, s;
 int i, j, k;

 diag = mat[0][0] + mat[1][1] + mat[2][2];

 if(diag < -0.999f )
 {
  i = QX;
  if( mat[QY][QY] > mat[QX][QX] )
   i = QY;
  if( mat[QZ][QZ] > mat[i][i] )
   i = QZ;

  j = g_QNext[i];
  k = g_QNext[j];

  s = ltsqrtf( mat[i][i] - ( mat[j][j] + mat[k][k] ) + /*mat[3][3]*/ 1.0f );

  pQuat[i] = s * 0.5f;
  s = 0.5f / s;
  pQuat[QW] = ( mat[k][j] - mat[j][k] ) * s;
  pQuat[j] = ( mat[j][i] + mat[i][j] ) * s;
  pQuat[k] = ( mat[k][i] + mat[i][k] ) * s;
  return;
 }

 s = ltsqrtf( diag + /*mat[3][3]*/ 1.0f );

 pQuat[3] = s * 0.5f;
 s = 0.5f / s;

 pQuat[0] = (mat[2][1] - mat[1][2]) * s;
 pQuat[1] = (mat[0][2] - mat[2][0]) * s;
 pQuat[2] = (mat[1][0] - mat[0][1]) * s;
}

void quat_ConvertToMatrix(const float *pQuat, float mat[4][4])
{
 float s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;

/*!
  get the values for matrix calcuation.
*/
 s = 2.0f / ((pQuat[0] * pQuat[0]) + (pQuat[1] * pQuat[1]) + 
  (pQuat[2] * pQuat[2]) + (pQuat[3] * pQuat[3]));

 xs = pQuat[0] * s;
 ys = pQuat[1] * s;
 zs = pQuat[2] * s;

 wx = pQuat[3] * xs;
 wy = pQuat[3] * ys;
 wz = pQuat[3] * zs;

 xx = pQuat[0] * xs;
 xy = pQuat[0] * ys;
 xz = pQuat[0] * zs;

 yy = pQuat[1] * ys;
 yz = pQuat[1] * zs;

 zz = pQuat[2] * zs;

/*!
  Fill in matrix

*/
 mat[0][0] = 1.0f - (yy + zz);
 mat[0][1] = xy - wz;
 mat[0][2] = xz + wy;

 mat[1][0] = xy + wz;
 mat[1][1] = 1.0f - (xx + zz);
 mat[1][2] = yz - wx;

 mat[2][0] = xz - wy;
 mat[2][1] = yz + wx;
 mat[2][2] = 1.0f - (xx + yy);

 mat[0][3] = mat[1][3] = mat[2][3] = mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
 mat[3][3] = 1.0f;
}

 

具体推倒过程可以参考相关文献。

5。四元数插值

有很多插值方法,比如线性,球形,样条插值等;

lerp (t;,q0,q1) = (1-t)q0 + tq1 ;//快速,但动画不平滑,需要归一化 / ||(1-t)q0 + tq1||;

slerp( t;, q0,q1) = [q0 *sin(thata(1-thata)) + q1sin(thata*t)] / sin(thata); //平滑,归一化;

thata 为q0 q1夹角。q0 dot q1 = cos(thata);

相关代码:

void quat_Slerp(float *pDest, const float *pQ1, const float *pQ2, float t)
{
 float rot1q[4];
 float omega, cosom, oosinom;
 float scalerot0, scalerot1;

/*!
  Calculate the cosine

*/
 cosom = pQ1[0]*pQ2[0] + pQ1[1]*pQ2[1] + pQ1[2]*pQ2[2] + pQ1[3]*pQ2[3];

/*!
  adjust signs if necessary

*/
 if(cosom < 0.0f)
 {
  cosom = -cosom;
  rot1q[0] = -pQ2[0];
  rot1q[1] = -pQ2[1];
  rot1q[2] = -pQ2[2];
  rot1q[3] = -pQ2[3];
 }
 else  
 {
  rot1q[0] = pQ2[0];
  rot1q[1] = pQ2[1];
  rot1q[2] = pQ2[2];
  rot1q[3] = pQ2[3];
 }

/*!
  calculate interpolating coeffs

*/
 if ( (1.0f - cosom) > 0.0001f ) 
 { 
/*!
   standard case

*/
  omega   = ltacosf(cosom);
  oosinom = 1.0f / ltsinf(omega);
  scalerot0 = ltsinf((1.f - t) * omega) * oosinom;
  scalerot1 = ltsinf(t * omega) * oosinom;
 }
 else
 { 
/*!
   rot0 and rot1 very close - just do linear interp.

*/
  scalerot0 = 1.0f - t;
  scalerot1 = t;
 }

 //! build the new quarternion
 pDest[0] = (scalerot0 * pQ1[0] + scalerot1 * rot1q[0]);
 pDest[1] = (scalerot0 * pQ1[1] + scalerot1 * rot1q[1]);
 pDest[2] = (scalerot0 * pQ1[2] + scalerot1 * rot1q[2]);
 pDest[3] = (scalerot0 * pQ1[3] + scalerot1 * rot1q[3]);
}

 

参考文献:

游戏编程精粹

 

本文转自:http://blog.csdn.net/hziee_/article/details/1630116

 

 

 

通过CreateFile操作串口,调用写入(WriteFile)时被挂起(hanges)

Windows中C++写的串口操作类,用CreateFile打开串口:

	HANDLE hSerialPort = ::CreateFile	(	szPortName, 
											GENERIC_READ| GENERIC_WRITE, 
											0, 
											NULL, 
											OPEN_EXISTING, 
											FILE_ATTRIBUTE_NORMAL,
											NULL);

 

设置参数:

		DCB dcb={0};
		if(::GetCommState(hSerialPort, &dcb))
		{
			dcb.BaudRate	= wBaundRate;
 			dcb.ByteSize	= 8;
 			dcb.Parity		= NOPARITY;
 			dcb.StopBits	= ONESTOPBIT;
			bRet = ::SetCommState(hSerialPort, &dcb);
		}

设置超时:

 

		if(::SetupComm(hSerialPort, CT_READ_CACHE, CT_WRITE_CACHE))
		{
			//
			COMMTIMEOUTS cto={0};
			cto.ReadIntervalTimeout			= 0;
			cto.ReadTotalTimeoutConstant	= 0;
			cto.ReadTotalTimeoutMultiplier	= 3000;
			cto.WriteTotalTimeoutConstant	= 0;
			cto.WriteTotalTimeoutMultiplier	= 0;
			bRet =  ::SetCommTimeouts(hSerialPort, &cto);
		}

清空串口并开启读取线程:

	if(bRet&&::PurgeComm(hSerialPort,PURGE_TXCLEAR|PURGE_RXCLEAR))
	{
		if(NULL == m_pbBuffer)
		{
			m_cbBuffer	= CT_READ_CACHE;
			bRet = (NULL!=(m_pbBuffer=(LPBYTE)::malloc(m_cbBuffer*sizeof(BYTE))));
		}
		if(bRet)
		{
			m_bStarted = TRUE;
			bRet = (INVALID_HANDLE_VALUE!=(m_hReadThread = ::CreateThread(NULL, 0, LPTHREAD_START_ROUTINE (_SerialPortProc), this, 0, NULL)));
		}
	}

读取线程:

DWORD SerialPortHelper::SerialPortProc	(	void	)
{
	DWORD dwError = 0;
	COMSTAT cs={0};

	SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING);
	DWORD dwCommStatus = 0;
	while (m_bStarted)
	{
		WaitCommEvent(m_hSerialPort, &dwCommStatus, 0);

		SetCommMask (m_hSerialPort, EV_RXCHAR);

		if(dwCommStatus & EV_RXCHAR)
		{
			if(::ClearCommError(m_hSerialPort, &dwError, &cs))
			{
				if(cs.cbInQue>0)
				{
					ReceiveData(cs.cbInQue);
				}
			}
		}
	}
	return 0;
}

这种情况下,如果调用WriteFile就永远无法返回,WriteFile被挂起了。

实际上原因在于读取线程中,如果串口没有任何数据到达,则串口被WaitCommEvent()挂起,所以无法写入数据,导致WriteFile()函数被挂起。

 

临界区,互斥量,信号量,事件的区别

四种进程或线程同步互斥的控制方法

1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2、互斥量:为协调共同对一个共享资源的单独访问而设计的。
3、信号量:为控制一个具有有限数量用户资源而设计。
4、事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。

临界区(Critical Section)

保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线 程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操 作共享资源的目的。
临界区包含两个操作原语:
EnterCriticalSection() 进入临界区
LeaveCriticalSection() 离开临界区
EnterCriticalSection()语句执行后代码将进入临界区以后无论发生什么,必须确保与之匹配的 LeaveCriticalSection()都能够被执行到。否则临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快,但却只能用来同步本 进程内的线程,而不可用来同步多个进程中的线程。
MFC提供了很多功能完备的类,我用MFC实现了临界区。MFC为临界区提供有一个CCriticalSection类,使用该类进行线程同步处理是 非常简单的。只需在线程函数中用CCriticalSection类成员函数Lock()和UnLock()标定出被保护代码片段即可。Lock()后代 码用到的资源自动被视为临界区内的资源被保护。UnLock后别的线程才能访问这些资源。

互斥量(Mutex)

互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程 所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同 一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。

互斥量包含的几个操作原语:
CreateMutex() 创建一个互斥量
OpenMutex() 打开一个互斥量
ReleaseMutex() 释放互斥量
WaitForMultipleObjects() 等待互斥量对象

同样MFC为互斥量提供有一个CMutex类。使用CMutex类实现互斥量操作非常简单,但是要特别注意对CMutex的构造函数的调用
CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL)
不用的参数不能乱填,乱填会出现一些意想不到的运行结果。

信号量(Semaphores)

信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程 最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore()创建信号量 时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数 就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目, 不能在允许其他线程的进入,此时的信号量信号将无法发出。线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可 用资源计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。
PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数,S大于等于零时代表可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。
P操作 申请资源:
(1)S减1;
(2)若S减1后仍大于等于零,则进程继续执行;
(3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。
V操作 释放资源:
(1)S加1;
(2)若相加结果大于零,则进程继续执行;
(3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度。

信号量包含的几个操作原语:
CreateSemaphore() 创建一个信号量
OpenSemaphore() 打开一个信号量
ReleaseSemaphore() 释放信号量
WaitForSingleObject() 等待信号量

事件(Event)

事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。
信号量包含的几个操作原语:
CreateEvent() 创建一个信号量
OpenEvent() 打开一个事件
SetEvent() 回置事件
WaitForSingleObject() 等待一个事件
WaitForMultipleObjects()         等待多个事件
WaitForMultipleObjects 函数原型:
WaitForMultipleObjects(
IN DWORD nCount, // 等待句柄数
IN CONST HANDLE *lpHandles, //指向句柄数组
IN BOOL bWaitAll, //是否完全等待标志
IN DWORD dwMilliseconds //等待时间

参数nCount指定了要等待的内核对象的数目,存放这些内核对象的数组由lpHandles来指向。fWaitAll对指定的这nCount个内核 对象的两种等待方式进行了指定,为TRUE时当所有对象都被通知时函数才会返回,为FALSE则只要其中任何一个得到通知就可以返回。 dwMilliseconds在这里的作用与在WaitForSingleObject()中的作用是完全一致的。如果等待超时,函数将返回 WAIT_TIMEOUT。

总结
1. 互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说它可以跨越进程使用。所以创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使 用临界区会带来速度上的优势并能够减少资源占用量。因为互斥量是跨进程的互斥量一旦被创建,就可以通过名字打开它。
2. 互斥量(Mutex),信号灯(Semaphore),事件(Event)都可以被跨越进程使用来进行同步数据操作,而其他的对象与数据同步操作无关,但 对于进程和线程来讲,如果进程和线程在运行状态则为无信号状态,在退出后为有信号状态。所以可以使用WaitForSingleObject来等待进程和 线程退出。
3. 通过互斥量可以指定资源被独占的方式使用,但如果有下面一种情况通过互斥量就无法处理,比如现在一位用户购买了一份三个并发访问许可的数据库系统,可以根 据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操作,这时候如果利用互斥量就没有办法完成这个要求,信号灯对象可以说是一种资源计数 器。

转自:http://space.itpub.net/10697500/viewspace-612045

 

Macbook双系统多分区的解决方案

一些前序知识:

1、Mac系统不是Intel的i386架构,没有Bios,但是有EFI,通过EFI管理系统的引导。

2、Mac系统的分区表采用GUID,不是MBR。因此如果硬盘完全交给windows控制,会导致Mac系统无法启动。

3、任何对MBR的强行操作,会导致已经装好的双系统引导失效。

4、Mac的EFI分区会用GPT锁定,不要尝试去操作这个分区。

 

我们以一台Macbook pro(2011.7后产)裸机为例,目标是安装Macos和Win7双系统,同时实现Win7的多分区操作。

1、首先开机采用option,选择wifi的方式恢复Mac系统,这个是苹果的强项,不再赘述。恢复完后系统有出厂一般的完整的Mac系统。

2、接下来可以采用两种方式,一种是采用Bootcamp较为简单的安装双系统,这种方式简便快捷,但是由于受到Mac的控制,对Win的性能会有一定的影响,因为这个分区相当于一个映射分区。还有一种方式是用第三方程序refit,接管Mac的启动,类似以前win下面的启动管理器之类的软件。可以通过这个第三方efi直接选择从哪个分区引导,好处是直读硬盘,缺点是驱动会有点麻烦,因为不是BC模拟,所以驱动要自找。

3、我们采用较为普遍的BC方式。接下来又可以有两种选择,一种是根据BC的指示找Win7的DVD盘安装系统,还有一种是想办法绕过苹果的限制,用U盘安装Win7.有人说不是本来就可以用U盘装么?那个仅仅适用早先的Macbook,最新的苹果本都不能支持U盘,哪怕你用什么Win7 DVD USB启动程序把U盘写成一个启动盘,亦或者修改系统文件使得BC显示“制作Win7的U盘安装程序”(这条本来是不显示的,因为不支持较新的本,但是通过修改BC配置文件可以显示出来,并且可以帮你制作好启动U盘,但是你会发现,在BC的重启后,仍然显示找不到启动设备)

4、此外还尝试了把U盘转化为GPT的引导方式等等,都没能让mac认出这个可引导设备。后来还发现,如果装win8就省时省力多了,因为win8的efi可以让mac直接引导起来,具体做法就是,u盘制作成gpt的启动盘,然后把win8的安装程序copy进去,然后就可以启动安装了,这就是efi的魅力。但是win7不行,因为win7的efi居然比mac的高了一个版本(可见微软比苹果靠谱多了)

5、由此我们使用DVD盘安装win7

6、接下来要解决多分区的问题,很多人说mac用bc装win7是只能一个区的,这完全是误解。我们先来看看为什么他们会这样说。正常状态下,磁盘如果处于基本磁盘状态下,只能有4个主分区。当然如果你能转化为动态磁盘,就可以有N个主分区,但是你的mac系统就坏了,这样不行。那么在基本磁盘的前提条件下,mac已经用了2个(EFI一个,MAC系统一个);这两个是雷打不动不能改变的了,那么为什么还会出现两个呢?不是win7只需要一个么?其实这正是win7作怪,大家通过自己测试可以发现,win7如果采用光盘引导,在安装的过程中分区,那么它将自动产生一个100多M的分区(win7标示为系统保留),这个分区是个主分区,且主要用来放引导和预读文件。这样再加上win7自己的系统分区,整个硬盘就撑满了4个主分区,如果你再想分配主分区或扩展分区,都会提示不行,要不要转化为动态磁盘?那显然不可能,因为mac已经装好,转化动态后将无法启动mac。(这里要记住,扩展分区也是主分区,只是扩展分区上可以有N个逻辑分区)。

7、那么怎么办?有人说好办啊,你把那个win7的100多M的分区删掉不就完了吗?确实可以,但是删掉的结果是不能启动win7,有人说那把win7的分区全部删掉,然后重新划分。这样也不行,因为win7会强制再分出那个100多M的分区来。所以正确的做法是:删除win7的系统分区,点击那个100多M的分区,使用安装时分区工具里的“扩展”选项,将分区扩展到可以装win7系统的程度,这样等于就只剩三个主分区了!(补充,直接这样操作有可能出现留下的100多M分区无法引导的情况,正确的做法是,先格式化第四个分区,然后删除之,然后创建分区,这时候多出来的第三个分区,就是写着“系统保留”字样,这个分区就是可引导的了!!!)

8、安装完win7后,进入系统,不管你安装时有没有用扩展工具将剩余硬盘空间撑满,都可以在win7磁盘管理里,右键的菜单中找到“扩展分区”“压缩分区”选项,这个就是类似无损文件调整分区大小的工具,这样就能腾出磁盘空间,创建扩展分区,然后在上面创建逻辑分区,这样,你的win7就可以有N个盘可以用,不需要再堆在一个系统盘里了。

9,最后再提醒下,国人大多用盗版,win7在激活时不要采用OEM欺骗的方式激活,这样会重写win7的引导扇区,结果就是win7启动报错,应该采用屏蔽win7激活检测的方式激活,这两种激活程序网上都有。假如你已经覆盖了引导扇区,那也不用担心,用win7的安装盘引导后,选择修复系统,进入CMD,采用bootsect指令强行修复MBR即可。

本文出自 “水煮豆豆_网络爬爬” 博客,请务必保留此出处http://netwalk.blog.51cto.com/173717/908220

 

Macbook Pro换硬盘后的数据迁移

刚刚买了一块1TB 7200RPS的硬盘和一条8G内存条,打算把我的Macbook Pro升级一下。

原装的是一块320G HTC的硬盘,因为要装Windows、Linux等多种虚拟机,硬盘空间马上就告急了;又因为要开虚拟机,如果内存太小,多个系统一起跑显得很局促,于是搞了个1T的硬盘和一条8G 金士顿内存条。

买一条8G内存条是因为,现有的是两条2G内存条,如果买两条4G的差不多380rmb,把两条2G的全替了,可是一条8G的也就不到400rmb,跟两条4G价格差别不大,既然如此,何不买一条8G的,还可以保留一条2G,一共10G,而且万一以后觉得内存还是不够用,再搞一条8G的来组成16G,岂不是爽呆了?至于有人说即便都是DDR3 1333的内存条,容量不一样组不成双通道,首先比较质疑这种说法,即便如此,考虑到总的容量比较大,向后的兼容性也更好,认了!

至于拆机换硬盘和内存条的文章多如牛毛,就不再累赘了,看到一条保留原系统的迁移方法值得保留,便于稍后查阅:

过年了,拿奖金到村里买了块160G日立SATA盘准备替换我的mbp600原配的80G硬盘,另外再买了个希捷贴牌的远古代工SATA硬盘盒(USB接口),这个盒子跟远古的品质一样的,不过价格便宜30块钱,还是非常值的,看图片。
(比较遗憾,原帖图片看不到鸟...)
关于硬盘的拆机更换,可以参考坛子里南方石城同志的帖子。但关于两块硬盘的系统和数据迁移问题,我没找到合适的。因为我原硬盘用bootcamp装了windows,实际上有2个分区,mac和win,这两个分区上都有非常重要的工作文件,而且两个分区的系统都运行得非常稳定,因此我不想在新硬盘上完全重装MAC和WIN的操作系统,再迁移数据。
昨天晚上折腾了好久,发现其实用系统的磁盘工具的恢复功能,能非常简单地解决问题。实际上这个功能是将分区做了完整镜像,并且镜像后的目标盘是可以启动的,而且可以从USB启动MAC和WIN系统!
过程是这样的:
首先,当然把新买的160G硬盘装进外置硬盘盒,使用USB连接MBP,系统识别后,启动磁盘工具,进行分区:
(比较遗憾,原帖图片看不到鸟...)   
如图,分出mac os扩展日志式分区(后续恢复mac系统,我的是10.4.11),和一个windows分区(FAT32,msdos),大小自己定。注意,对新硬盘,要使用GUID分区表格式!!
图中,原“Macintosh HD”安装的是tiger系统,WINDOWS_HD是BootCamp的winXP。
分区完成后,使用磁盘工具的恢复功能,将原盘和目标盘分别拖拽到空白框位置:
(比较遗憾,原帖图片看不到鸟...)
点击恢复按钮,开始恢复过程(我的体验速度是,原mac系统分区46.68GB,恢复用了两个小时的时间)。完成mac区的恢复后,再恢复windows区。
恢复完成后,磁盘大小情况:
(比较遗憾,原帖图片看不到鸟...)
这时,你的数据恢复工作已经做完了。有什么效果?我们打开系统的启动磁盘功能看一下:
 (比较遗憾,原帖图片看不到鸟...)
可以看到,现在内置的两个磁盘分区(图中后两个)和外置USB连接的SATA硬盘的两个分区都是可以启动的!!
我测试了一下所有四个分区的启动和程序调用,文档查看,没有任何问题,而且,外置硬盘上的windows是可以完美启动的!(注意,如果你启动机器时按住Option来启动,是看不到外置硬盘上的win分区启动选项的,需要用mac下的启动磁盘来选择启动)。
那么,下一步你的工作就是拆机,换硬盘吧。
希望这个帖子能消除一些同志对换硬盘的数据恢复问题的疑虑。从这个过程我又体会到,Mac系统是多么人性化和简单!!虽然我也找了一些第三方工具,如discstudio,CCC等,实际都用不上。

 

C++通过Callback向C#传递数据

现在比较流行C#与C++融合:C#做GUI,开发效率高,C++做运算,运行效率高,二者兼得。

但是C++与C#必然存在数据交互,C#与C++dll的数据交互从来都是一个让人头疼的问题。

从调用方式看也有两种情况:

1、C#调用C++函数

这种情况用的比较多,数据流向可以是C#流向C++,通过参数将数据传递给C++(如:SetData(double[] data));也可以是C++流向C#(如:GetData(double[] data))。

2、C++ Callback

这种情况是C++中通过Callback的方式调用C#代码,类似于C++做过一些处理后向C#发送事件,事件可以携带数据(如处理后的数据)。则C++中定义函数指针的方式是:

typedef  void(*Render)(double* data, BOOL* color);

 

C#作为委托,定义的函数被C++ callback:

public delegate void RenderCallback([MarshalAs(UnmanagedType.LPArray, SizeConst =23)]double[] data, [MarshalAs(UnmanagedType.LPArray, SizeConst = 23)]int[] colors);

千万注意,delegate中的double[]数组一定要加上MarshalAs标记,标记为传递数组,而且必须指定传递的数量,如果不标记数量,则每次只传递一个数值,这个问题折磨我很久才搞定!

其他注意事项:

1、如何在C#中保持C++的函数指针

回调函数的另一个注意事项是向C++ dll传递回调函数指针的问题

假设有个函数向C++dll传递指针:

    public delegate void EKFRenderCallback(string data, string colors);

    public class EKFLib
    {
        [DllImport("EKFLib.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern void SetRenderCallback(EKFRenderCallback render);

C#中如下传递被回调的函数:

        public void RenderCallback(string data, string color)
        {
            // rendering
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            EKFLib.SetRenderCallback(RenderCallback);
            EKFLib.Init();
        }

这虽然没什么问题,但是通过SetRenderCallback()传入到C++的指针不受托管代码管理,在C#中认为此指针对象未被任何代码引用,GC做垃圾回收时,将会把C#本地的空指针回收,导致C++无法执行回调,出现“CallbackOnCollectedDelegate”错误:

对“MotionCapture!MotionCapture.EKFRenderCallback::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。

微软官网的例子是控制GC回收机制,这是个比较笨拙的方法,更加理所当然的方法是把委托定义成一个属性,指向一个new出来的callback,然后再把这个callback传递进C++dll中,这样,在C#端有对象引用,保证了GC不会回收此callback:

        public void RenderCallback(string data, string color)
        {
            // rendering
        }

        private EKFRenderCallback render;
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            render = new EKFRenderCallback(RenderCallback);
            EKFLib.SetRenderCallback(render);
            EKFLib.Init();
        }

 

2、__stdcall与_cdecl传递数据

最近一个项目是通过C++ 的 dll做高速运算,然后把结果数据通过Callback的方式回调给C#(界面部分),结果总是在C#中接到回调事件后就直接挂掉(程序直接在毫无提示的情况下退出,没有任何调试信息或者提示)。

导致问题的原因是,默认情况下,C++中如下定义的函数指针,默认是以_cdecl方式调用的:

typedef  void(*Render)(double* data, BOOL* color);

这种情况下,参数堆栈是由调用者(C++一侧)维护的,在C++调用此回调函数后,会把参数弹出堆栈而释放,导致C#读取数据时出现莫名其妙的错误。

以上是回调函数传递数组可能出现的情况,而如下所示,只传递一个参数的情况,甚至会在C#方莫名其妙的卡死:

typedef void (*CalibrationProgressCallback)(double percent);
改为__stdcall的方式即可解决问题,申明如下:

typedef  void(__stdcall *Render)(double* data, BOOL* color);

以下来自网络的一段_cdecl和__stdcall的解释,必须牢记:

1. __cdecl

即所谓的C调用规则,按从右至左的顺序压参数入栈,由调用者把参数弹出栈。切记:对于传送参数的内存栈是由调用者来维护的。返回值在EAX中。因此,对于象printf这样变参数的函数必须用这种规则。编译器在编译的时候对这种调用规则的函数生成修饰名的饿时候,仅在输出函数名前加上一个下划线前缀,格式为_functionname。
2. __stdcall

按从右至左的顺序压参数入栈,由被调用者把参数弹出栈。_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,切记:函数自己在退出时清空堆栈,返回值在EAX中。  __stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,格式为_functionname@number。如函数int func(int a, double b)的修饰名是_func@12

所以,从C++ dll中回调函数给C#传递数据,必须由C#函数在使用完数据后(退出函数时)自己清空堆栈!所C++中的回调函数指针应该如下定义:

typedef void (_stdcall *CalibrationProgressCallback)(double percent);

总结:

C++通过callback向C#传递数据必须注意以下几点:

1、C++中的回调函数必须用_stdcall标记,使用stdcall方式回调;

2、如果是数组,必须用 [MarshalAs(UnmanagedType.LPArray, SizeConst = 23)]标记参数,指定为数组且标记数组长度;

3、C#方必须申明一个变量,用来指向C++的回调指针函数,避免被C#回收掉。

 

 

 

 

 

C# import dll的P/Invoke调用在性能上的损失

    Net Framework提供了P/Invoke方式从托管代码中调用非托管的本地Dll,但是Micorsoft表示P/Invoke的性能并不是很好,远远达不到本地代码调用本地代码Dll的性能,所谓P/Invoke的性能不好并非是本地代码的执行效率问题,P/Invoke不会影响到非托管代码的执行,只是调用过程中的开销比较大,也就是说高密度频繁调用小量的高效率代码的代价可能会超过纯粹的托管代码,其效率损耗主要在托管类型与本地类型的相互转换上,以及非托管Dll的加载与释放上,所以使用P/Invoke非常适合足够规模一整块的高效率代码调用,而非频繁的小规模调用,小规模高密度频繁的P/Invoke调用往往在性能上得不偿失。

如何在程序中实现对三维模型的旋转

 如何在程序中实现对三维模型的旋转——探讨旋转过程中,程序所需要的变量与及计算原理

作者:KT

在程序中,通过鼠标旋转3D模型最常用的方法应该就是——轨迹球 

参考了国外的博客文章和同济大学高等数学下册之后,终于能初步明白这种轨迹球的计算原理,

我看了一下高数,把一些公式的推导过程也列出来了。

本日志的文字,图片以及推导过程,都是我利用软件和参考书籍完成的,尽量力求正确了

如果发现错误存在,请联系本人

阅读可能有一定的难度,毕竟最近才开始写技术类文章。

模拟效果示意图——用两张图片模拟一下效果,本日志旨在理论上进行分析

如何在程序中实现对三维模型的旋转

第一 : 简单介绍

我们在显示器所看到的屏幕是二维平面(只有X和Y),因此鼠标的坐标也就有X和Y坐标,那么将屏幕看成是一个平面,在这个平面后面,虚构一个球体(轨迹球,3D模型就位于轨迹球之内),然后屏幕平面捕捉鼠标的坐标,然后将鼠标的坐标投影到球面上!(下图效果示意图)

——轨迹球旋转带动3D模型旋转?可以这样理解,不过具体解释,后面会有!

图中鼠标点击在屏幕平面时,必须将其投影至背后虚构的轨迹球球面上!

第二:坐标转换

屏幕平面是二维坐标,而虚构的球体是三维坐标,很明显是不能将鼠标的坐标(X,Y)直接投影成三维坐标(X,Y,Z) 

因此这个时候需要进行坐标维数的转换!

——二维坐标能够转换成三维坐标吗?答案是可以,虽然二维坐标只有(x,y),但是将二维坐标通过合理变化后,再利用x坐标值和y坐标值就能计算出z坐标值,后面我会写上详细的公式推导过程。

下图就是转化示意图,强调一点,这个是前视图的投影图来的,两个正方形都是屏幕平面的正面!

 好,现在鼠标点击了屏幕平面,那么就必须利用一定的变化公式将这个点转变为三维坐标点!——即计算圆形中X和Y的值

注意三维图中的1和-1是相对数,代表1个单位,不是具体的值,因此三维图中的X和Y是相对值,即百分比!

Px、Py分别是鼠标的X坐标和Y坐标,这个在程序中是可以直接捕获得知数据的!

公式如下:

 

解释:因为三维图的中心点 (0,0) 在二维图中是(width/2,height/2),

三维图中,中心点(0,0)到上下左右边的距离为width/2,height/2,而且到上下左右四边的标记距离都是1个单位!
即width/2就是三维图中X轴的1个单位,height/2就是Y轴的1个单位 

px-width/2 就是该点在三维图中距离竖轴的距离,然后将该值除以width/2就能得出这段距离占1个单位的比例!——即 X 值!

 

那么Y的公式就是:

这样是错的!错的!

为什么,我们观察下,二维图中的Y轴,这个这里取的是Y的负半轴!所以Py应该是负值,

但是在三维图中,我们看到投影的点的坐标(x,y)是在[1,1]的正半轴区间内,y的值肯定是正数,所以要将上面计算出来的Y值取相反数!

正确的公式是:

 一开始我也没有想明白,结果算错了,不过事后发现这里的推导还是很简单

如果大家还是不明白这一点的话,那么可以这样理解,首先利用

计算出来的y必定是负数,因为Py只能为负(二维坐标中,取的是Y的负半轴) ,好那么这样计算出来的投影点坐标应该是x为正,y为负,在[1,-1]区间内,那么这个点很明显与实际的投影点是关于中心横轴对称的,如图所示

那么计算错误的投影点Y 与 正确投影点的 Y 就应该是关于中心横轴对称的,互为相反数,因此对错误的Y取相反数就就能取得正确点的Y值,这样理解起来应该没问题了!

好了,现在我们已经拿到了投影点的X值和Y值了,那么正如前面所言,通过X和Y计算Z值!

在球体中 有一公式:

 

 其中r是球体半径

公式推导:

首先需要预习一下向量的基础知识——翻起了高等数学 – -!

         

    向量a , 向量 b , 向量 c

    a+b=c  这个向量公式,大家应该都记得吧

那么开始进入球体公式推导

首先 a+b=c  , c+e=f  f 就是球面半径的向量   那么就是 f=c+e=a+b+e  求出向量的模的话,就是 

 其实 a的模就是x坐标值,b的模就是y坐标值,e就是z坐标值!

如果还是不懂话 ,直接用勾股定理吧 (x,y,z轴都是互相垂直的!)

好了,公式

 得证了,那么

Z坐标值计算公式:

 因为球体半径r=1 所以,最终公式为

好啦,二维坐标转为三维坐标的计算完成, 得到了在轨迹球面上的投影点坐标(x,y,z)!

第三:点与点之间的旋转


旋转示意图

 

示意图说明:鼠标投影点从v1处从移动到v2处,旋转轴的概念就等同于地球的地轴——这样说应该能明白了吧

如果要实现轨迹球旋转,就必须获得v1,v2,θ和旋转轴!

v1,v2可以用第二步中的坐标转换得到,

那么这里主要是计算出 θ和旋转轴

这里也是需要一些背景知识,其实大家都学过,还是向量

我借用书本上的例子来说几点——两向量的数量积!  两向量的向量积!

书本例子:——已经懂的可以跳过

同济大学高等数学第六版下册P13

 设一物体在恒力F作用下沿直线从点M1移动到点M2,以S表示位移量M1M2,那么F所作的功的计算:

F看成是a向量

s看成是b向量 那么就有

a*b=|a| |b| cos(θ)

所以得到

 

好,这样我们就可以利用这个公式在轨迹图中计算θ值了

θ求出来了,那么旋转轴呢!

其实旋转轴 

Axis=v1 * v2 

因为对于向量a,向量b,向量c,

若c=a x b ,那么c就是必须与a,b都垂直的!

很明显旋转轴Axis是与v1和v2垂直的!满足于c=a x b!

所以Axis=v1 * v2 

关于这点 具体解释 请见同济大学高等数学第六版下册P17


好,回答之前的问题

问:是轨迹球旋转带动3D模型旋转?

答:我现在的观点是,轨迹球是虚构存在的一个球,为了能够让程序在计算过程中获得一个球体曲面而虚构出来的立体图形,它的作用不是实现旋转,是为了将我们在程序(显示器屏幕平面)所点击的鼠标坐标转化为一个在球面上的坐标,我们看到的程序是一个平面,但是我们已经通过这个虚构的轨迹球将我们的操作球立体化了,那就相当于我们是在球面上操作着鼠标!然后计算出旋转所需数据,传递给3D模型,使其发生旋转变化!轨迹球就是一个为了满足计算而提供曲面的虚构立体图形!


这里我想用一句简单的话话概括这篇日志的重点

——虽然我们看到的是一个平面,但是我们在这平面背后操作的是一个立体图形!

——————————————————————————————


好了,现在能够计算出v1,v2,θ和旋转轴,这个四个东西已经能够满足一般的旋转动画的变量需求了,一般的3D模型旋转动画程序都是需要这四个变量——当然还有一些很强劲的dll提供的接口已经是很人性化了,只将二维的鼠标坐标跟3D模型传进去函数即可。虽然我弄了这些这些公式推导,但在实际生活中,我也会试着去找别人写好高级类库来完成工作,因为这个理论的推导用的是球体,忽略了3D模型的具体外在形式,现实生活中的模型,不可能那么完美的嵌入到球体中,有可能是需要椭圆体,这个时候利用上面的推导会出现很严重的快速转移错误——因为高度变窄,鼠标稍微移动就能产生大幅度的旋转,这种旋转是快速而错误的!

这仅仅是一个问题,还有各种变焦,摄像机角度更换的更深层次的

Raspberry Pi Configuration Settings

################################################################################
##  Raspberry Pi Configuration Settings
##
##  Revision 14, 2012/10/22
##
##  Details taken from the eLinux wiki
##  For up-to-date information please refer to wiki page.
##
##  Wiki Location : http://elinux.org/RPi_config.txt
##
##
##  Description:
##    Details of each setting are described with each section that begins with
##    a double hashed comment ('##')
##    It is up to the user to remove the single hashed comment ('#') from each
##    option they want to enable, and to set the specific value of that option.
##
##  WARNING: Setting the following combination of parameters will set a
##  permanent bit within the SOC and your warranty is void.
##    over_voltage>0, and at least one of the following:
##      force_turbo=1
##      current_limit_override=0x5A000020
##      temp_limit>85
##
##  Overclock settings will be disabled at runtime if the SoC reaches temp_limit
##
################################################################################

################################################################################
##  Standard Definition Video Settings
################################################################################

## sdtv_mode
##     defines the TV standard for composite output
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Normal NTSC (Default)
##     1        Japanese version of NTSC - no pedestal
##     2        Normal PAL
##     3        Brazilian version of PAL - 525/60 rather than 625/50, different
##              subcarrier
##
#sdtv_mode=0

## sdtv_aspect
##     defines the aspect ratio for composite output
##
##     Value    Description
##     -------------------------------------------------------------------------
##     1        4:3 (Default)
##     2        14:9
##     3        16:9
##
#sdtv_aspect=1

## sdtv_disable_colourburst
##     Disables colour burst on composite output. The picture will be
##     monochrome, but possibly sharper
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Colour burst is enabled (Default)
##     1        Colour burst is disabled
##
#sdtv_disable_colourburst=1

################################################################################
##  High Definition Video Settings
################################################################################

## hdmi_safe
##     Use "safe mode" settings to try to boot with maximum hdmi compatibility.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Disabled (Default)
##     1        Enabled (this does: hdmi_force_hotplug=1, config_hdmi_boost=4,
##                                  hdmi_group=1, hdmi_mode=1,
##                                  disable_overscan=0)
##
#hdmi_safe=1

## hdmi_force_hotplug
##     Pretends HDMI hotplug signal is asserted so it appears a HDMI display
##     is attached
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Disabled (Default)
##     1        Use HDMI mode even if no HDMI monitor is detected
##
#hdmi_force_hotplug=1

## hdmi_ignore_hotplug
##     Pretends HDMI hotplug signal is not asserted so it appears a HDMI
##     display is not attached
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Disabled (Default)
##     1        Use composite mode even if HDMI monitor is detected
##
#hdmi_ignore_hotplug=1 

## hdmi_drive
##     chooses between HDMI and DVI modes
##
##     Value    Description
##     -------------------------------------------------------------------------
##     1        Normal DVI mode (No sound)
##     2        Normal HDMI mode (Sound will be sent if supported and enabled)
##
#hdmi_drive=2

## hdmi_ignore_edid
##     Enables the ignoring of EDID/display data
##
#hdmi_ignore_edid=0xa5000080

## hdmi_edid_file
##     Read the EDID data from the edid.dat file instead of from the attached
##     device
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Read EDID data from attached device (Default)
##     1        Read EDID data from edid.txt file
##
#hdmi_edid_file=1

## hdmi_force_edid_audio
##     Pretends all audio formats are supported by display, allowing
##     passthrough of DTS/AC3 even when not reported as supported.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Use EDID provided values (Default)
##     1        Pretend all audio formats are supported
##
#hdmi_force_edid_audio=1

## avoid_edid_fuzzy_match
##     Avoid fuzzy matching of modes described in edid.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Use fuzzy matching (Default)
##     1        Avoid fuzzy matching
##
#avoid_edid_fuzzy_match=1

## hdmi_group
##     Defines the HDMI type
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Use the preferred group reported by the edid (Default)
##     1        CEA
##     2        DMT
##
#hdmi_group=1

## hdmi_mode
##     defines screen resolution in CEA or DMT format
##
##     H means 16:9 variant (of a normally 4:3 mode).
##     2x means pixel doubled (i.e. higher clock rate, with each pixel repeated
##                                  twice)
##     4x means pixel quadrupled (i.e. higher clock rate, with each pixel
##                                     repeated four times)
##     reduced blanking means fewer bytes are used for blanking within the data
##                      stream (i.e. lower clock rate, with fewer wasted bytes)
##
##     Value    hdmi_group=CEA                  hdmi_group=DMT
##     -------------------------------------------------------------------------
##     1        VGA                             640x350   85Hz
##     2        480p  60Hz                      640x400   85Hz
##     3        480p  60Hz  H                   720x400   85Hz
##     4        720p  60Hz                      640x480   60Hz
##     5        1080i 60Hz                      640x480   72Hz
##     6        480i  60Hz                      640x480   75Hz
##     7        480i  60Hz  H                   640x480   85Hz
##     8        240p  60Hz                      800x600   56Hz
##     9        240p  60Hz  H                   800x600   60Hz
##     10       480i  60Hz  4x                  800x600   72Hz
##     11       480i  60Hz  4x H                800x600   75Hz
##     12       240p  60Hz  4x                  800x600   85Hz
##     13       240p  60Hz  4x H                800x600   120Hz
##     14       480p  60Hz  2x                  848x480   60Hz
##     15       480p  60Hz  2x H                1024x768  43Hz  DO NOT USE
##     16       1080p 60Hz                      1024x768  60Hz
##     17       576p  50Hz                      1024x768  70Hz
##     18       576p  50Hz  H                   1024x768  75Hz
##     19       720p  50Hz                      1024x768  85Hz
##     20       1080i 50Hz                      1024x768  120Hz
##     21       576i  50Hz                      1152x864  75Hz
##     22       576i  50Hz  H                   1280x768        reduced blanking
##     23       288p  50Hz                      1280x768  60Hz
##     24       288p  50Hz  H                   1280x768  75Hz
##     25       576i  50Hz  4x                  1280x768  85Hz
##     26       576i  50Hz  4x H                1280x768  120Hz reduced blanking
##     27       288p  50Hz  4x                  1280x800        reduced blanking
##     28       288p  50Hz  4x H                1280x800  60Hz
##     29       576p  50Hz  2x                  1280x800  75Hz
##     30       576p  50Hz  2x H                1280x800  85Hz
##     31       1080p 50Hz                      1280x800  120Hz reduced blanking
##     32       1080p 24Hz                      1280x960  60Hz
##     33       1080p 25Hz                      1280x960  85Hz
##     34       1080p 30Hz                      1280x960  120Hz reduced blanking
##     35       480p  60Hz  4x                  1280x1024 60Hz
##     36       480p  60Hz  4x H                1280x1024 75Hz
##     37       576p  50Hz  4x                  1280x1024 85Hz
##     38       576p  50Hz  4x H                1280x1024 120Hz reduced blanking
##     39       1080i 50Hz  reduced blanking    1360x768  60Hz
##     40       1080i 100Hz                     1360x768  120Hz reduced blanking
##     41       720p  100Hz                     1400x1050       reduced blanking
##     42       576p  100Hz                     1400x1050 60Hz
##     43       576p  100Hz H                   1400x1050 75Hz
##     44       576i  100Hz                     1400x1050 85Hz
##     45       576i  100Hz H                   1400x1050 120Hz reduced blanking
##     46       1080i 120Hz                     1440x900        reduced blanking
##     47       720p  120Hz                     1440x900  60Hz
##     48       480p  120Hz                     1440x900  75Hz
##     49       480p  120Hz H                   1440x900  85Hz
##     50       480i  120Hz                     1440x900  120Hz reduced blanking
##     51       480i  120Hz H                   1600x1200 60Hz
##     52       576p  200Hz                     1600x1200 65Hz
##     53       576p  200Hz H                   1600x1200 70Hz
##     54       576i  200Hz                     1600x1200 75Hz
##     55       576i  200Hz H                   1600x1200 85Hz
##     56       480p  240Hz                     1600x1200 120Hz reduced blanking
##     57       480p  240Hz H                   1680x1050       reduced blanking
##     58       480i  240Hz                     1680x1050 60Hz
##     59       480i  240Hz H                   1680x1050 75Hz
##     60                                       1680x1050 85Hz
##     61                                       1680x1050 120Hz reduced blanking
##     62                                       1792x1344 60Hz
##     63                                       1792x1344 75Hz
##     64                                       1792x1344 120Hz reduced blanking
##     65                                       1856x1392 60Hz
##     66                                       1856x1392 75Hz
##     67                                       1856x1392 120Hz reduced blanking
##     68                                       1920x1200       reduced blanking
##     69                                       1920x1200 60Hz
##     70                                       1920x1200 75Hz
##     71                                       1920x1200 85Hz
##     72                                       1920x1200 120Hz reduced blanking
##     73                                       1920x1440 60Hz
##     74                                       1920x1440 75Hz
##     75                                       1920x1440 120Hz reduced blanking
##     76                                       2560x1600       reduced blanking
##     77                                       2560x1600 60Hz
##     78                                       2560x1600 75Hz
##     79                                       2560x1600 85Hz
##     80                                       2560x1600 120Hz reduced blanking
##     81                                       1366x768  60Hz
##     82                                       1080p     60Hz
##     83                                       1600x900        reduced blanking
##     84                                       2048x1152       reduced blanking
##     85                                       720p      60Hz
##     86                                       1366x768        reduced blanking
##
#hdmi_mode=1

## config_hdmi_boost
##     configure the signal strength of the HDMI interface.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        (Default)
##     1
##     2
##     3
##     4        Try if you have interference issues with HDMI
##     5
##     6
##     7        Maximum
##
#config_hdmi_boost=0

## hdmi_ignore_cec_init
##     Doesn't sent initial active source message.  Avoids bringing
##     (CEC enabled) TV out of standby and channel switch when rebooting.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Normal behaviour (Default)
##     1        Doesn't sent initial active source message
##
#hdmi_ignore_cec_init=1

## hdmi_ignore_cec
##     Pretends CEC is not supported at all by TV.
##     No CEC functions will be supported.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Normal behaviour (Default)
##     1        Pretend CEC is not supported by TV
##
#hdmi_ignore_cec=1

################################################################################
##  Overscan Video Settings
################################################################################

## overscan_left
##     Number of pixels to skip on left
##
#overscan_left=0

## overscan_right
##     Number of pixels to skip on right
##
#overscan_right=0

## overscan_top
##     Number of pixels to skip on top
##
#overscan_top=0

## overscan_bottom
##     Number of pixels to skip on bottom
##
#overscan_bottom=0

## disable_overscan
##     Set to 1 to disable overscan
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Overscan Enabled (Default)
##     1        Overscan Disabled
##
#disable_overscan=1

################################################################################
##  Framebuffer Video Settings
################################################################################

## framebuffer_width
##     Console framebuffer width in pixels. Default is display width minus
##     overscan.
##
#framebuffer_width=0

## framebuffer_height
##     Console framebuffer height in pixels. Default is display height minus
##     overscan.
##
#framebuffer_height=0

## framebuffer_depth
##     Console framebuffer depth in bits per pixel.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     8        Valid, but default RGB palette makes an unreadable screen
##     16       (Default)
##     24       Looks better but has corruption issues as of 2012/06/15
##     32       Has no corruption issues but needs framebuffer_ignore_alpha=1
##              and shows the wrong colors as of 2012/06/15
##
#framebuffer_depth=16

## framebuffer_ignore_alpha
##     Set to 1 to disable alpha channel. Helps with 32bit.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Enable Alpha Channel (Default)
##     1        Disable Alpha Channel
##
#framebuffer_ignore_alpha=0

################################################################################
##  General Video Settings
################################################################################

## display_rotate
##     Rotate the display clockwise or flip the display.
##     The 90 and 270 degrees rotation options require additional memory on GPU,
##     so won't work with the 16M GPU split.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        0 degrees (Default)
##     1        90 degrees
##     2        180 degrees
##     3        270 degrees
##     0x10000  Horizontal flip
##     0x20000  Vertical flip
##
#display_rotate=0

################################################################################
##  Licensed Codecs
##
##  Hardware decoding of additional codecs can be enabled by purchasing a
##  license that is locked to the CPU serial number of your Raspberry Pi.
##
##  Up to 8 licenses per CODEC can be specified as a comma seperated list.
##
################################################################################

## decode_MPG2
##     License key to allow hardware MPEG-2 decoding.
##
#decode_MPG2=0x12345678

## decode_WVC1
##     License key to allow hardware VC-1 decoding.
##
#decode_WVC1=0x12345678

################################################################################
##  Test Settings
################################################################################

## test_mode
##     Enable test sound/image during boot for manufacturing test.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Disable Test Mod (Default)
##     1        Enable Test Mode
##
#test_mode=0

################################################################################
##  Memory Settings
################################################################################

## disable_l2cache
##     Disable arm access to GPU's L2 cache. Needs corresponding L2 disabled
##     kernel.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Enable L2 Cache (Default)
##     1        Disable L2 cache
##
#disable_l2cache=0

## gpu_mem
##     GPU memory allocation in MB for all board revisions.
##
##     Default 64
##
#gpu_mem=128

## gpu_mem_256
##     GPU memory allocation in MB for 256MB board revision.
##     This option overrides gpu_mem.
##
#gpu_mem_256=128

## gpu_mem_512
##     GPU memory allocation in MB for 512MB board revision.
##     This option overrides gpu_mem.
##
#gpu_mem_512=128

################################################################################
##  Boot Option Settings
################################################################################

## disable_commandline_tags
##     Stop start.elf from filling in ATAGS (memory from 0x100) before
##     launching kernel
##
#disable_commandline_tags=0

## cmdline (string)
##     Command line parameters. Can be used instead of cmdline.txt file
##
#cmdline=""

## kernel (string)
##     Alternative name to use when loading kernel.
##
#kernel=""

## kernel_address
##     Address to load kernel.img file at
##
#kernel_address=0x00000000

## ramfsfile (string)
##     ramfs file to load
##
#ramfsfile=""

## ramfsaddr
##     Address to load ramfs file at
##
#ramfsaddr=0x00000000

## initramfs (string address)
##     ramfs file and address to load it at (it's like ramfsfile+ramfsaddr in
##     one option).
##
##     NOTE: this option uses different syntax than all other options - you
##           should not use "=" character here.
##
#initramfs initramf.gz 0x00800000

## device_tree_address
##     Address to load device_tree at
##
#device_tree_address=0x00000000

## init_uart_baud
##     Initial uart baud rate.
##
##     Default 115200
##
#init_uart_baud=115200

## init_uart_clock
##     Initial uart clock.
##
##     Default 3000000 (3MHz)
##
#init_uart_clock=3000000

## init_emmc_clock
##     Initial emmc clock, increasing this can speedup your SD-card.
##
##     Default 100000000 (100mhz)
##
#init_emmc_clock=100000000

## boot_delay
##     Wait for a given number of seconds in start.elf before loading
##     kernel.img.
##
##     delay = (1000 * boot_delay) + boot_delay_ms
##
##     Default 1
##
#boot_delay=0

## boot_delay_ms
##     Wait for a given number of milliseconds in start.elf before loading
##     kernel.img.
##
##     delay = (1000 * boot_delay) + boot_delay_ms
##
##     Default 0
##
#boot_delay_ms=0

## avoid_safe_mode
##     Adding a jumper between pins 5 & 6 of P1 enables a recovery Safe Mode.
##     If pins 5 & 6 are used for connecting to external devices (e.g. GPIO),
##     then this setting can be used to ensure Safe Mode is not triggered.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Respect Safe Mode input (Default)
##     1        Ignore Safe Mode input
##
#avoid_safe_mode=1

################################################################################
##  Overclocking Settings
##
##  ARM, SDRAM and GPU each have their own PLLs and can have unrelated
##  frequencies.
##
##  The GPU core, h264, v3d and isp share a PLL, so need to have related
##  frequencies.
##  pll_freq = floor(2400 / (2 * core_freq)) * (2 * core_freq)
##  gpu_freq = pll_freq / [even number]
##
##  The effective gpu_freq is automatically rounded to nearest even integer, so
##  asking for core_freq = 500 and gpu_freq = 300 will result in divisor of
##  2000/300 = 6.666 => 6 and so 333.33MHz.
##
##
##  Standard Profiles:
##                  arm_freq    core_freq    sdram_freq    over_voltage
##     -------------------------------------------------------------------------
##     None         700         250          400           0
##     Modest       800         300          400           0
##     Medium       900         333          450           2
##     High         950         450          450           6
##     Turbo        1000        500          500           6
##
################################################################################

## force_turbo
##     Control the kernel "ondemand" governor. It has no effect if no overclock
##     settings are specified.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Enable dynamic clocks and voltage for the ARM core, GPU core and
##              SDRAM (Default).
##              Overclocking of h264_freq, v3d_freq and isp_freq is ignored.
##     1        Disable dynamic clocks and voltage for the ARM core, GPU core
##              and SDRAM.
##              Overclocking of h264_freq, v3d_freq and isp_freq is allowed.
##
#force_turbo=0

## initial_turbo
##     Enables turbo mode from boot for the given value in seconds (up to 60)
##     or until cpufreq sets a frequency. Can help with sdcard corruption if
##     overclocked.
##
##     Default 0
##
#initial_turbo=0

## temp_limit
##     Overheat protection. Sets clocks and voltages to default when the SoC
##     reaches this Celsius value.
##     Setting this higher than default voids warranty.
##
##     Default 85
##
#temp_limit=85

## arm_freq
##     Frequency of ARM in MHz.
##
##     Default 700.
##
#arm_freq=700

## arm_freq_min
##     Minimum frequency of ARM in MHz (used for dynamic clocking).
##
##     Default 700.
##
#arm_freq_min=700

## gpu_freq
##     Sets core_freq, h264_freq, isp_freq, v3d_freq together.
##
##     Default 250.
##
#gpu_freq=250

## core_freq
##     Frequency of GPU processor core in MHz. It has an impact on ARM
##     performance since it drives L2 cache.
##
##     Default 250.
##
#core_freq=250

## core_freq_min
##     Minimum frequency of GPU processor core in MHz (used for dynamic
##     clocking). It has an impact on ARM performance since it drives L2 cache.
##
##     Default 250.
##
#core_freq_min=250

## h264_freq
##     Frequency of hardware video block in MHz.
##
##     Default 250.
##
#h264_freq=250

## isp_freq
##     Frequency of image sensor pipeline block in MHz.
##
##     Default 250.
##
#isp_freq=250

## v3d_freq
##     Frequency of 3D block in MHz.
##
##     Default 250.
##
#v3d_freq=250

## sdram_freq
##     Frequency of SDRAM in MHz.
##
##     Default 400.
##
#sdram_freq=400

## sdram_freq_min
##     Minimum frequency of SDRAM in MHz (used for dynamic clocking).
##
##     Default 400.
##
#sdram_freq_min=400

## avoid_pwm_pll
##     Unlink core_freq from the rest of the gpu. Analog audio should still
##     work, but from a fractional divider, so lower quality.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Linked core_freq (Default)
##     1        Unlinked core_freq
##
#avoid_pwm_pll=1

################################################################################
##  Voltage Settings
################################################################################

## current_limit_override
##     Disables SMPS current limit protection. Can help if you are currently
##     hitting a reboot failure when overclocking too high.
##
#current_limit_override=0x5A000020

## over_voltage
##     ARM/GPU core voltage adjust.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     -16      0.8   V
##     -15      0.825 V
##     -14      0.85  V
##     -13      0.875 V
##     -12      0.9   V
##     -11      0.925 V
##     -10      0.95  V
##     -9       0.975 V
##     -8       1.0   V
##     -7       1.025 V
##     -6       1.05  V
##     -5       1.075 V
##     -4       1.1   V
##     -3       1.125 V
##     -2       1.15  V
##     -1       1.175 V
##     0        1.2   V (Default)
##     1        1.225 V
##     2        1.25  V
##     3        1.275 V
##     4        1.3   V
##     5        1.325 V
##     6        1.35  V
##     7        1.375 V (requires force_turbo=1)
##     8        1.4   V (requires force_turbo=1)
##
#over_voltage=0

## over_voltage_min
##     Minimum ARM/GPU core voltage adjust (used for dynamic clocking).
##
##     Value    Description
##     -------------------------------------------------------------------------
##     -16      0.8   V
##     -15      0.825 V
##     -14      0.85  V
##     -13      0.875 V
##     -12      0.9   V
##     -11      0.925 V
##     -10      0.95  V
##     -9       0.975 V
##     -8       1.0   V
##     -7       1.025 V
##     -6       1.05  V
##     -5       1.075 V
##     -4       1.1   V
##     -3       1.125 V
##     -2       1.15  V
##     -1       1.175 V
##     0        1.2   V (Default)
##     1        1.225 V
##     2        1.25  V
##     3        1.275 V
##     4        1.3   V
##     5        1.325 V
##     6        1.35  V
##     7        1.375 V (requires force_turbo=1)
##     8        1.4   V (requires force_turbo=1)
##
#over_voltage_min=0

## over_voltage_sdram
##     Sets over_voltage_sdram_c, over_voltage_sdram_i, over_voltage_sdram_p
##     together
##
##     Value    Description
##     -------------------------------------------------------------------------
##     -16      0.8   V
##     -15      0.825 V
##     -14      0.85  V
##     -13      0.875 V
##     -12      0.9   V
##     -11      0.925 V
##     -10      0.95  V
##     -9       0.975 V
##     -8       1.0   V
##     -7       1.025 V
##     -6       1.05  V
##     -5       1.075 V
##     -4       1.1   V
##     -3       1.125 V
##     -2       1.15  V
##     -1       1.175 V
##     0        1.2   V (Default)
##     1        1.225 V
##     2        1.25  V
##     3        1.275 V
##     4        1.3   V
##     5        1.325 V
##     6        1.35  V
##     7        1.375 V
##     8        1.4   V
##
#over_voltage_sdram=0

## over_voltage_sdram_c
##     SDRAM controller voltage adjust.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     -16      0.8   V
##     -15      0.825 V
##     -14      0.85  V
##     -13      0.875 V
##     -12      0.9   V
##     -11      0.925 V
##     -10      0.95  V
##     -9       0.975 V
##     -8       1.0   V
##     -7       1.025 V
##     -6       1.05  V
##     -5       1.075 V
##     -4       1.1   V
##     -3       1.125 V
##     -2       1.15  V
##     -1       1.175 V
##     0        1.2   V (Default)
##     1        1.225 V
##     2        1.25  V
##     3        1.275 V
##     4        1.3   V
##     5        1.325 V
##     6        1.35  V
##     7        1.375 V
##     8        1.4   V
##
#over_voltage_sdram_c=0

## over_voltage_sdram_i
##     SDRAM I/O voltage adjust.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     -16      0.8   V
##     -15      0.825 V
##     -14      0.85  V
##     -13      0.875 V
##     -12      0.9   V
##     -11      0.925 V
##     -10      0.95  V
##     -9       0.975 V
##     -8       1.0   V
##     -7       1.025 V
##     -6       1.05  V
##     -5       1.075 V
##     -4       1.1   V
##     -3       1.125 V
##     -2       1.15  V
##     -1       1.175 V
##     0        1.2   V (Default)
##     1        1.225 V
##     2        1.25  V
##     3        1.275 V
##     4        1.3   V
##     5        1.325 V
##     6        1.35  V
##     7        1.375 V
##     8        1.4   V
##
#over_voltage_sdram_i=0

## over_voltage_sdram_p
##     SDRAM phy voltage adjust.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     -16      0.8   V
##     -15      0.825 V
##     -14      0.85  V
##     -13      0.875 V
##     -12      0.9   V
##     -11      0.925 V
##     -10      0.95  V
##     -9       0.975 V
##     -8       1.0   V
##     -7       1.025 V
##     -6       1.05  V
##     -5       1.075 V
##     -4       1.1   V
##     -3       1.125 V
##     -2       1.15  V
##     -1       1.175 V
##     0        1.2   V (Default)
##     1        1.225 V
##     2        1.25  V
##     3        1.275 V
##     4        1.3   V
##     5        1.325 V
##     6        1.35  V
##     7        1.375 V
##     8        1.4   V
##
#over_voltage_sdram_p=0

解决Raspberry Pi只能在默认640×480模式下显示的问题

购买Raspberry Pi V2后,还得为他配置其他一些周边器件,如5V2A的micro usb电源线、显示器、键盘、鼠标等。手头上有N多VGA显示器,却没一台DVI的,没办法,淘宝上买了专门针对树莓派生产的电源(18RMB)和hdmi转vga线(70RMB)。

按照网上的一些说法,先通过SSH登录进去,把/boot/config.txt里的几个参数放出:

hdmi_safe=1
disable_overscan=1

overscan_left=-30
overscan_right=-30
overscan_top=-30
overscan_bottom=-30

hdmi_force_hotplug=1

hdmi_group=2
hdmi_mode=16

hdmi_drive=2

config_hdmi_boost=4

注意,必须把hdmi_drive设为2,因为1是DVI输出,2才是hdmi输出,因为我的线是hdmi转vga的。

这样,重新启动Pi后,基本能显示了,可是默认是640×480的,看着非常别扭,网上找了很多资料,包括把如下config.txt部分放开:

framebuffer_width=1280
framebuffer_height=960

貌似分辨率成了1280×960,而实际上是,只是Pi按1280×960输出到屏幕上了,而屏幕的分辨率还是640×480的,所以字体很虚很模糊,几乎看不清。

按理说只要更改

hdmi_group=2   —>1:CEA  2:DMT
hdmi_mode=4   —>从模式列表中选取一种显示模式

就可以切换显示分辨率了,可是怎么改都没啥用。貌似不起任何作用!

幸好看了完整的Raspberry Pi配置说明,发现当hdmi_safe设置为1时,hdmi_group默认为1,hdmi_mode为1,后面你怎么改hdmi_group和hdmi_mode都不起作用了!!!


## hdmi_safe
##     Use "safe mode" settings to try to boot with maximum hdmi compatibility.
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Disabled (Default)
##     1        Enabled (this does: hdmi_force_hotplug=1, config_hdmi_boost=4,
##                                  hdmi_group=1, hdmi_mode=1,
##                                  disable_overscan=0)
##
#hdmi_safe=1

注意看完整的Raspberry Pi配置说明,你会发现,当disable_overscan=1时,overscan_top、overscan_botom、overscan_left、overscan_right几个参数不起作用!

################################################################################
##  Overscan Video Settings
################################################################################

## overscan_left
##     Number of pixels to skip on left
##
#overscan_left=0

## overscan_right
##     Number of pixels to skip on right
##
#overscan_right=0

## overscan_top
##     Number of pixels to skip on top
##
#overscan_top=0

## overscan_bottom
##     Number of pixels to skip on bottom
##
#overscan_bottom=0

## disable_overscan
##     Set to 1 to disable overscan
##
##     Value    Description
##     -------------------------------------------------------------------------
##     0        Overscan Enabled (Default)
##     1        Overscan Disabled
##
#disable_overscan=1

所以,最后我的配置文件是这样的:

pi@raspberrypi:/boot$ vi config.txt 
#hdmi_edid_file=1

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
disable_overscan=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=-30
#overscan_right=-30
#overscan_top=-30
#overscan_bottom=-30

# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720

# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
hdmi_group=2
hdmi_mode=32

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# for more options see http://elinux.org/RPi_config.txt

绝对完美运行。

一个对hdmi_safe=1的不了解,折腾了我这么多天,真是不值啊。

后面写的就不用看了,都是以前走的弯路,那个弯啊,绕啊,希望你们就别走了……

===========================================================

用tvservice -d edid.dat将edid数据导出到edid.dat:

pi@raspberrypi:/opt/vc/bin$ tvservice -d edid.dat
Written 0 bytes to edid.dat

没数据。。。

使用tvservice -s查看当前的显示状态

pi@raspberrypi:~$ tvservice -s
state: HPD high|HDMI mode|HDCP off|composite off (0x12001a), 640x480 @ 60Hz, progressive

的确是640×480 @ 60 Hz显示的。再用-m查看支持的显示,却发现只有一种CEA模式,而DMT模式根本就没有:

pi@raspberrypi:~$ tvservice -m CEA
Group CEA has 1 modes:
           mode 1: 640x480 @ 60Hz, progressive
pi@raspberrypi:~$ tvservice -m DMT
Group DMT has 0 modes:

这就难怪怎么改config.txt中的hdmi_group和hdmi_mode都没用的原因了!!!

网上翻了很多资料,终于发现,只要在config.txt文件开头加入如下信息,重启,终于以更高的分辨率显示了:

hdmi_edid_file=1

hdmi_edid_file默认为0,表示从设备读取edid信息,如果为1,则强制从edid.txt文件读取edid信息。

启动后,进入终端,查看当前状态:

pi@raspberrypi:~$ tvservice -s
state: HPD high|HDMI mode|HDCP off|composite off (0x12001a), 1280x720 @ 60Hz, progressive

可见现在的显示模式是 1280×720 @ 60Hz。

现在hdmi是如下配置的:

hdmi_group=1
hdmi_mode=16

貌似这个值不起作用了。

很疑惑,这个edid.txt文件在哪里???如果不存在,是否可以通过导入一个edit.txt文件来达到配置显示分辨率的目的呢?

 

附:

从这里http://elinux.org/RPiconfig可以看到group和mode的对应关系,相应的修改即可:

These values are valid if hdmi_group=1 (CEA)
hdmi_mode=1    VGA
hdmi_mode=2    480p  60Hz
hdmi_mode=3    480p  60Hz  H
hdmi_mode=4    720p  60Hz
hdmi_mode=5    1080i 60Hz
hdmi_mode=6    480i  60Hz
hdmi_mode=7    480i  60Hz  H
hdmi_mode=8    240p  60Hz
hdmi_mode=9    240p  60Hz  H
hdmi_mode=10   480i  60Hz  4x
hdmi_mode=11   480i  60Hz  4x H
hdmi_mode=12   240p  60Hz  4x
hdmi_mode=13   240p  60Hz  4x H
hdmi_mode=14   480p  60Hz  2x
hdmi_mode=15   480p  60Hz  2x H
hdmi_mode=16   1080p 60Hz
hdmi_mode=17   576p  50Hz
hdmi_mode=18   576p  50Hz  H
hdmi_mode=19   720p  50Hz
hdmi_mode=20   1080i 50Hz
hdmi_mode=21   576i  50Hz
hdmi_mode=22   576i  50Hz  H
hdmi_mode=23   288p  50Hz
hdmi_mode=24   288p  50Hz  H
hdmi_mode=25   576i  50Hz  4x
hdmi_mode=26   576i  50Hz  4x H
hdmi_mode=27   288p  50Hz  4x
hdmi_mode=28   288p  50Hz  4x H
hdmi_mode=29   576p  50Hz  2x
hdmi_mode=30   576p  50Hz  2x H
hdmi_mode=31   1080p 50Hz
hdmi_mode=32   1080p 24Hz
hdmi_mode=33   1080p 25Hz
hdmi_mode=34   1080p 30Hz
hdmi_mode=35   480p  60Hz  4x
hdmi_mode=36   480p  60Hz  4xH
hdmi_mode=37   576p  50Hz  4x
hdmi_mode=38   576p  50Hz  4x H
hdmi_mode=39   1080i 50Hz  reduced blanking
hdmi_mode=40   1080i 100Hz
hdmi_mode=41   720p  100Hz
hdmi_mode=42   576p  100Hz
hdmi_mode=43   576p  100Hz H
hdmi_mode=44   576i  100Hz
hdmi_mode=45   576i  100Hz H
hdmi_mode=46   1080i 120Hz
hdmi_mode=47   720p  120Hz
hdmi_mode=48   480p  120Hz
hdmi_mode=49   480p  120Hz H
hdmi_mode=50   480i  120Hz
hdmi_mode=51   480i  120Hz H
hdmi_mode=52   576p  200Hz
hdmi_mode=53   576p  200Hz H
hdmi_mode=54   576i  200Hz
hdmi_mode=55   576i  200Hz H
hdmi_mode=56   480p  240Hz
hdmi_mode=57   480p  240Hz H
hdmi_mode=58   480i  240Hz
hdmi_mode=59   480i  240Hz H
H means 16:9 variant (of a normally 4:3 mode).
2x means pixel doubled (i.e. higher clock rate, with each pixel repeated twice)
4x means pixel quadrupled (i.e. higher clock rate, with each pixel repeated four times)

 

These values are valid if hdmi_group=2 (DMT)
hdmi_mode=1    640x350   85Hz
hdmi_mode=2    640x400   85Hz
hdmi_mode=3    720x400   85Hz
hdmi_mode=4    640x480   60Hz
hdmi_mode=5    640x480   72Hz
hdmi_mode=6    640x480   75Hz
hdmi_mode=7    640x480   85Hz
hdmi_mode=8    800x600   56Hz
hdmi_mode=9    800x600   60Hz
hdmi_mode=10   800x600   72Hz
hdmi_mode=11   800x600   75Hz
hdmi_mode=12   800x600   85Hz
hdmi_mode=13   800x600   120Hz
hdmi_mode=14   848x480   60Hz
hdmi_mode=15   1024x768  43Hz  DO NOT USE
hdmi_mode=16   1024x768  60Hz
hdmi_mode=17   1024x768  70Hz
hdmi_mode=18   1024x768  75Hz
hdmi_mode=19   1024x768  85Hz
hdmi_mode=20   1024x768  120Hz
hdmi_mode=21   1152x864  75Hz
hdmi_mode=22   1280x768        reduced blanking
hdmi_mode=23   1280x768  60Hz
hdmi_mode=24   1280x768  75Hz
hdmi_mode=25   1280x768  85Hz
hdmi_mode=26   1280x768  120Hz reduced blanking
hdmi_mode=27   1280x800        reduced blanking
hdmi_mode=28   1280x800  60Hz
hdmi_mode=29   1280x800  75Hz
hdmi_mode=30   1280x800  85Hz
hdmi_mode=31   1280x800  120Hz reduced blanking
hdmi_mode=32   1280x960  60Hz
hdmi_mode=33   1280x960  85Hz
hdmi_mode=34   1280x960  120Hz reduced blanking
hdmi_mode=35   1280x1024 60Hz
hdmi_mode=36   1280x1024 75Hz
hdmi_mode=37   1280x1024 85Hz
hdmi_mode=38   1280x1024 120Hz reduced blanking
hdmi_mode=39   1360x768  60Hz
hdmi_mode=40   1360x768  120Hz reduced blanking
hdmi_mode=41   1400x1050       reduced blanking
hdmi_mode=42   1400x1050 60Hz
hdmi_mode=43   1400x1050 75Hz
hdmi_mode=44   1400x1050 85Hz
hdmi_mode=45   1400x1050 120Hz reduced blanking
hdmi_mode=46   1440x900        reduced blanking
hdmi_mode=47   1440x900  60Hz
hdmi_mode=48   1440x900  75Hz
hdmi_mode=49   1440x900  85Hz
hdmi_mode=50   1440x900  120Hz reduced blanking
hdmi_mode=51   1600x1200 60Hz
hdmi_mode=52   1600x1200 65Hz
hdmi_mode=53   1600x1200 70Hz
hdmi_mode=54   1600x1200 75Hz
hdmi_mode=55   1600x1200 85Hz
hdmi_mode=56   1600x1200 120Hz reduced blanking
hdmi_mode=57   1680x1050       reduced blanking
hdmi_mode=58   1680x1050 60Hz
hdmi_mode=59   1680x1050 75Hz
hdmi_mode=60   1680x1050 85Hz
hdmi_mode=61   1680x1050 120Hz reduced blanking
hdmi_mode=62   1792x1344 60Hz
hdmi_mode=63   1792x1344 75Hz
hdmi_mode=64   1792x1344 120Hz reduced blanking
hdmi_mode=65   1856x1392 60Hz
hdmi_mode=66   1856x1392 75Hz
hdmi_mode=67   1856x1392 120Hz reduced blanking
hdmi_mode=68   1920x1200       reduced blanking
hdmi_mode=69   1920x1200 60Hz
hdmi_mode=70   1920x1200 75Hz
hdmi_mode=71   1920x1200 85Hz
hdmi_mode=72   1920x1200 120Hz reduced blanking
hdmi_mode=73   1920x1440 60Hz
hdmi_mode=74   1920x1440 75Hz
hdmi_mode=75   1920x1440 120Hz reduced blanking
hdmi_mode=76   2560x1600       reduced blanking
hdmi_mode=77   2560x1600 60Hz
hdmi_mode=78   2560x1600 75Hz
hdmi_mode=79   2560x1600 85Hz
hdmi_mode=80   2560x1600 120Hz reduced blanking
hdmi_mode=81   1366x768  60Hz
hdmi_mode=82   1080p     60Hz
hdmi_mode=83   1600x900        reduced blanking
hdmi_mode=84   2048x1152       reduced blanking
hdmi_mode=85   720p      60Hz
hdmi_mode=86   1366x768        reduced blanking