發表文章

ESP8266 RTOS 環境架設

圖片
        最近重新接觸ESP8266,之前是永AiThinker架設好的 eclipse環境編譯,雖然方便可是SDK太舊,升級SDK也很麻煩,到官網看一下發現有新的環境可以使用(ESP-EDF)與ESP8266_RTOS SDK。 1.先下載 MSYS32     -官方提供的載點: 連結 (下面範例將msys32放在C:\) 2.下載 toolcahin:      - 載點 (xtensa-lx106-elf)     -如果SDK低於3.0版         - 載點 (xtensa-lx106-elf) 3.打開 c:\msys32\mingw32.exe 4.創建一個資料夾"esp":      - mkdir -p ~/esp       -進到資料夾          -cd esp 5.Get ESP8266_RTOS_SDK     -git clone  --recursive https://github.com/espressif/ESP8266_RTOS_SDK.git    ESP8266_RTOS_SDK 會下載到 ~/esp/ESP8266_RTOS_SDK中 5.設定路徑 IDF_PATH:    - export IDF_PATH="D:/msys32/home/f4568/esp/ESP8266_RTOS_SDK" 6.安裝 Python packages     - python -m pip install --user -r $IDF_PATH /requirements.txt 7.專案開始 copy get-started/hello_world  到~/esp    -cd ~/esp    -cp -r $IDF_PATH /...

[Ubuntu] 在VirtualBox中使用 comport ( 序列埠 )

圖片
最近在使用新的esp8266 RTOS SDK 在Ubuntu下使用,花了點時間研究怎麼在VirtualBox掛載的Ubuntu下使用: 打開設定 -連接埠號,去裝置管理員內確認 -模式選擇"主機裝置" -路徑打上根埠號一樣字 左邊選擇系統    -打勾 "啟用I/O APIC" 啟動Ubuntu -打開terminal  輸入  dmesg | grep tty     -可以看到ttyS0 打開putty         -設定鮑率 完成 補充: -如果出現  或是  /dev/ttyUSB0 permission denied --方法只要調整權限就可以了   -sudo chmod 777 /dev/ttyS0

C語言筆記-2維陣列初始化

筆記一下,指標的二維陣列如何進行初始化 int ** c = malloc(n * sizeof ( int * )); for ( int i = 0 ;i < n;i ++ ) * (c + i) = malloc(n * sizeof ( int ));

ESP32學習筆記-OTA 注意事項

