網站建設鼠標移動變顏色百度seo
原創(chuàng)首發(fā)于CSDN,轉載請注明出處,謝謝!
文章目錄
- 為何會在Linux下開發(fā)單片機
- 個人系統(tǒng)環(huán)境與所用開發(fā)板
- 安裝開源編譯器 sdcc
- STC MCU ISP 閃存工具 stcgal 的安裝
- 單片機代碼的編譯與測試
- |編寫主代碼 main.c
- |使用 sdcc 編譯
- |閃存燒錄 stcgal
- 單片機效果展示
- 拓展1??:使用SDCC進行單片機程序編寫的不同點
- 拓展2??:附頭文件 8051.h 文本
- 參考資料
- 文章更新時間記錄
為何會在Linux下開發(fā)單片機
個人初步學習51單片機的時,所能接觸到的教程基本都是在Windows環(huán)境下使用Keil開發(fā)。誠然,Keil確實是一款強大的開發(fā)軟件,但博主個人受限于以下因素:
- 個人使用的是蘋果電腦 MacBook Air;
- 所裝的VM虛擬機里已經安裝了 Ubuntu 20.04.01。
加之其他瑣碎的原因,博主終是走上了適配在Linux環(huán)境下的開源編譯器SDCC來開發(fā)單片機這條路【不止是現在的C51單片機,還有以后的STM32,統(tǒng)一在Linux環(huán)境下進行開發(fā) 】。其實兩者在拋開系統(tǒng)環(huán)境、編譯軟件的差異,大體上都是一樣的:①【SDCC、Keil】編譯生成hex文件;②【stcgal、stc-isp】啟動燒錄軟件燒錄程序。
在Ubuntu系統(tǒng)下搭建51單片機開發(fā)環(huán)境全過程里,出乎預料的反而是察覺了個人對于Linux系統(tǒng)的 文件架構、軟硬鏈接、軟鏈接的“漂移”、環(huán)境變量 等幾個方面的認識不足,惹出了幾個無厘頭的“bug”。 故才有了“參考資料”一節(jié)內那幾篇環(huán)境變量、系統(tǒng)變量的博文,對于這幾個主題的研究,以后也會出幾篇相關內容的博文。
個人系統(tǒng)環(huán)境與所用開發(fā)板
- 電腦:MacBook Air
- 虛擬機:VMWare Fusion 12
- Linux系統(tǒng):Ubuntu 20.04.01
- 開發(fā)板:普中HC6800V2.0 (開發(fā)板實物請?zhí)D到“單片機效果展示”一節(jié)。)
安裝開源編譯器 sdcc
終端輸入指令 sudo -i 進入根目錄 /,再次輸入指令 sudo apt-get install sdcc
。安裝完畢,全程無報錯。終端輸入指令 sdcc -v 驗證編譯器是否安裝成功:
?\ast?小貼士:SDCC的全稱是Small Device C Compiler,即“小型設備C語言編譯器”。根據官網(http://sdcc.sourceforge.net/)的說法,SDCC是一個可重定向目標的、優(yōu)化的標準C編譯器套件(支持ANSI C89、ISO C99和ISO C11),支持基于英特爾MCS51(8031、8032、8051、8052等)、Maxim(原Dallas)的DS80C390系列、Freescale(原摩托羅拉)的HC08系列(hc08、s08)、Zilog的Z80系列(z80、z180、gbz80、Rabbit 2000/3000、Rabbit 3000A、TLCS-90)、Padauk(pdk14、pdk15)和意法半導體的STM8。
圖片里打框的MCS51就是我們常說的51單片機,在根目錄里進入路徑 usr/share/sdcc/include/mcs51 輸入 ls,會顯示出一堆不同型號的51單片機芯片的適配頭文件。至此,編譯器SDCC的安裝大功告成。
STC MCU ISP 閃存工具 stcgal 的安裝
在根目錄 / 下輸入指令 pip3 install stcgal
(系統(tǒng)沒有安裝 pip3 就自己下載安裝),安裝的同時會下載兩個軟件 tqdm-4.64.1 與 pyserial-3.5 。前者顯示文件 main.hex 的燒錄進度條,后者則是串口通信軟件。(記住了,不管安裝什么軟件,在安裝之前必須要好好查一查其具體的功能是什么。)
單片機代碼的編譯與測試
|編寫主代碼 main.c
#include <mcs51/8051.h>void Delay(unsigned int ms);void main(){while(1){//自行對照開發(fā)板引腳圖。P1_1 = 0; Delay(500);P1_1 = 1;//led燈以一秒為一個周期閃爍。Delay(500); }
}void Delay(unsigned int ms){unsigned int a, b;for(a = ms; a > 0; a--){for(b = 100; b > 0; b--);}
}
|使用 sdcc 編譯
在終端前后輸入以下兩條指令,經過sdcc的編譯,測試文件夾內會多出一堆的文件,我們需要的主文件是 main.hex
sdcc main.c
//sdcc默認生成的文件后綴不是hex而是ihx,需要使用packihx轉換。packihx main.ihx > main.hex && ls
搜索相關資料的時候發(fā)現了第三條指令:makebin (makebin main.ihx > main.bin)。原來與 ?\ast?.hex 格式文件相比,?\ast?.bin 格式有文件三個方面的差異(請自行驗證):
- HEX文件是包括地址信息的,而BIN文件格式只包括了數據本身。 在燒寫/下載HEX文件時一般不需要用戶指定地址,因為HEX文件內部信息已經包括了地址,而燒寫B(tài)IN文件時,用戶必須指定地址信息;
- BIN文件。對二進制文件而言,沒有格式,文件只是純粹的二進制數據。
- HEX文件使用ASCII來表示二進制的數值。 如一般的8-BIT的二進制數值0x3F,用ASCII來表示就需要表示字符‘3’和字符‘F’,每個字符需要一個BYTE,所以 HEX文件需要大于BIN文件2倍的內存空間。
|閃存燒錄 stcgal
用USB線連接電腦將與單片機(請自行安裝與系統(tǒng)版本對應的CH341驅動,無頭緒的讀者請參考下列第二篇博文《搭建Ubuntu的51單片機開發(fā)環(huán)境(學習記錄)》里對應的驅動安裝一節(jié)),輸入指令 ls /dev/tty?\ast? 確認USB接入后在終端輸入指令
stcgal -P stc89 -p /dev/ttyUSB0 main.hex
或者直接輸入
stcgal main.hex
筆者在燒錄程序時直接用第二條,在上文里代碼頭文件已經選擇了51單片機類型為 8051 #include <mcs51/8051.h>
,個人認為 stcgal 運行時默認 port 為 /dev/ttyUSB0,故使用時直接運行,無需手動指定端口和波特率。
單片機效果展示
單片機的LED燈模塊,右邊數第一個LED燈以一秒為一個周期閃爍。
拓展1??:使用SDCC進行單片機程序編寫的不同點
SDCC支持的C語言與Keil的差異:
- 包含自定義的頭文件時必須使用雙引號。 某個項目中有個名為tm1638.h 的文件,在Keil寫成 #include <tm1638.h> ,但在SDCC中必須寫成 #include “tm1638.h” ;
- sdcc編譯51單片機代碼文件的頭文件(引腳定義文件)名字不一樣。 Keil中為 #include <reg52.h>,而在SDCC中需要寫成 #include <mcs51/8051.h>;
- Keil中的特殊類型 sbit 和 sfr 在SDCC中為 __sbit和 __sfr 。 如Keil中的代碼 sfr P0 = 0x80、sbit P0_1 = P0 ^ 1。在SDCC中就要寫成:__sfr __at (0x80) P0、__sbit __at (0x81) P0_1 。但在8051.h 中已經定義了常用的端口,需要使用哪個端口時,直接使用P0、P1、P2_1之類的宏即可;
- Keil中的code關鍵字(用于將數據放入代碼段)在SDCC中應該寫成__code。 在Keil中的代碼unsigned char code sevenseg_hex[] = { … },在SDCC中應該這樣寫:__code unsigned char sevenseg_hex[] = { … };
- Keil中的 interrupt 關鍵字在SDCC中應該寫成 __interrupt。 定義中斷處理函數的代碼在SDCC中應該寫成:void timer0() __interrupt 1 { … } 。
< 請讀者自行驗證以上,同時歡迎在評論區(qū)補充不同的差異點。>
拓展2??:附頭文件 8051.h 文本
/*-------------------------------------------------------------------------8051.h: Register Declarations for the Intel 8051 ProcessorCopyright (C) 2000, Bela Torok / bela.torok@kssg.chThis library is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License along with this library; see the file COPYING. If not, write to theFree Software Foundation, 51 Franklin Street, Fifth Floor, Boston,MA 02110-1301, USA.As a special exception, if you link this library with other files,some of which are compiled with SDCC, to produce an executable,this library does not by itself cause the resulting executable tobe covered by the GNU General Public License. This exception doesnot however invalidate any other reasons why the executable filemight be covered by the GNU General Public License.
-------------------------------------------------------------------------*/#ifndef REG8051_H
#define REG8051_H/* BYTE Register */
__sfr __at (0x80) P0 ;
__sfr __at (0x81) SP ;
__sfr __at (0x82) DPL ;
__sfr __at (0x83) DPH ;
__sfr __at (0x87) PCON ;
__sfr __at (0x88) TCON ;
__sfr __at (0x89) TMOD ;
__sfr __at (0x8A) TL0 ;
__sfr __at (0x8B) TL1 ;
__sfr __at (0x8C) TH0 ;
__sfr __at (0x8D) TH1 ;
__sfr __at (0x90) P1 ;
__sfr __at (0x98) SCON ;
__sfr __at (0x99) SBUF ;
__sfr __at (0xA0) P2 ;
__sfr __at (0xA8) IE ;
__sfr __at (0xB0) P3 ;
__sfr __at (0xB8) IP ;
__sfr __at (0xD0) PSW ;
__sfr __at (0xE0) ACC ;
__sfr __at (0xF0) B ;/* BIT Register */
/* P0 */
__sbit __at (0x80) P0_0 ;
__sbit __at (0x81) P0_1 ;
__sbit __at (0x82) P0_2 ;
__sbit __at (0x83) P0_3 ;
__sbit __at (0x84) P0_4 ;
__sbit __at (0x85) P0_5 ;
__sbit __at (0x86) P0_6 ;
__sbit __at (0x87) P0_7 ;/* TCON */
__sbit __at (0x88) IT0 ;
__sbit __at (0x89) IE0 ;
__sbit __at (0x8A) IT1 ;
__sbit __at (0x8B) IE1 ;
__sbit __at (0x8C) TR0 ;
__sbit __at (0x8D) TF0 ;
__sbit __at (0x8E) TR1 ;
__sbit __at (0x8F) TF1 ;/* P1 */
__sbit __at (0x90) P1_0 ;
__sbit __at (0x91) P1_1 ;
__sbit __at (0x92) P1_2 ;
__sbit __at (0x93) P1_3 ;
__sbit __at (0x94) P1_4 ;
__sbit __at (0x95) P1_5 ;
__sbit __at (0x96) P1_6 ;
__sbit __at (0x97) P1_7 ;/* SCON */
__sbit __at (0x98) RI ;
__sbit __at (0x99) TI ;
__sbit __at (0x9A) RB8 ;
__sbit __at (0x9B) TB8 ;
__sbit __at (0x9C) REN ;
__sbit __at (0x9D) SM2 ;
__sbit __at (0x9E) SM1 ;
__sbit __at (0x9F) SM0 ;/* P2 */
__sbit __at (0xA0) P2_0 ;
__sbit __at (0xA1) P2_1 ;
__sbit __at (0xA2) P2_2 ;
__sbit __at (0xA3) P2_3 ;
__sbit __at (0xA4) P2_4 ;
__sbit __at (0xA5) P2_5 ;
__sbit __at (0xA6) P2_6 ;
__sbit __at (0xA7) P2_7 ;/* IE */
__sbit __at (0xA8) EX0 ;
__sbit __at (0xA9) ET0 ;
__sbit __at (0xAA) EX1 ;
__sbit __at (0xAB) ET1 ;
__sbit __at (0xAC) ES ;
__sbit __at (0xAF) EA ;/* P3 */
__sbit __at (0xB0) P3_0 ;
__sbit __at (0xB1) P3_1 ;
__sbit __at (0xB2) P3_2 ;
__sbit __at (0xB3) P3_3 ;
__sbit __at (0xB4) P3_4 ;
__sbit __at (0xB5) P3_5 ;
__sbit __at (0xB6) P3_6 ;
__sbit __at (0xB7) P3_7 ;__sbit __at (0xB0) RXD ;
__sbit __at (0xB1) TXD ;
__sbit __at (0xB2) INT0 ;
__sbit __at (0xB3) INT1 ;
__sbit __at (0xB4) T0 ;
__sbit __at (0xB5) T1 ;
__sbit __at (0xB6) WR ;
__sbit __at (0xB7) RD ;/* IP */
__sbit __at (0xB8) PX0 ;
__sbit __at (0xB9) PT0 ;
__sbit __at (0xBA) PX1 ;
__sbit __at (0xBB) PT1 ;
__sbit __at (0xBC) PS ;/* PSW */
__sbit __at (0xD0) P ;
__sbit __at (0xD1) F1 ;
__sbit __at (0xD2) OV ;
__sbit __at (0xD3) RS0 ;
__sbit __at (0xD4) RS1 ;
__sbit __at (0xD5) F0 ;
__sbit __at (0xD6) AC ;
__sbit __at (0xD7) CY ;/* BIT definitions for bits that are not directly accessible */
/* PCON bits */
#define IDL 0x01
#define PD 0x02
#define GF0 0x04
#define GF1 0x08
#define SMOD 0x80/* TMOD bits */
#define T0_M0 0x01
#define T0_M1 0x02
#define T0_CT 0x04
#define T0_GATE 0x08
#define T1_M0 0x10
#define T1_M1 0x20
#define T1_CT 0x40
#define T1_GATE 0x80#define T0_MASK 0x0F
#define T1_MASK 0xF0/* Interrupt numbers: address = (number * 8) + 3 */
#define IE0_VECTOR 0 /* 0x03 external interrupt 0 */
#define TF0_VECTOR 1 /* 0x0b timer 0 */
#define IE1_VECTOR 2 /* 0x13 external interrupt 1 */
#define TF1_VECTOR 3 /* 0x1b timer 1 */
#define SI0_VECTOR 4 /* 0x23 serial port 0 */#endif
參考資料
- 《Mac版下實現51單片機進行開發(fā)的環(huán)境搭建》,CSDN博主:熺子,時間:2022年3月29日;
- 《搭建Ubuntu的51單片機開發(fā)環(huán)境(學習記錄)》,CSDN博主:橫著望的貓,時間:2021年12月20日;
- 《Linux(Ubuntu)下51單片機的開發(fā)環(huán)境的配置及詳細的操作步驟》,CSDN博主:逗比小憨憨,時間:2021年2月4日;
- 《如何在Linux下進行51單片機的開發(fā)》,微信公眾號:我的一九九三,時間:2021年12月16日;
- 《還在用keil做51單片機開發(fā)馬?快來試試開源的SDCC吧》,微信公眾號:STEM創(chuàng)造家,時間:2021年12月10日;
- 《CentOS7設置環(huán)境變量》(該篇博文在嗶哩嗶哩里有博主配套的視頻講解,強烈推薦觀看!),博主:C語言技術網-碼農有道,時間:2020年3月27日;
- 《一文帶你學會Linux系統(tǒng)的變量》,微信公眾號:生信喵實驗柴,時間:2021年12月14日;
- 《如何設置與查看Linux系統(tǒng)中的環(huán)境變量》,微信公眾號:良許,時間:2020年8月17日;
- 《Linux目錄詳解,軟件應該安裝到哪個目錄》,博主:Deshun,時間:2019年6月13日。
文章更新時間記錄
- 文章框架搭好;「2023.2.2.19 19:10」
- 九篇參考博文打列完畢;「2023.2.19 19:26」
- “安裝開源編譯器
SDCC
”一節(jié)完畢?!?023.2.19 21:07」 - “STC MCU ISP閃存工具
stcgal
的安裝”一節(jié)完畢?!?023.2.19 21:25」 - “單片機代碼的編譯與測試”一節(jié)里的三小節(jié)完畢?!?023.2.20 13:33」
- “使用SDCC進行單片機程序編寫的不同點”一節(jié)完成。「2023.2.20 13:53」
- “單片機效果展示”一節(jié)完成。「2023.2.20 18:43」
- “使用sdcc編譯”該小節(jié)內增加了BIN文件相關內容?!?023.2.20 19:45」
- 文章首次發(fā)布于CSDN?!?023.2.21 12:20」
P.S.1 2022年12月下旬在別人的同類型的博文下了留言,如今自己在兩個月也寫了一篇。兩個月,兩個月,兩年,兩年,唉?!?023.2.20 19:47」