3.بررسی مثال VirtualSerial (بخش دوم )
خوب حالا برمیگردیم داخل فایل سورس اصلی برنامه یعنی ، VirtualSerial.c :
در ادامه فایل چیزی که میبینیم یه داده داریم که به صورت Structure که اون هم به صورت لانه ای تعریف شده ( چقدر خفنه !) که به قرار زیر هست :
کد:
typedef struct
{
struct
{
uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */
uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint. */
uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint. */
bool DataINEndpointDoubleBank; /**< Indicates if the CDC interface's IN data endpoint should use double banking. */
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint. */
uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint. */
bool DataOUTEndpointDoubleBank; /**< Indicates if the CDC interface's OUT data endpoint should use double banking. */
uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used. */
uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used. */
bool NotificationEndpointDoubleBank; /**< Indicates if the CDC interface's notification endpoint should use double banking. */
} Config; /**< Config data for the USB class interface within the device. All elements in this section
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
*/
struct
{
struct
{
uint16_t HostToDevice; /**< Control line states from the host to device, as a set of \c CDC_CONTROL_LINE_OUT_*
* masks. This value is updated each time \ref CDC_Device_USBTask() is called.
*/
uint16_t DeviceToHost; /**< Control line states from the device to host, as a set of \c CDC_CONTROL_LINE_IN_*
* masks - to notify the host of changes to these values, call the
* \ref CDC_Device_SendControlLineStateChange() function.
*/
} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
CDC_LineEncoding_t LineEncoding; /** Line encoding used in the virtual serial port, for the device's information.
* This is generally only used if the virtual serial port data is to be
* reconstructed on a physical UART.
*/
} State; /**< State data for the USB class interface within the device. All elements in this section
* are reset to their defaults when the interface is enumerated.
*/
} USB_ClassInfo_CDC_Device_t;
خوب اول ،
مختصری در مورد Structure
خوب ببینید ما تو زبان سی انواع داده داریم مثل char, int , float ,unsigned char,unsigned iint,long in و ... که همونطور که میدونید میتونیم با استفاده از پیشوندها ترکیبات جدید بسازیم اما اینها همگی به یک نوع داده خاص دلالت میکنند ، یعنی ما نمیتونیم تو یه داده از نوع int هم کاراکتر بریزیم هم عدد !
خوب فرض کنید که سازمان ثبت احوال میخواد اطلاعات هر نفر رو اعم از نام ، نام خانوادگی ، نام پدر ، تاریخ تولد ، محل صدور، شماره شناسنامه، کد ملی و ... رو تو یه متغیر ذخیره کنه .
خوب اگه بخواد این ها رو ذخیره کنه باید برای اون هایی که به صورت کارکتر هستند بیاد یه آرایه دو بعدی که بعد اولش تعداد کاراکتر های مورد نیاز برای هر نفر و آرایه دومش تعداد آدم ها هستند رو از نوع char تعریف کنه و برای اون هایی که از نوع عدد هستند باید برای یه ارایه دوبعدی تعریف کنه که تو بعد اول تعداد درایه مورد نیاز برای اون اطلاعات خاص و تو بعد دوم تعداد آدم ها رو از نوع مثلا int تعریف کنه .
خوب حالا این به خودش میگه چی میشد من یه متغیر داشتم که به اندازه آدم ها آرایه داشت و تو همون متغیر اطلاعات رو وارد میکردم . خوب این آقا چیزی که میخواد اینه که یه نوع داده باشه ، 120 بایتی ، که تو مثلا 100 بایت اولش بشه کارکتر گذاشت تو 20 بایت بعدش عدد بعد هم به صورت آرایه تک بعدی باشه و بعدش هم به اندازه تمام آدم ها باشه .
خوب همونطور که میدونید ما همچین چیزی تو زبان سی نداریم ، پس باید این "نوع داده جدید رو ایجاد کنیم " این کار با استفاده از دستور struct به فرم کلی زیر انجام میشه :
کد:
struct "اسم نوع داده جدید"{
لیست عناصر داده ;
};
مثلا فرض کنید میخواییم همین نوع داده ای که سازمان ثبت احوال لازم داره رو ایجاد کنیم ،مینویسیم :
کد:
struct personal{
char first_name[20];
char last_name[20];
char father_name[20];
int date_of_birth;
};
خوب این از نوع داده جدید .
اما ما که صرفا نمیخواییم فقط یه نوع داده تعریف کنیم ،مگه نه !؟
چیزی که سازمان ثبت احوال میخواست "یه متغیر با یه نوع داده جدید" بود.
پس باید متغیر هامون رو هم با نوع داده جدید تعریف کنیم تا بتونیم ازشون برای کاری که می خواهیم استفاده کنیم .
فرم کلی تعریف متغیر مثل تعریف متغیر های معمولی هست که به قرار زیر هست :
کد:
struct "اسم متغیر" "اسم نوع داده جدید"
یا مثلا همون موقع که نوع رو ایجاد میکنیم ، پشت بندش متغیر ها مون رو هم تعریف میکنیم ، تو این حالت در صورت عدم نیاز به این نوع داده جدید برای تعریف متغیر هایی از این جنس داده در مکان های دیگه میتونیم از اسم نوع داده جدید فاکتور بگیریم و حذفش کنیم ، به صورت زیر :
کد:
struct {
لیست عناصر داده ;
} "اسم متغیر"
خوب حالا میتونیم یه متغیر با اون نوع داده ای که سازمان ثبت احوال میخواست ایجاد کنیم ، اسم متغیر رو هم person میزاریم و از نوع personal(که قبلا این توع داده رو تعریفش کردیم) رو به صورت یه متغیر مثلا 1000 درایه ای که قراره تو هر داریه مشخصات یه نفر قرار بگیره ، به صورت زیر تعریف میکنیم :
کد:
struct personal person[1000];
یا :
کد:
struct {
char first_name[20];
char last_name[20];
char father's_name[20];
int date_of_birth;
}person[1000];
خوب حالا برای دسترسی به هر کدوم از عناصر متغیر جدید مون که به صورت ساختمان داده هست باید از "." استفاده کنیم .
مثلا فرض کنید که میخواییم اطلاعات شخص شماره 20 رو برای سازمان ثبت احوال ثبت کنیم ، داریم :
کد:
person[20].first_name="ali";
person[20].last_name="taghipour";
person[20].father_name="hasan";
person[20].date_of_birth=1370;
خوب حالا فرض کنید که سازمان احوال بخواد اطلاعات رو برحسب آدرس که شامل استان ، شهر ، خیابان ،کوچه و پلاک محل زندگی افراد sort کنه و همینطور تاریخ تولید افراد ، روز ، ماه و سالش هم مشخص باشه .
خوب به نظرتون باید اینجا چه کار کرد !؟
خوب یه راه حل اینه که بیاییم از ساختمان داده به صورت لانه ای استفاده کنیم ، یعنی چی؟
ببینید همونطور که دید تا اینجا عناصرساختمان نوع داده های جدید که تعریف کردیم از نوع داده های استاندارد زبان سی بود ، حالا این عناصر میتونند از نوع یه ساختمان داده جدید که قبلا ایجادشون کرده بودیم باشند .
خوب پس برای این مورد آخر یعنی اعمال آدرس و تاریخ تولد بر حسب روز ماه و سال کاری که به نظر من میرسه ، میشه از این تکنیک تعریف ساختمان ها به صورت لانه ای استفاده کرد به ترتیب زیر :
1. بیاییم اول ساختمان داده آدرس که شامل عناصر : استان ، شهر خیابان ، کوچه و پلاک هست به صورت زیر تعریف کنیم :
کد:
struct address {
char town[20];
char city[20];
char street[20];
char alley[20];
int no;
};
2. بیاییم ساختمان داده تاریخ رو با عناصر روز ، ماه و سال به صورت زیر تعریف کنیم :
کد:
struct date{
int day;
int month;
int year;
};
3. حالا بیاییم ساختمان داده اصلی که متغیر مشخصات افراد از اون نوع تعیین میشه به صورت زیر بنویسیم :
کد:
struct {
char first_name[20];
char last_name[20];
char father_name[20];
struct address addr;
struct date birth;
}person[1000];
حالا بجای اینکه بیاییم جدا جدا ساختمان داده رو تعریف کنیم و بعد بیاییم از اون ساختمان دادهذ برای تعریف یه متغیر جدید داخل یه ساختمان داده دیگه استفاده کنیم اون ساختمان داده و متغیر از اون جنس رو هم داخل همون ساختمان داده اصلی تعریف میکنیم مثلا برای مثال قبل داریم :
کد:
struct {
char first_name[20];
char last_name[20];
char father_name[20];
struct {
char town[20];
char city[20];
char street[20];
char alley[20];
int no;
}addr;
struct{
int day;
int month;
int year;
}birth;
}person[1000];
خوب حالا بیایید مثلا مشخصات همون نفر 20 ام رو دوباره وارد کنیم :
کد:
person[20].first_name="ali";
person[20].last_name="taghipour";
person[20].father_name="hasan";
person[20].birth.day=31;
person[20].birth.month=6;
person[20].birth.year=1370;
person[20].addr.town="Tehran";
person[20].addr.city="Eslamshahr";
person[20].addr.street="Emam khomyni";
person[20].addr.alley="Shahid kazemi";
person[20].addr.no=51;
خوب تا همین جا از مبحث Structure برای کار ما تو اینجا کافیه .
دوستان ببخشید دیگه کم آوردم ادامه باشه برای پست بعدی!انشالله.
پایان قسمت سوم