本帖最后由 沒有你 于 2020-6-21 14:28 編輯
開發(fā)STC單片機最常用的平臺是keil,也可以用IAR for 8051,但是這兩種平臺都只能在Windows平臺上開發(fā)。如果要跨平臺開發(fā)STC單片機的話,比如windows、linux和MacOS,甚至在樹莓派上,那么可以使用SDCC編譯器。SDCC的特點是免費、開源和跨平臺,這個是keil和IAR沒法比的。網(wǎng)上對SDCC的資料總結(jié)不是很詳細,沒有提供一個完整的makefile模板。有一款開源下載工具stcflash可以燒錄STC單片機,因為stcflash是用python實現(xiàn)的,所以很容易做到跨平臺。不過,原作者已經(jīng)多年未更新stcflash了,導(dǎo)致stcflash也只支持一些古董級別類似STC89C51類的單片機的燒錄。我在此基礎(chǔ)上添加了對STC8全系列(STC8A、STC8F、STC8H、STC8G、STC8C)、STC15系列的型號識別和燒錄支持。下圖是在vscode終端用stcflash燒錄STC8A8K64S4A12的過程:
stcflash.PNG (21.25 KB, 下載次數(shù): 170)
下載附件
2020-6-18 00:38 上傳
下圖是在樹莓派4B上對STC8H8K64U的燒錄過程:
截圖_2020-06-21_14-26-05.png (65.21 KB, 下載次數(shù): 154)
下載附件
2020-6-21 14:27 上傳
這樣,無論在windows、linux,MacOS還是樹莓派,只要有安裝python環(huán)境,都可以正常燒錄STC新系列的單片機了。編輯代碼可以采用VScode,VScode擁有強大的插件支持,堪稱宇宙第一編輯器。VScode的特點也是免費、開源和跨平臺。組合VScode+SDCC+stcflash,都是免費、開源和跨平臺,解決了代碼的編輯、編譯和下載的問題。本次對SDCC的介紹分為三部分,第一部分是SDCC的介紹,第二部分是提供一個工程模板和Makefile的實例,第三部分是使用改進開源stcflash對STC8系列單片機的燒錄。下面是第一部分的內(nèi)容。
一、SDCC簡介
SDCC是一款免費開源的編譯器,它支持標準(ANSI C89 / ISO C90,ISO C99,ISO C11 /ISO C17)C編譯。SDCC是由Sandeep Dutta為8位單片機設(shè)計的編譯器,支持MCS51(8051,8052,8031,8032等)、STM8、PIC、DS80C390,HC08,Z80等十幾種架構(gòu)的單片機的編譯。SDCC還是一款跨平臺的編譯器,支持windows、linux和Mac OS,同一個代碼工程可以在不同平臺編譯和調(diào)試。
二、SDCC組成
SDCC主要由可執(zhí)行文件和庫組成,其中,可執(zhí)行文件由如下構(gòu)成:
- 1、sdcc compiler
- 這個是編譯器,可以單純編譯代碼,但是沒有對生成文件進行鏈接
- 2、sdcpp prepocessor
- 這個是預(yù)處理器,可以對頭文件和相關(guān)宏進行預(yù)處理
- 3、sdas assemblers and sdld linker
- 這個是匯編語言處理器和鏈接器,可以編譯匯編語言,并且鏈接所有的生成文件,生成ihx格式的燒錄文件。
- 4、sdbinutils utilties(sdar,sdranlib,sdnm,sdobjcopy)
- 這個主要是由GUN Binutils分離出來的,比如可以用sdobject進行反匯編。
- 5、ucsim simulator
- 這是軟件仿真器
- 6、sdcdb debugger
- 這個是代碼調(diào)試器
- 7、Packihx
- 這個工具可以把ihx后綴的文件轉(zhuǎn)換成hex后綴的文件
- 8、makebin
- 這個工具可以將ihx文件轉(zhuǎn)換成bin文件
- 9、SDCC run-time libraries
復(fù)制代碼
庫由如下構(gòu)成:
- 1、dbuf library
- 2、Boost C++ libraries
復(fù)制代碼
三、SDCC支持的基本數(shù)據(jù)類型
SDCC支持多種數(shù)據(jù)類型,如下圖所示:
數(shù)據(jù)類型.PNG (105.61 KB, 下載次數(shù): 170)
下載附件
2020-6-14 21:58 上傳
編譯器也允許在函數(shù)的任何地方內(nèi)聯(lián)匯編代碼,另外,也可以調(diào)用在匯編中開發(fā)的例程。
四、SDCC的下載和安裝 1、源碼安裝
SDCC源碼.PNG (36.95 KB, 下載次數(shù): 166)
下載附件
2020-6-14 21:58 上傳
如果想要自己編譯的話,可以直接下載源碼編譯安裝。官方給源碼,主要是為了兼容多個平臺,比如x86、ARM v6和ARM v8等。只要在對應(yīng)平臺編譯源碼,就能產(chǎn)生相應(yīng)的可執(zhí)行二進制文件。 對linux而言,源碼的安裝包括三個步驟:配置(configure)、編譯(make)和安裝(make install)。configure文件是一個可執(zhí)行的腳本文件,它有很多選項,在待安裝的源碼目錄下使用命令./configure –help可以輸出詳細的選項列表。其中--prefix選項是配置安裝目錄,如果不配置該選項,安裝后可執(zhí)行文件默認放在/usr /local/bin,庫文件默認放在/usr/local/lib,配置文件默認放在/usr/local/etc,其它的資源文件放在/usr /local/share。可以通過./configure --prefix=目錄,來指定安裝的路徑。 以Ubuntu16.4為例,下載源碼后解壓,然后進入源碼目錄,打開終端輸入- ./configure --disable-pic14-port --disable-pic16-port --prefix=/opt/SDCC/
復(fù)制代碼 這時configure文件會檢測系統(tǒng)是否符合安裝的條件,可能會出現(xiàn)一些錯誤: - 1、缺少bison
- configure: error: Cannot find required program bison
- 解決方法:sudo apt-get install flex bison
- 2、找不到找不到adjacency_list.hpp
- configure: error: boost library not found (boost/graph/adjacency_list.hpp).
- 解決方法:sudo apt-get install libboost-date-time-dev libboost-program-options-dev libboost-system-dev libboost-filesystem-dev libboost-iostreams-dev
- 3、沒有PIC14、PIC16設(shè)備
- failed for device/lib/pic14
- 解決方法:./configure --disable-pic14-port --disable-pic16-port
復(fù)制代碼 如果條件符合,再輸入:make,即可編譯源碼。編譯源碼的過程中,可能出現(xiàn): - 1、fatal error: zlib.h:
- 解決方法: sudo apt-get install zlib1g-dev
復(fù)制代碼等待編譯完成后,輸入:sudo make install,即可安裝SDCC到Ubuntu中,而且安裝目錄就在指定的/usr/SDCC。 如果是自己指定的目錄,需要手動添加環(huán)境變量,按照本例子,輸入: 在最后添加- export PATH=/opt/SDCC/bin:$PATH
復(fù)制代碼 然后再執(zhí)行 使之生效。
卸載SDCC也比較簡單,如果是按照上面的那種,直接刪除/usr/SDCC文件夾即可。如果沒有指定prefix,也可以在源碼目錄輸入(可能有些源碼不帶uninstall),實現(xiàn)自動卸載程序。 2、二進制文件包安裝 如果想方便的話,可以直接下載官方對應(yīng)各個平臺編譯好的二進制文件包,注意根據(jù)不同平臺的選擇下載對應(yīng)的二進制文件。比如window系統(tǒng),是下載exe后綴的文件,還有注意32位系統(tǒng)還是64位系統(tǒng)。Linux平臺的話,比如Ubuntu,可以在終端輸入:sudo apt-get install sdcc,系統(tǒng)會自動下載安裝SDCC及其組件。不過,這種方式安裝的SDCC可能不是最新版本。SDCC官方也提供樹莓派可以直接使用的二進制包,想想直接樹莓派編譯開發(fā)8051單片機也是一件比較有趣的操作! 3、查看SDCC版本 在終端輸入 可以查看sdcc的版本信息。目前我下載使用的SDCC版本為4.0.2版本。
SDCC版本.PNG (13.71 KB, 下載次數(shù): 173)
下載附件
2020-6-14 21:57 上傳
五、SDCC的使用 1、生成文件解析 SDCC支持命令行操作,最常用的命令就是sdcc sourcefile.c,這個命令是編譯并且鏈接生成文件,生成的文件有如下幾種: - sourcefile.asm - 由編譯器創(chuàng)建的匯編文件
- sourcefile.lst - 由匯編器創(chuàng)建的匯編鏈接文件
- sourcefile.rst - 由鏈接編輯器創(chuàng)建的具有鏈接信息更新的匯編鏈接文件
- sourcefile.sym - 由匯編器創(chuàng)建的源文件鏈接標識
- sourcefile.rel - 由匯編器產(chǎn)生的目標文件,可以作鏈接編輯器的輸入
- sourcefile.map - 由鏈接器創(chuàng)建的加載模塊的內(nèi)存映射
- sourcefile.mem - 帶有內(nèi)存使用情況的文件
- sourcefile.ihx - 以Intel hex forma格式的加載模塊
復(fù)制代碼 2、多個源文件編譯 如果只有一個源文件,可以直接用sdcc xxx.c命令編譯生成ihx文件。對于多個源文件,可以分別編譯源文件產(chǎn)生目標文件,最后將所有目標文件鏈接起來就行。 假設(shè)現(xiàn)在同一個目錄下有三個源文件:foo1.c、foo2.c和foolmain.c,其中main函數(shù)在foolmain.c里。有兩種方法編譯: - sdcc -c foo1.c
- sdcc -c foo2.c
- sdcc -c foomain.c
- sdcc foomain.rel foo1.rel foo2.rel
復(fù)制代碼解釋:sdcc -c foo1.c告訴SDCC編譯但是不鏈接文件,編譯后產(chǎn)生目標文件foo1.rel。sdcc foomain.rel foo1.rel foo2.rel則是告訴SDCC鏈接foomain.rel需要依賴foo1.rel和foo2.rel,最后可以生成ihx文件 - sdcc -c foo1.c
- sdcc -c foo2.c
- sdcc foomain.c foo1.rel foo2.rel
復(fù)制代碼解釋:這個和上面的步驟是等價的。sdcc foomain.c foo1.rel foo2.rel告訴SDCC編譯和鏈接foomain.c需要依賴foo1.rel foo2.rel。 3、生成hex文件 所有源文件編譯鏈接完成后,會產(chǎn)生ihx后綴的文件,這個文件無法支持用STC-ISP燒錄單片機,所以需要將ihx轉(zhuǎn)成hex文件。首先找到SDCC的安裝目錄下的bin目錄,復(fù)制packihx文件到源文件目錄下,然后在終端輸入packihx xxx.ihx > xxx.hex,然后就可以生成hex文件了。 4、其他選項 SDCC還有許多其他命令可以選擇,比如: - sdcc --code-loc 0x2000 source.c,可以指定程序從0x2000開始存放
- sdcc --opt-code-speed source.c,可以讓SDCC對代碼的運行速度做優(yōu)化
- Sdcc --model-large source.c,可以指定單片機的數(shù)據(jù)存儲模型為large。
- sdcc -mmcs51 source.c可以選擇目標處理器為MCS51,這個也是SDCC的默認選項,可以不用指定。但是如果要編譯STM8單片機的源文件,則要sdcc -mstm8 source.c,指定STM8。為目標處理器。
復(fù)制代碼 此外,還有許多其他選項,有興趣的可以查看官方說明手冊,鏈接: http://sdcc.sourceforge.net/doc/sdccman.pdf六、存儲類型 MCS51內(nèi)部存儲類型如下圖所示:
存儲類型.PNG (34.9 KB, 下載次數(shù): 178)
下載附件
2020-6-14 21:58 上傳
1、__data/__near 這個是默認的存儲類型,聲明變量被分配到8051內(nèi)存存儲器RAM的可直接尋址的地址空間data里。訪問此類型變量也是速度最快的 使用如下: - __data unsigned char value;
復(fù)制代碼 2、__xdata/__far 這種存儲類型聲明的變量被分配到外部存儲器RAM(xdata)中去,這個是large數(shù)據(jù)存儲模型單片機的默認地址分配(意思就是如果指定-model-large數(shù)據(jù)存儲模型,定義變量就算不加__xdata,變量也會被自動分配到外部存儲器RAM(xdata)中) 使用如下: - __xdata unsigned char value;
復(fù)制代碼 3、__idata 這種存儲器類型的聲明被分配到8051內(nèi)部存儲器RAM的間接尋址空間(idata) 使用如下: - __idata unsigned char value;
復(fù)制代碼4、__pdata 這種存儲類型聲明的變量被分配到外部存儲器RAM(xdata)的前256字節(jié)空間去,這個是medium數(shù)據(jù)存儲模型單片機的默認地址分配。 使用如下: - __pdata unsigned char value;
復(fù)制代碼 5、__code 這種存儲類型聲明的變量被分配到代碼存儲區(qū),這種類型的變量是只讀的,常用__code來聲明一些常量,比如查表數(shù)據(jù)等。 使用如下: - __code unsigned char value;
復(fù)制代碼
6、__bit 這種存儲類型聲明的變量被分配到8051存儲器的可尋址區(qū)域。8051內(nèi)核有16字節(jié)的可尋址RAM(0x20-02F),總共可以提供16x8=128bits尋址位。 使用如下: 7、__sfr / __sfr16 / __sfr32 / __sbit 這種存儲類型通常用于特殊功能寄存器,可以以位、字節(jié)和字訪問。比如: - __sfr __at (0x80) P0 //端口P0
- _sbit __at (0x80+1) //端口P0_1
復(fù)制代碼
其中,__at表示指派一個絕對地址 七、絕對地址 通常使用__at來指派一個絕對地址,可以指定一個變量的RAM存儲地址。比如:
- __xdata __ar (0x2000) unsigned char value //指定變量value存放在外部RAM的0x2000到0x2001地址。
- __code __at (0x3000) char name[5] = "SDCC";//字符串SDCC存放0x3000的ROM空間
復(fù)制代碼
八、指針 SDCC編譯器用*字符支持變量指針的聲明,SDCC指針可用在所有標準C中可用的操作中。但是,因為8051和派生系列的獨特結(jié)構(gòu),SDCC編譯器提供兩個類型的指針:通用指針和存儲器指針。一些指針聲明的例子如下: - __xdata unsigned char * __data p;//內(nèi)部ram的指針p指向外部ram的數(shù)據(jù)對象
- __data unsigned char * __xdata p;//外部ram的指針p指向內(nèi)部ram的數(shù)據(jù)對象
- __xdata unsigned char * __code p;//rom的指針p指向外部ram的數(shù)據(jù)對象
- __code unsigned char * __code p;//rom的指針p指向rom的數(shù)據(jù)對象
- usigned char * __xdata p;//位于xdata空間的普通指針
- unsigned char * p;//位于默認存儲空間的普通指針
- char (* __data fp) (void);//位于data空間的函數(shù)指針
復(fù)制代碼
九、中斷服務(wù)例程 SDCC編譯器支持在C語言源程序直接編寫8051單片機的中斷服務(wù)例程,需要用到關(guān)鍵字__interrupt,中斷函數(shù)的定義格式如下:
- void 函數(shù)名 (void) __interrupt (n) __using(n)
復(fù)制代碼其中,第一個n表示中斷號,第二個n表示使用寄存器組。 其中,不同中斷的入口地址計算如下圖所示:
中斷向量地址.PNG (67.48 KB, 下載次數(shù): 178)
下載附件
2020-6-14 21:58 上傳
__using(n)可以指定中斷服務(wù)例程所使用的寄存器組,單片機進入中斷函數(shù)會先保存當前寄存器組的內(nèi)容,如果指定其他的寄存器組,可以不保存當前的寄存器組的內(nèi)容,直接使用指定寄存器組,可以提高效率。 如果中斷服務(wù)例程沒有指定一個寄存器組(沒有__using)或者使用__using(0),編譯器將保存所有被使用的寄存器到堆棧的入口之上并且在退出時恢復(fù)。然而,如果中斷服務(wù)例程調(diào)用其他函數(shù),整個寄存器組被保存到堆棧中。該方案對使用非常少的寄存器的小中斷服務(wù)例程是非常有利的。 使用時,除了定義中斷服務(wù)函數(shù),還需要在main函數(shù)的源文件聲明該中斷服務(wù)例程,這樣才能正常進入中斷 十、使用內(nèi)嵌匯編代碼 SDCC支持兩種內(nèi)嵌匯編代碼格式: - 第一種:__asm __endasm
- 第二種:__asm__("inline_assembler_code")
復(fù)制代碼其中,第二種格式需要SDCC 3.2.0版本及以上才支持。兩種格式使用示例如下所示: - 第一種示例:
- __asm
- ; This is a comment
- label:
- nop
- __endasm
- 第二種示例:
- __asm__("; This is a comment\nlabel:\n\tnop");
復(fù)制代碼第二種格式需要使用\n來換行,沒有第一種直觀,一般推薦使用第一種方式內(nèi)嵌匯編代碼。 可以使用內(nèi)嵌匯編來實現(xiàn)nop(空操作)的功能,一般用于延時等,可以如下定義: - #define DELAY \
- __asm \
- nop \
- nop \
- _endasm
復(fù)制代碼下一部分我會基于一個實際工程模板介紹makefile的編寫,通過makefile管理工程多個源文件、頭文件和宏。
|