قبلا در مطلب “معرفی قابلیت QuecOpen در ماژول های کویکتل” در مورد QuecOpen صحبت کردیم و اشاره کردیم که به کمک این قابلیت میتونیم کدنویسی خودمون رو روی ماژول انجام بدیم و نیازی به کنترلر خارجی نداشته باشیم ، حالا در این آموزش میخوایم نحوه اجرای یک Hello World رو روی EC200U بررسی کنیم ،پس با سیسوگ همراه باشید.
برای کدنویسی این ماژول ما IDE خاصی نداریم ، تنها چیزی که داریم یه SDK هست که البته غیر از اون هم به چیز دیگه ای نیاز نداریم ، شما میتونید برای ادیت کد ها از هر ادیتوری که میخواید استفاده کنید.
کامندهایی که برای بیلد کردن پروژه موجود هستند هم ، قابل اجرا توی ویندوز و لینوکس هستند ، ما برای نوشتن این مطلب از ویندوز استفاده میکنیم.
اول از همه باید پوشه sdk رو اکسترکت کنیم ، تصویر زیر ساختار این پوشه رو نشون میده
وارد پوشه sdk میشیم و برای اطمینان از درست بودن فایل هامون ، قبل از اینکه تغییری در اونها بدیم یکبار پروژمون رو build میکنیم. برای اینکار از PowerShell استفاده میکنیم و دستور زیر رو اجرا میکنیم
1 | .\build_all.bat new EC200UEU_AA appimage |
در صورت موفقیت آمیز بودن با این پیغام مواجه میشیم
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ... .\hex\flash_test_fdl.elf .\hex\flash_test_fdl.img .\hex\flash_test_fdl.map .\hex\partinfo.bin 30 File(s) copied 1 file(s) moved. 1 file(s) moved. D:\LTE01R02A05_C_SDK_U\target\EC200UEU_AA_APPIMAGE\prepack\8915DM_cat1_open-cat1_UIS8915DM_BB_RF_SS_NoVolte_cus-release.pac 1 file(s) moved. .\target.cmake 1 File(s) copied .\hex\examples\APPIMAGE_APP.elf .\hex\examples\APPIMAGE_APP.img .\hex\examples\APPIMAGE_APP.map .\hex\examples\APPIMAGE_APP.pac .\hex\examples\APPIMAGE_APP.sign.img .\hex\examples\APPIMAGE_APP_prepack.cpio 6 File(s) copied 1 file(s) moved. 1 file(s) moved. 1 file(s) moved. Sat 05/28/2022 START TIME: 17:09:41.39 END TIME: 17:11:20.16 PS D:\LTE01R02A05_C_SDK_U> |
خب حالا میریم سراغ نوشتن کد خودمون…
اول از همه باید بگم که sdk به صورت دیفالت شامل app های کوچیک هست که هر کدومشون یه کاری رو انجام میدند و هر کدوم هم توی یک thread جدا اجرا میشند ، نقطه شروع پردازنده هم برای پردازش کد ها فایل ql_init.c توی مسیر components\ql-application\init
هست که تابع appimg_enter
در اون صدا زده میشه.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | int appimg_enter(void *param) { QlOSStatus err = QL_OSI_SUCCESS; ql_task_t ql_init_task = NULL; QL_INIT_LOG("init demo enter: %s @ %s", QL_APP_VERSION, QL_APP_BUILD_RELEASE_TYPE); prvInvokeGlobalCtors(); if(0 == strcasecmp(QL_APP_BUILD_RELEASE_TYPE, "release")) { ql_dev_cfg_wdt(1); //open the kernel log //ql_quec_trace_enable(1); } else { ql_dev_cfg_wdt(0); //close the kernel log //ql_quec_trace_enable(0); } /*Caution: GPIO pin must be initialized here, otherwise the pin status cannot be determined*/ ql_pin_cfg_init(); err = ql_rtos_task_create(&ql_init_task, 1024*4, APP_PRIORITY_NORMAL, "ql_init", ql_init_demo_thread, NULL, 1); if(err != QL_OSI_SUCCESS) { QL_INIT_LOG("init failed"); } return err; } |
همونطور که توی خط 24 کد بالا میبینید ، یک thread جدید ایجاد شده که بدنه تابع اون به این صورت هست :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | static void ql_init_demo_thread(void *param) { QL_INIT_LOG("init demo thread enter, param 0x%x", param); /*Caution:If the macro of secure boot and the function are opened, download firmware and restart will enable secure boot. the secret key cannot be changed forever*/ #ifdef QL_APP_FEATURE_SECURE_BOOT //ql_dev_enable_secure_boot(); #endif #if 0 ql_gpio_app_init(); ql_gpioint_app_init(); #endif #ifdef QL_APP_FEATURE_LEDCFG ql_ledcfg_app_init(); #endif #ifdef QL_APP_FEATURE_AUDIO //ql_audio_app_init(); #ifdef QL_APP_FEATURE_HEADSET_DET //ql_headset_det_app_init(); #endif #endif ... |
در اینجا هر زیر اپلیکیشنی که بخوایم استفاده کنیم میتونیم فعالش کنیم ، ما برای تست Hello World خودمون ، تابع ql_uart_app_init رو از کامنت در میاریم.
1 2 3 | #ifdef QL_APP_FEATURE_UART ql_uart_app_init(); #endif |
حالا به سراغ فایل uart_demo.c
در مسیر components\ql-application\peripheral
میریم . نقطه شروع ما توی این فایل همون تابع ql_uart_app_init
هست که در اون یک thread ایجاد کرده که تابع ql_uart_demo_thread در اون اجرا میشه
1 | ql_rtos_task_create(&uart_task, QL_UART_TASK_STACK_SIZE, QL_UART_TASK_PRIO, "QUARTDEMO", ql_uart_demo_thread, NULL, QL_UART_TASK_EVENT_CNT); |
در ادامه میتونید پارامتر های این تابع رو بررسی کنید
دستورات دیگر RTOS و نحوه پیاده سازی اونها در فایل Quectel_EC200U_Series_QuecOpen_RTOS_Development_Guide_V1.0 به طور کامل توضیح داده شده.
خب ، حالا به تابع ql_uart_demo_thread
میریم
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | static void ql_uart_demo_thread(void *param) { int ret = 0; QlOSStatus err = 0; ql_uart_config_s uart_cfg = {0}; int write_len = 0; ql_uart_tx_status_e tx_status; unsigned char data[] = "hello uart demo\r\n"; /*********************************************************** Note start: 1.If the BAUD rate is QL UART BAUD_AUTO,a string of 'at'should be sent at least once to identify the baud rate. 2.Once the baud rate is identified, it cannot be changed unless restarted. ************************************************************/ uart_cfg.baudrate = QL_UART_BAUD_115200; uart_cfg.flow_ctrl = QL_FC_NONE; uart_cfg.data_bit = QL_UART_DATABIT_8; uart_cfg.stop_bit = QL_UART_STOP_1; uart_cfg.parity_bit = QL_UART_PARITY_NONE; ret = ql_uart_set_dcbconfig(QL_UART_PORT_2, &uart_cfg); QL_UART_DEMO_LOG("ret: 0x%x", ret); if(QL_UART_SUCCESS != ret) { goto exit; } /*********************************************************** Note start: 1. If QL_UART_PORT_1 is selected for use, there is no need to set TX and RX pin and function 2. According to the QuecOpen GPIO table, user should select the correct PIN to set function 3. CTS and RTS pins (UART2 and UART3) also need to be initialized if hardware flow control function is required ************************************************************/ ret = ql_pin_set_func(QL_UART2_TX_PIN, QL_UART2_TX_FUNC); if(QL_GPIO_SUCCESS != ret) { goto exit; } ret = ql_pin_set_func(QL_UART2_RX_PIN, QL_UART2_RX_FUNC); if(QL_GPIO_SUCCESS != ret) { goto exit; } /*Note end*/ ret = ql_uart_open(QL_UART_PORT_2); QL_UART_DEMO_LOG("ret: 0x%x", ret); if(QL_UART_SUCCESS == ret) { ret = ql_uart_register_cb(QL_UART_PORT_2, ql_uart_notify_cb); QL_UART_DEMO_LOG("ret: 0x%x", ret); memset(&uart_cfg, 0, sizeof(ql_uart_config_s)); ret = ql_uart_get_dcbconfig(QL_UART_PORT_2, &uart_cfg); QL_UART_DEMO_LOG("ret: 0x%x, baudrate=%d, flow_ctrl=%d, data_bit=%d, stop_bit=%d, parity_bit=%d", ret, uart_cfg.baudrate, uart_cfg.flow_ctrl, uart_cfg.data_bit, uart_cfg.stop_bit, uart_cfg.parity_bit); while(1) { write_len = ql_uart_write(QL_UART_PORT_2, data, strlen((char *)data)); QL_UART_DEMO_LOG("write_len:%d", write_len); ql_uart_get_tx_fifo_status(QL_UART_PORT_2, &tx_status); QL_UART_DEMO_LOG("tx_status:%d", tx_status); ql_rtos_task_sleep_ms(20000); } } exit: err = ql_rtos_task_delete(NULL); if(err != QL_OSI_SUCCESS) { QL_UART_DEMO_LOG("task deleted failed"); } } |
همونطور که مشخصه ، توی خط 15 تا 21 تنطیمات UART (مثل BAUD RATE , DATA BIT , …) رو مشخص کرده ، بعد از اون توی خط 34 و 39 کد بالا ، پین های مربوطه رو برای rx و tx مشخص کرده و عملکرد اونها رو برای uart مشخص کرده ؛ الان میخوایم ببینیم که این دو پین QL_UART2_TX_PIN و QL_UART2_RX_PIN از روی سخت افزار کدوم پایه ها میشند ، توی فایل components\ql-application\peripheral\inc\ql_pin_cfg.h
این دو پایه به این صورت تعریف شدند:
1 2 3 | //for uart demo #define QL_UART2_TX_PIN QUEC_PIN_UART2_TXD #define QL_UART2_RX_PIN QUEC_PIN_UART2_RXD |
و بعد از اون توی فایل components\ql-kernel\inc\quec_pin_index.h دوباره به این صورت تعریف شدند:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #define QUEC_PIN_DNAME_SDMMC1_CLK 32 #define QUEC_PIN_DNAME_KEYOUT_4 81 #define QUEC_PIN_DNAME_KEYOUT_5 82 #define QUEC_PIN_DNAME_KEYIN_4 137 #define QUEC_PIN_DNAME_KEYIN_5 138 /*************** Pin ****************/ #define QUEC_PIN_UART2_RXD QUEC_PIN_DNAME_KEYIN_4 #define QUEC_PIN_UART2_TXD QUEC_PIN_DNAME_KEYIN_5 #define QUEC_PIN_UART3_RXD QUEC_PIN_DNAME_KEYOUT_4 #define QUEC_PIN_UART3_TXD QUEC_PIN_DNAME_KEYOUT_5 /*********** EC200U End ***********/ |
و در نهایت پایه های 137 و 138 میشند.
البته این پایه ها روی بردی که در فروشگاه سیسوگ موجود هست به راحتی قابل دسترسیه
شاید به نظر کمی بیهوده بیاد که چندمرحله مختلف برای مشخص کردن یک پین تعریف شده ، اما اینطور نیست ! اگر شما هم از همین استاندارد برای کدنویسی پیروی کنید میتونید بدون تغییر ، کدی که برای مثلا ماژول ec200u نوشتید رو روی eg915u هم استفاده کنید.
به سراغ کد بر میگردیم و توی خط 8 ، متنی که میخوایم چاپ کنیم رو تغییر میدیم
1 | unsigned char data[] = "Hello World\r\n"; |
زمان توقف رو هم از 20 ثانیه به 1 ثانیه کاهش میدیم (خط 65)
1 | ql_rtos_task_sleep_ms(1000); |
با دستور زیر کدمون رو کامپایل میکنیم
1 | .\build_all.bat r EC200UEU_AA appimage |
خروجی ما توی پوشه target\EC200UEU_AA_APPIMAGE قرار میگیره
برای پروگرام نیازه که اول دستور AT+QDOWNLOAD رو برای ماژول ارسال کنیم ، بعد از اون ماژول ریست میشه و یه پورت جدید با نام Diag شناخته میشه
حالا از نرم افزار QFlash نسخه 5.7 استفاده کرده و فایل 8915DM_cat1_open_APPIMAGE_merge.pac رو انتخاب میکنیم و ماژول رو پروگرام میکنیم.
با وصل کردن یک مبدل سریال به پایه های AUX_RXD و AUX_TXD ماژول میتونیم خروجی رو بررسی کنیم.
برای کسب اطلاعات بیشتر و دریافت اطلاعات مورد نیاز و SDK برای کار با QuecOpen این فرم زیر را تکمیل کرده تا با شما تماس گرفته شود.
CMake Error: The source directory “C:/Quectel ec200u” does not appear to contain CMakeLists.txt.
Specify –help for usage, or press the help button on the CMake GUI.
ninja: error: loading ‘build.ninja’: The system cannot find the file specified.
ببخشد
.\build_all.bat new EC200UEU_AA appimage من این دستور در vs code می فرستم با ارور بالا برخورد می کنم برای build کردن می تونید راهنمایم کنید …
اروری که داره میده خیلی واضحه. مشخصا داره میگه من فایل CMakeLists.txt رو پیدا نمیکنم که نشون میده احتمال زیاد توی فولدر اشتباهی دارید دستور رو میزنید. باید تو فولدر اصلی sdk که فایل CMakeLists.txt هست، این دستور رو بزنید
توی اسم فولدر هاتون هم از فاصله استفاده نکنید.
سلام می خواستم ببینم Quec open از Cpp هم پشتیبانی می کند?
سلام. خیر. با c باید کد بزنید
سلام
ببخشید من ی مشکلی که داشتم قبل پروگرم کردن ماژول دستورات اتصال به اینترنت و gps را ساپورت میکرد ولی از وقتی برنامه ریختم روش با پورت usb at هر دستوری مربوط به اینترنت یا gps میفرستم را ارور 58 برمیگردونه.
سلام . در زمان تنظیم sdk ماژول رو به درستی انتخاب کردید ؟
منظور اینکه از همین دستور استفاده کردید ؟
.\build_all.bat new EC200UEU_AA appimage
اگر اینطور هست دستوراتی که استفاده میکنید و ماژول جواب نمیدهد را بفرستید
بله درست انتخاب کردم و بیلد گرفتم و تونستم توی ترمینال hello world ببینم
ولی دستورات gps و اینترنت ساپورت نمیکنه
AT+QGPS
AT+QIACT
AT+QIDEACT
همه رو میزنه
+CME ERROR: invalid command line
سلام وقت بخیر من هم مشکل کاربر ZAHRA رو دارم و تمام AT Command های مربوط به اینترنت را میزنه +CME ERROR: invalid command line
لطفا راهنمایی کنید ممنونم
وقتی ماژول رو روشن میکنم،پورت دیاگ فقط نصب میشه، در حالی که که طبق آموزش های سایت ابتدا باید پورت AT port نصب بشه و بعد از ارسال AT+QDOWNLOAD پورت دیاگ فعال میشه لطفا من رو راهنمایی بفرمایید
درایور های ماژول رو نصب کردید ؟!
سلام ، من یک پکیج دیتای ماژول از طرف شما داشتم 0که وشه SDK و درایور رو داشته ولی وشه tools رو نداره (نرم افزارها ی کار با ماژول بویژه QFLASH ورژن 5.7 را ندارم)
درایور رو نصب کردم ماژول را که روشن می کنم به پورت ها SPRD U2S Diag اضافه میشه ظاهرا درایورهای دریافتی هم مشکل دارند چون با نام Quectel USB هم نیست
سلام مجدد یه پیغام به همون کاربری که براتون ارسال کرده در تلگرام بدید تا اونها را هم براتون ارسال بشه
با تشکر فایل ها ارسال شد. ولی مشکل من در مورد شناخت تنها یک پورت به نام SPRD U2S Diag وجود دارد در حالی که در مستندات ارسالی و سایت با روشن شدن ماژول و اتصال آن به کامپیوتر حداقل دو پورت با پیشوند Quectel دیده میشه