圖片
這篇主要真對這幾天要使用ESP32開發專案,將examples中直直制專案內朽發現的問題,以及解決的方法 undefined reference to `_binary_ca_cert_pem_start 一開始移植後遇到這個問題,經過搜尋以及嘗試後解決方法如下:        將範例中的server_certs及裡面的ca_certpem 一起複製到自己的專案 打開main.資料夾中的CMakeLists.txt,加入" set(COMPONENT_EMBED_TXTFILES ${IDF_PROJECT_PATH}/server_certs/ca_cert.pem) " E (86336) esp_ota_ops: not found otadata 解決方法法就是 make menuconfig->partition Table->勾選Factory app,  two OTA definitions

ESP32學習筆記-常見的系統API

這篇做一個紀錄,將常用的系統API紀錄在這邊  esp_restart(): 系統軟體重起功能,  esp_chip_info() 得到chip的相關數據,使用方法: /* Print chip information */ esp_chip_info_t chip_info; esp_chip_info( & chip_info); printf( "This is ESP32 chip with %d CPU cores, WiFi%s%s, " , chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "" , (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "" ); printf( "silicon revision %d, " , chip_info.revision); printf( "%dMB %s flash \n " , spi_flash_get_chip_size() / ( 1024 * 1024 ), (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external" );   vTaskDelay(1000 / portTICK_PERIOD_MS) 這個比較偏FreeRTOS的東西,不過在這邊先做紀錄  

C語言筆記-用結構體讓函式可以返回多個資料

C與言的函式無法回傳一個以上的值,不過可以透過回傳一個結構來完成: 範例: #include <stdio.h> #include <stdlib.h> #include <math.h> typedef struct { double width,height; }size_s; size_s width_height ( char * papertype){ return ! strcasecmp(papertype, "A4" ) ? (size_s){.width = 210 ,.height = 297 } : ! strcasecmp(papertype, "Letter" ) ? (size_s){.width = 216 ,.height = 279 } : ! strcasecmp(papertype, "Legal" ) ? (size_s){.width = 2216 ,.height = 356 } : (size_s){.width = NAN,.height = NAN}; } int main ( void ) { size_s a4size = width_height( "A4" ); printf( "width=%g,height=%g \n " ,a4size.width,a4size.height); } 透過 condition?iftrue:else的格式來取代switch,而且也可以放在return後面 "21centry c"一書的作者很提倡這種風格。 除了用結構體之外,也可以用指標透過參數在函式內修改來完成: void width_height ( char * papertype, double * width, double * height); 這種風格是我常用的方法,也是最常見的格式,不過很容易混淆輸入跟輸出。

C語言筆記-結構體的初始化

圖片
一般程式常看到這種結構的初始化方式: direction_s upright={NULL,0,1,1,0}; direction_s upright = { NULL , 0 , 1 , 1 , 0 }; 這種填充式的結構初始化很糟糕,因為必須要記住所有的結構成員順序,這種方式很不人性化 初始化應該使用上標籤: #include <stdio.h> #include <stdlib.h> typedef struct { int one; double two,three,four; }n_str; n_str d = { 100 , .four = 10 , .two = 30 , }; int main ( void ) { printf( "%d %g %g %g" ,d.one,d.two,d.three, d.four); } 從上面的程式碼中可以看到初始化結構成員,順序不用與聲明的一致,編譯器也是可以成功編譯 未聲明的原素初始化為0,沒有初始過的都是設為0 可以混和聲明 在"21 century c"中有這個範例可以參考: #include <stdio.h> #include <stdlib.h> typedef struct { char * name; int left,right,up,down; }direction_s; void this_row (direction_s d); void draw_box (direction_s d); int main ( void ) { direction_s D = {.name = "left" ,.left = 1 }; draw_box(D); D = (direction_s){ "upper right" ,.up = 1 ,.right = 1 }; draw_box(D); draw_box((direction_s){}); return 0 ; } void this_row ...

C語言筆記-用__VA_ARGS__ 完成free_all() 函式向量化

free()是一個長見的函式,不過他一次只能接受一個參數 因此常常在函式尾巴必須加上一堆釋放記憶體的工作: free(ptr1); free(ptr2); free(ptr3); 這樣的程式碼很不美觀,很冗長,寫成這樣: free_all(ptr1,ptr2,ptr3); 完成方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdio.h> #include <stdlib.h> #define Fn_apply(type,fn,...){\ void *stopper_for_apply=(int[]){0};\ type **list_for_apply=(type*[]){__VA_ARGS__,stopper_for_apply};\ \ for(int i=0;list_for_apply[i]!=stopper_for_apply;i++)\ fn(list_for_apply[i]);\ } #define Free_all(...) Fn_apply(void, free,__VA_ARGS__); int main ( void ) { int * x = malloc( 1000 ); int * y = malloc( 1000 ); int * z = malloc( 1000 ); Free_all(x,y,z); } 第5行:     提高安全性, 第6行:     需要一個終止符,卻保不與任何使用中的指標匹配,包括任何的NULL指標。 因此我們使用複合常量形式定義醫包含整數的陣列,並定義一個指向這個陣列的指標。 for迴圈的終止條件所觀察的是指標本身,而不是他指向的東西

C語言筆記-用__VA_ARGS__ 製作Foreach

很常看到陣列或是結構內使用複合常量,例如: char ** strings = ( char * []){ "one" , "two" } 現在將它放入一個For迴圈中。循環得第一部分聲明了這個字串數組,然後開始便歷整個陣列,直到最後的NULL標記。 #include #include typedef char * string; int main ( void ) { string str = "thresad" ; for (string * list = (string[]){ "111" ,str, "ropw" , NULL }; * list; list ++ ) printf( "%s " , * list); } 這樣的程式碼不易閱讀,很雜,所以用宏定易簡化: #include #include typedef char * string; #define Foreach_string(iterator,...) for(string *iterator=(string[]){__VA_ARGS__,NULL};*iterator;iterator++) int main ( void ) { string str = "two" ; Foreach_string(i, "one" ,str, "three" ){ printf( "%s " , * i); } } 此文章內容參考"21 century c"一書,在此做筆記 如須刪除請告知 謝謝

C語言筆記-用__VA_ARGS__ 完程多列表的宏定義

如果現在想要發送兩個任意長度列表,可以這樣做 假設現在程式顯示一個訊息,同時將一個機器獨的錯誤碼發送到日誌: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio.h> #include <stdlib.h> #define fileprintf(...) fprintf(stderr,__VA_ARGS__) #define doubleprintf(human,machine) do{\ printf human;\ fileprintf machine;\ }while(0) int main ( void ) { int x =- 1 ; if (x < 0 ) doubleprintf(( "x is negative(%d) \n " ,x),( "NEGVAL:x=%d \n " ,x)); } 他會被拓展成: 1 2 do {printf ( "x is negative (%d) \n " , x); fileprintf ( "NEGVAL: x=%d \n " , x);} while ( 0 ); 下面試另一個例子: 給出兩列R和C,每個單元(i,j)保持Ri Cj的乘積,此城市的核心是matrix_cross宏 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 #include <stdio.h> #include <stdlib.h> #include <math.h> #define make_a_list(...) (double[]){__VA_ARGS__,NAN} #define matrix_cross(list1,list2) matrix_cross_base(make_a_list list1,\ make_a_list list2) void...

C語言筆記-透過 __VA_ARGS__ 達成可變參數的宏定義

圖片
      C語言中,可改變長度的函式很容易發生問題(之後提到) 不過要做到可改變參數的宏定義式很簡單的,關鍵字是:   __VA_ARGS__ 期展開的結果是給定的原素集合 舉例: #include <stdio.h> #include <stdlib.h> #define forloop(i,loopmax,...) for(int i=0;i<loopmax;i++)\ {__VA_ARGS__} int main ( void ) { int sum = 0 ; forloop(i, 10 ,sum += i;printf( "sum to %i:%i \n " ,i,sum);); } 輸出結果為: 不過實戰上不會這樣使用。 可參考這一篇: isnan與宏定義來做一個可調整輸入參數的功能

C語言筆記-文本處理(3) 用asprintf strdup 做一個實用的可拓展字串的宏定義

用asprintf()把一段文字添加到另一個字串尾部:   asprintf(&s,%s and other string: %s",s,add); 如果今天很多字串要處理,變成 int num=5,id=27; char *s=strdup("select"); asprintf(&s,"%sscol%i\n",s,num); asprintf(&s,"%sfrom tab\n",s); asprintf(&s,"%swhere person id=%i",s,id); 得到: selectscol5 from tab where person id=27 上面這樣看,除了不整潔 也很厭煩, 也有記憶體洩漏的風險在,因為s的原位址中的對向在asprintf向s提供一個心位置時不會被釋放掉,如果生成的字串數量是未知得,長度也是未知就可以透過宏定義來簡化: #define Sasprintf(write_to, ...){ \ char *tmp_string_for_extend=(write_to); \ asprintf(&(write_to),__VA_ARGS__); \ free(tmp_string_for_extend); \ } int main(void) { int i=666; char *q=NULL; char *k="Jack"; Sasprintf(q,"Hello~~ "); Sasprintf(q,"%s %s Nice to meet you  %d.",q,k,i); printf("%s\n",q); } Sasprintf宏加上strdup,差不多100%的字串處理都能應付了,除了一個下面提到的問題乙級偶爾需要使用free外,可以不必續考慮記憶體的問體。 這個問題是:  如果q沒有初始為NULL或是忘記使用strdup,那麼第一次使用Sasprintf宏將會釋放...

C語言筆記-文本處理(2)常數字串的陷阱,用 strdup 處理

以下程式創了兩個字串: include <stdio .h=""> int main(void) {     char *s1="First";     char *s2;     asprintf(&amp;s2,"Second");     printf("%s\n,s1);     printf("%s\n,s2); } 兩種都產生了一個字串,但編譯器會用不同的方式去處理,如果不熟悉就容易造成錯誤。 "First"就是在一個空間規劃好噁的位置上,S1直接指向這個位址,如此的簡單快速 閱讀程式碼s1跟s2的行為是相同的,但是我們無法修改也不能去釋放s1 如果加上: s2[0]='f'; s1[0]='t';   //錯誤 free(s2); free(s1);    //錯誤 s1指定的內容是絕對唯讀的。 這個錯誤在我一開始踏入這行的時候遇過,被折騰了一下子 有一個簡單的方解決方法:strdup。 這是 POSIX的標準函式,字串複製(string duplicate)的簡寫:  char *s3=strdup("First"); "First"也是以硬編碼的方式寫入,但s3視這個常數字串的一份複製,所以可以自由修改。 用strdup就可以用同一種方式處理自串,不用擔心踩雷。 如果不支援strdup,就用asprintf自己寫一個 char *strdup(char const* in){     if(!in) return NULL;     char *out;     asprintf(&amp;out,"%s",in):     return out; }