余熾業(yè) 雷瑞庭 宋躍 王健偉,2
(1. 東莞理工學(xué)院 電子工程學(xué)院,廣東東莞 523808;2. 華南理工大學(xué) 電子與信息學(xué)院,廣州 510640)
在ARM、Linux 技術(shù)廣泛應(yīng)用的今天,RS485 總線憑其傳輸距離遠(yuǎn)、抑制共模干擾能力強(qiáng)、用戶可以自定義應(yīng)用協(xié)議等優(yōu)點在各種工業(yè)控制場合中而得到廣泛的應(yīng)用[1-2]。而其設(shè)計由于要涉及l(fā)inux 內(nèi)核復(fù)雜代碼的修改,所以設(shè)計比較麻煩[3-4],如何簡便地完成其RS485 通信設(shè)計也是值得研究的。我們在實際的工程設(shè)計中就此進(jìn)行了研究與探索。
工程要求是:在ARM920T 核的S3C2440 處理器和嵌入式LINUX 基礎(chǔ)上,完成ARM 和PC 機(jī)遠(yuǎn)程9600 bps 的穩(wěn)定通信。
本設(shè)計以RS232 與半雙工RS485 總線在I/O 控制方向的不同點為切入口,通過編寫單個IO 的驅(qū)動來實現(xiàn)485 總線的方向控制,在應(yīng)用層編程中利用多進(jìn)程的發(fā)現(xiàn)調(diào)用方向控制程序,從而實現(xiàn)RS485 的通信,本文在介紹硬件接口、系統(tǒng)設(shè)計過程的同時,重點介紹LINUX 系統(tǒng)的軟件設(shè)計思想與設(shè)計過程。
S3C2440 處理器片內(nèi)集成了許多嵌入式應(yīng)用的控制器,可以方便地實現(xiàn)嵌入式應(yīng)用中的各種接口模塊。本設(shè)計中用到了S3C2440 片內(nèi)集成的三個UART(Universal Asynchronous Receiver/Transmitter),由于UART0 在移植嵌入式LINUX 的時候被用作控制臺(console),所以如今用到的是UART1。由于ARM處理器的引腳電平和EIA 規(guī)定的電器標(biāo)準(zhǔn)不一樣,所以必須要外接電平轉(zhuǎn)換芯片[1,5-7],利用片內(nèi)UART 外接不同的轉(zhuǎn)換芯片可以輕松地實現(xiàn)RS485 或者RS232 串行協(xié)議標(biāo)準(zhǔn)。RS485 采用差分信號負(fù)邏輯,+2V ~+6V 表示“0”,-6V ~-2V 表示“1”。為了達(dá)到RS485 總線的電氣特性標(biāo)準(zhǔn),設(shè)計中用到Analog Devices 公司的半雙工RS-485 隔離收發(fā)器。
ADM2483 是帶隔離的增強(qiáng)型RS485 收發(fā)器,它包括一個三通道隔離器,一個帶三態(tài)輸出的差分驅(qū)動器和一個帶三態(tài)輸入的差分接收器,允許多達(dá)256 個收發(fā)器接入總線,最高傳輸速率為500 Kbps,邏輯端兼容3V/5V 工作電源??偩€端5 V 供電。
圖1 為系統(tǒng)中利用S3C2440 中的UART1 實現(xiàn)半雙工的RS-485 總線的原理圖,在同一時刻里數(shù)據(jù)只能往一個方向傳輸。其中的引腳RE’與DE 分別為接收使能和發(fā)送使能端,現(xiàn)在將其并聯(lián)起來接到S3C2440 的nCTS0 引腳,由該引腳的電平控制芯片數(shù)據(jù)的方向。要發(fā)送數(shù)據(jù)時要叫其置1,接收數(shù)據(jù)時要將其清0。
圖1 S3C2440-485 接口原理圖
由于在RS485 標(biāo)準(zhǔn)中僅僅規(guī)定了總線的電氣特性,而電氣特性的轉(zhuǎn)換則由AMD2483 芯片完成,所以在LINUX 操作系統(tǒng)中,完全可以借助內(nèi)核的串口驅(qū)動來實現(xiàn)[4,8-9]。區(qū)別在于要在串口收發(fā)數(shù)據(jù)前增加一個方向控制I/O 的驅(qū)動。在linux2.6 內(nèi)核源碼當(dāng)中,已經(jīng)實現(xiàn)好了對S3C2440 的GPIO 的設(shè)置函數(shù),可以在GPIO 口的驅(qū)動程序中直接調(diào)用,在本設(shè)計中用到了兩個內(nèi)核函數(shù)(在arch/arm/plat-s3c24xx/gpio. c)其函數(shù)原型如下:
void s3c2410_ gpio_ cfgpin(unsigned int pin,unsigned int function)。此函數(shù)的功能是設(shè)置引腳的功能,參數(shù)pin 是要設(shè)置的引腳,對應(yīng)著是nCTS0 也即是S3C2410_ GPH0 引腳,參數(shù)function 是要設(shè)置引腳的功能,設(shè)置中用到的是輸出功能所以該值是S3C2410_ GPH0_ OUTP。
void s3c2410_ gpio_ setpin(unsigned int pin,unsigned int x)。此函數(shù)的功能是設(shè)置引腳的輸出值,參數(shù)pin 是要設(shè)置的引腳,參數(shù)x 是要設(shè)置引腳的輸出值0 或者1。
單個引腳的驅(qū)動可以以簡單字符設(shè)備的驅(qū)動來實現(xiàn),其中只用到了一個重要的函數(shù)為
在嵌入式LINUX 中已經(jīng)對串口的驅(qū)動有了很好的支持,而且已經(jīng)將很多串口的功能設(shè)置都封裝好,可以在應(yīng)用層直接調(diào)用。串口的設(shè)備文件位于/dev 目錄下,對串口的收發(fā)數(shù)據(jù)同樣的是通過對設(shè)備文件的讀寫操作來實現(xiàn)的[2,9-10]。
在使用串口之前必須對其進(jìn)行相關(guān)的配置,包括:波特率,數(shù)據(jù)位,校驗位,停止位等。串口的設(shè)置有結(jié)構(gòu)體struct termios 來體現(xiàn)的。利用串口相關(guān)的函數(shù)來設(shè)置結(jié)構(gòu)體里面的值就可以完成串口的相關(guān)配置[11-12]。在本設(shè)計中將串口配置為波特率是9 600 bps,8 位數(shù)據(jù)位,無校驗,1 位停止位。
LINUX 系統(tǒng)上的進(jìn)程間有父子關(guān)系。一個進(jìn)程有且僅有一個父進(jìn)程,但是可能有多個子進(jìn)程。在LINUX 系統(tǒng)中可以使用三個系統(tǒng)調(diào)用創(chuàng)建進(jìn)程:fork(),vfork(),和clone()。其中fork()系統(tǒng)調(diào)用是穿件進(jìn)程最常用的方式,其接口頭文件與函數(shù)原型如下:
當(dāng)fork 調(diào)用成功返回時,系統(tǒng)中將會出現(xiàn)一個新的進(jìn)程。新的進(jìn)程為原進(jìn)程的子進(jìn)程,而原進(jìn)程則是新進(jìn)程的父進(jìn)程。子進(jìn)程幾乎完全克隆了父進(jìn)程的一切特性,包括虛擬地址空間和執(zhí)行進(jìn)度。fork 函數(shù)返回一個pid_ t 型的進(jìn)程ID,從程序員的角度看,父子進(jìn)程的唯一差異在于fork 函數(shù)的返回值是不同的:父進(jìn)程返回的是非零值,是其子進(jìn)程的ID,如果是-1,就表示創(chuàng)建進(jìn)程失敗;而在子進(jìn)程中永遠(yuǎn)返回0。這就是在程序中判斷是父進(jìn)程的依據(jù)。
在LINUX 系統(tǒng)中,經(jīng)常將一個進(jìn)程的執(zhí)行流程從一個可執(zhí)行程序轉(zhuǎn)移到另一個可執(zhí)行程序,也就是裝載并運行一個程序。這些函數(shù)通常被稱為exec 函數(shù)族,它們的接口頭文件和原型如下:
以上各個函數(shù)的對比如表1 所示:
表1 各個函數(shù)的對比
測試環(huán)境為在已經(jīng)移植好linux 嵌入式操作系統(tǒng)的S3C2440 處理器。由于S3C2440 處理器自帶著三個串口,本次測試用到的是串口1。串口波特率設(shè)置為9 600 bps,8 位數(shù)據(jù)位,無奇偶校驗,1 位停止位。測試的方法是上位機(jī)PC 利用串口調(diào)試助手不斷的往S3C2440 上發(fā)送“hello world”字符串,下位機(jī)接收到該字符串后改變串口為寫模式,然后把該字符串發(fā)回給PC 機(jī),這樣就可以在PC 機(jī)的串口調(diào)試助手里面看到發(fā)送回來的字符串有無錯誤。
部分程序片斷如下:
由于進(jìn)程調(diào)度的開銷,通信中數(shù)據(jù)的更新的時間間隔不能太短。實驗測試中PC 是每間隔1 000 ms往ARM 發(fā)送一次數(shù)據(jù),通信數(shù)據(jù)量4 kB,設(shè)計達(dá)到預(yù)期目標(biāo)。盡管偶爾有誤碼出現(xiàn),但本設(shè)計中避免了涉及l(fā)inux 內(nèi)核復(fù)雜代碼的的修改,仍不失為有實用價值的設(shè)計方法。
[1]尤保常,楊源源,張曉,等.Linux 環(huán)境下RS485 通訊軟件開發(fā)與界面設(shè)計[J].自動化儀表,2010(12):22-25.
[2]王志穎,馬衛(wèi)東.Linux 系統(tǒng)下RS-485 串行通信程序設(shè)計[J].計算機(jī)應(yīng)用研究,2002,19(2):136-138.
[3]陳鐵軍,仇洪冰.基于S3C2410 的嵌入式Linux 的移植方法[J].桂林電子工業(yè)學(xué)院學(xué)報,2004,26(4):259-263.
[4]張莉君,莊曉奇,歐陽才.基于S3C2410 的多路高精度數(shù)據(jù)采集系統(tǒng)設(shè)計[J].機(jī)床與液壓,2010,38(2):71-74.
[5]陳鼐,于盛林.基于S3C2410X 的液晶屏接口設(shè)計與實現(xiàn)[J].測控技術(shù),2006,25(12):68-71.
[6]葉順流.基于ARM 的嵌入式Linux 研究與實現(xiàn)[D].重慶:重慶大學(xué),2005.
[7]王志穎,馬衛(wèi)東.Linux 系統(tǒng)下RS-485 串行通信程序設(shè)計[J].計算機(jī)應(yīng)用研究,2002,19(2):136-138.
[8]Michael R Sweet.Serial Programming Guide for POSIX Operating Systems[EB/OL]. http://digilander.libero.it/robang/rubrica/serial.htm.
[9]Peter H Baumann. The Linux Serial Programming HOWTO[EB/OL]. http://www.collective.com.au/howtos/Serial-Programming-HOWTO.html.
[10]江澤濤,吳俊安.用Kylix 實現(xiàn)Linux 環(huán)境下的串行通信[J].計算機(jī)應(yīng)用研究,2005,22(9):214-216.
[11]鄭燕飛,余海燕.Linux 的多線程機(jī)制探討與實踐[J].計算機(jī)應(yīng)用,2001,21(1):81-83.
[12]王子強(qiáng),劉海燕,李媛州.Linux 下圖形用戶界面程序的開發(fā)與實現(xiàn)[J].計算機(jī)應(yīng)用與軟件,2005,22(6):81-83.