如果不是Seven問起來,我以為C51這種東西已經屬於歷史遺跡了。不過簡單搜索了一下,發現c51老而彌堅,仍然茁壯的生長着。原因據說,一方面是有很大的用戶群和既有的軟硬件資源,另外一方面,的確在很多的高校教學中仍然占有一席之地。其實個人感覺,高校課程的更新真的是需要再加快了。
不過不管如何,作為入門類的單片機,c51還好啦,這些學習的經歷,並不會浪費,學生能夠很快的轉化到其它平台上去。
Seven碰到的情況是這樣,c51開發工具目前基本以windows為主,在mac上無法工作,總不能為了學習c51就換一台電腦。我搜索了一下,發現了sdcc這個工具,於是來嘗試一下,首先是安裝sdcc:
brew install sdcc
找一個呼吸燈程序源碼,來測試一下編譯是否正常:
#include <8051.h>
// 延時函數
// 參數 in 為延時的時間長度(單位時間很短,大約一條指令的時間)
void delay(unsigned int in)
{
unsigned int i;
for(i=0;i<10*in;i++) {;}
}
// 由暗變亮的子函數
// 參數 ledn 為點第幾位的燈
void off_on(unsigned char ledn)
{
unsigned int i,j;
for(i=0;i<100;i++)
{
for(j=0;j<100;j++)
{
if(i<=j)
{ // 模擬pwm的低電平輸出
P0 = 0;
}
else
{ // 模擬PWM的高電平輸出
P0 = 1<<ledn;
}
delay(10); // 這里的延時 根據燈的情況自己調整
}
}
}
// 由亮變暗的子函數
// 參數 ledn 為點第幾位的燈
void on_off(unsigned char ledn)
{
unsigned int i,j;
for(i=100;i>1;i--)
{
for(j=0;j<100;j++)
{
if(i<=j)
{ // 模擬pwm的低電平輸出
P0 = 0;
}
else
{ // 模擬PWM的高電平輸出
P0 = 1<<ledn;
}
delay(10); // 這里的延時 根據燈的情況自己調整
}
}
}
// 主程序開始
void main()
{
unsigned char ledn;
while(1)
{
for(ledn=0;ledn<8;ledn++)
{
off_on(ledn);
on_off(ledn);
}
}
}
(補充知識:在mac電腦中一般都是在命令行工作,編輯文件可以使用vi編輯器,不熟悉vi編輯器的,也可以推薦使用TextMate.app,這個程序可以在啟動台找到,也可以在命令行執行mate命令來啟動編輯器。如果沒有安裝過的話,還可以使用brew cask install textmate
來安裝。)
上面的源代碼我們保存到比如test.c文件,接下來編譯一下:
#編譯命令,后面的test.c就是我們的源碼,可以替換成你需要的名字:
sdcc test.c
#編譯成功會生成多個文件:
test.asm test.ihx test.lk test.lst test.map test.mem test.rel test.rst test.sym
這些文件中其實只有test.ihx文件是我們需要的輸出文件。其它文件都是工作過程中的臨時文件,一般沒有用處,可以刪除,但在大型系統中查錯、分析可能會用得到。在windows工作慣了的同學們可能更習慣.hex輸出文件,把.ihx轉換為.hex的命令是:
packihx test.ihx > test.hex
還有可能會需要.bin文件,轉換方法是:
sdobjcopy -I ihex -O binary test.ihx test.bin
#-I指定的是輸入格式,-O指定的是輸出格式
#最后兩個參數分別是輸入、輸出的文件名
#sdobjcopy不帶任何參數執行有更詳細的幫助可以參考
.hex/.bin文件,並非是必須的,特別是在mac上工作,只是交流的時候如果需要,可以用上面的方法轉換出來。
一般在學習的情況下,知道上面這些就夠用了。在正式的開發過程中,特別是項目比較大,有多個模塊,你可能還需要知道下面這些用法。
把源代碼編譯成鏈接庫文件.rel:
sdcc -c test.c
執行完成你會發現已經有了.rel鏈接庫文件。.rel可以經由再次編譯,輸出成常規的.ihx文件,方法跟普通編譯其實是一樣的:
sdcc test.rel
這里大多初學者會有一個疑問,既然最終都是要.ihx文件,為啥還要編譯成.rel文件呢?原因很多,常見的如下:
- 當一個工程很大的時候,會分成多個.c程序來寫,這就需要分別編譯。而如果很多個.c文件,這編譯也是很慢的,所以通行的做法是哪個文件被修改了,就僅編譯改變了的文件。這時候使用.rel文件就會快很多,因為從.c文件到.rel文件,編譯做了大多工作,只是沒有做最后的拼裝。一個大工程編譯僅修改過的文件到.rel,然后把所有的.rel拼裝在一起成為.ihx文件,速度會很快。
- 還有的時候,比如你編寫了一個模塊,這個模塊是通用的,可以供很多人使用,但你不希望別人看到源碼或者避免別人修改搞亂了源碼。你可以只給對方.rel文件和函數描述的.h文件,對方把你的模塊放到自己的項目中而不去關心源代碼是怎樣的。
繼續我們的話題。單片機為了提高效率,還經常會用到匯編語言,匯編語言在sdcc軟件包中是分cpu來實現的,一般默認提供這些cpu的匯編器:
sdas390 sdas6808 sdas8051 sdasgb sdasrab sdasstm8 sdastlcs90 sdasz80
這些匯編器統一的命名規則是sdasxxxx,xxxx是指cpu的型號,比如8051的cpu就使用sdas8051,z80的cpu就使用sdasz80。匯編器使用的方法是(以8051為例):
sdas8051 -ols filename.asm
匯編結果輸出.rel文件以及一些其它的過程文件。
重要:使用sdcc編譯單片機程序,跟windows下面keil的c代碼是有一些差別的,列表如下:
Mac sdcc | Windows Keil c | |
---|---|---|
頭文件 | 8051.h/8052.h | reg51.h/reg52.h |
IO端口 | P2_0 | P2^0 |
IO口定義 | #define LED P2_0 | sbit LED = P2^0 |
中斷函數 | void INT0_ISR() __interrupt 0 | void INT0_ISR() interrupt 0 |
可以看到,這個差別是非常小的。對於初學者來說,一般就是引用頭文件的時候要注意別用錯。其它的內容,碰到了就注意用對應的語法,碰不到就不用管。
————————————————————————————————————————————
有了編譯的結果,還要燒錄到51單片機上來測試結果,燒錄這個詞是行業內的“黑話”,表達同樣意思的常用說法還有“刷機”、“燒機”、“燒寫”、“下載到單片機”等,當然”下載到單片機”其實是最正式的說法。
燒錄需要有一個燒錄軟件,mac上可以這樣安裝:
#首先到一個保存燒錄程序的目錄:
cd ~/bin/
#下載程序
wget https://raw.githubusercontent.com/laborer/stcflash/master/stcflash.py
#下載的程序實際是一個文本文件,設定這個文件的可以執行標志
chmod +x stcflash.py
51單片機都是通過串口跟電腦連接的,當前的電腦一般都沒有串口,所以都是使用usb串口卡,mac電腦一定要安裝對應的mac版本電腦驅動程序。這時候51單片機通過串口插到電腦上之后,在/dev/目錄會看到這個串口設備,設備的名字根據串口卡廠商的不同而不同,比如叫:/dev/tty.usbserial 。
剛才下載的這個燒寫軟件支持.ihx文件和.bin文件,也就是說我們剛才編譯的.ihx文件直接就可以燒錄到51單片機上,燒錄的命令是:
stcflash.py test.ihx
文章看起來似乎比較復雜,其實包含了才開始搭建環境以及你需要知道的所有入門型知識,只需要折騰這一次,以后的使用,應當能感覺到在mac更加的迅速、高效。
參考資料鏈接:
sdcc官網:http://sdcc.sourceforge.net/,建議以官方文檔為主。
sdcc簡單說明:http://blog.csdn.net/baskmmu/article/details/43683289,因版本問題,此文檔中有一些錯誤,請甄別性的閱讀。
使用SDCC在Linux/macOS上開發51單片機程序:https://lonord.name/article/580cb1f67240257ec13293fb
燒錄軟件:https://github.com/laborer/stcflash