⑴ linux C 配置串口
配置串口需要包含頭文件
其中最核心的配置結構體為:
如何獲取該結構呢?我們操作串口跟操作文件一樣,也是調用 open() 函數來打開串口,
這樣我們就能夠得到一個文件描述符 fd ,然後就可以調用 tcgetattr() 函數來獲取上述配置結構體了。
Linux 串口默認的配置為:波特率 9600,數據位 8 位,無奇偶校驗,停止位 1 位,無 CTS/RTS 。
以下介紹一些常用的配置項:波特率、奇偶校驗、數據位、停止位、硬體控制流。
相關介面:
Linux 將串口的波特率分為了輸入波特率和輸出波特率,不過最常用的場景是將兩者設置成一樣。
cfgetispeed() 函數獲取輸入波特率, cfgetospeed() 函數獲取輸出波特率。 cfsetispeed() 函數設置輸入波特率, cfsetospeed() 函數用於設置輸出波特率,當然 cfsetspeed() 函數擴展為同時設置輸入和輸出波特率。
上述介面中的 speed_t 是一系列波特率的標志位,例如常用的 115200 波特率就為 B115200,參考下述選項:
設置奇偶校驗位可以通過修改 termios 結構體中的 c_cflag 成員來實現,若無校驗,則將 PARENB 位設為 0;若有校驗,則 PARENB 為 1。之後再根據 PARODD 來區分奇偶校驗, PARODD 為 1 表示奇校驗, PARODD 為 0 表示偶校驗。例如設置無奇偶校驗位:
設置數據位可以通過修改 termios 結構體中的 c_cflag 成員來實現,CS5、CS6、CS7 和 CS8 分別代表數據位 5、6、7 和 8。不過在設置數據位之前,需要先用 CSIZE 來做屏蔽欄位,清楚這幾個標志位,例如設置數據位為 8 位:
設置停止位可以通過修改 termios 結構體中的 c_cflag 成員來實現, CSTOPB 位為 1 表示 2 位停止位, CSTOPB 位為 0 標志 1 位停止位。例如設置停止位為 1 位:
設置硬體控制流可以通過修改 termios 結構體中的 c_cflag 成員來實現, CRTSCTS 為 1 表示使用硬體控制流,為 0 表示不使用硬體控制流。例如使能硬體控制流:
當然,最後還需要用 tcflush() 拋棄存儲在 fd 里的未接收的數據。
再利用介面 tcsetattr() 函數將配置信息寫入文件描述符 fd :
這樣整個串口最常用的用法就配置完成了。
具體的配置使用可以參考我的項目 HCI-Middleware 里的 hci_transport_uart_linux.c 文件。
參考:
⑵ linux 查看某個串口參數(波特率,數據位等)命令什麼
用CAT命令查看
#cat /proc/tty/driver/serial
如果需要配置串口參數,minicom是個很好的選擇。
一、安裝
sudo apt-get install minicom
二、專配置
配置minicom的參數
運行屬$ sudo minicom -s
便進入了minicom的配置界面,使用上下鍵選擇Serial port setup,回車。此時游標在「change which setting」後面停留,它的上面有如下菜單:
只需輸入上面對應的字母,就可以進如相應的菜單進行設置。設置完成,回車,游標會回到「change which setting」後面,如此重復。完成按回車返回主菜單即可。
⑶ 如何在S3C2440上linux操作系統下將串口的波特率提高以致921600
在說說我做的這個事情,其實聽起來很簡單,就是把串口的波特率提上去,硬體環境呢,就是採用飛凌的TE2440-II(比較古老了,大家勿噴)操作系統是linux2.6.28,大家都知道,正常情況下,Linux下串口波特率最高到115200,因為我們特殊需要的原因,需要把波特率提高到至少460800,當然最理想的結果就是波特率達到921600,大的背景就是這個樣子了。
然後先考究硬體,看看在硬體上到底能不能滿足我們的要求,主控晶元S3C2440,在UART一章說在系統時鍾下,波特率最高可達115200,然後注釋中說如果Pclk達到60M,可以實現921600,我就按他說的,將主頻提高,順便將pclk提高到了60M,發現921600根本實現不了,230400波特率雖然能通,但是錯誤率很高,根本無法用,然後我又嘗試著將Pclk提高到了70M,通過這種飲鴆止渴的方式,波特率可以提高到230400並且穩定傳輸,但是更高的波特率則無法實現,而Pclk不能無限提高,因為我們開發板還連接了觸摸屏,在Pclk70M的情況下,觸摸屏經常重啟,說明這個方案不可行,所以就pass掉了,下面簡單說一下我怎麼更改的系統時鍾Fclk,Hclk,Pclk。這三個時鍾的關系以及計算方法我就不贅述了,我主要參考博客http://blog.csdn.NET/dong_hong/article/details/8469269進行修改
1)首先找到bootloader中 INC文件夾下的Option.inc文件,打開以後,找到如下代碼段,這段代碼就是主頻400M時對應的M,P和S值設置,需要更改主頻的話更改其中相應的數值幾個(後來我發現,其實這個地方不改也行,因為最終起作用的是第二步)
[ FCLK = 400000000
CLKDIV_VAL EQU5
;1:4:8
M_MDIV EQU
127 ;127
M_PDIV EQU
2 ;2
[ CPU_SEL = 32440001
M_SDIV EQU
1 ; 2440A
|
M_SDIV EQU
0 ; 2440X
]
]
2)找到u2440mon.c,然後在main()函數中找到如下代碼,修改case2中的mpll_val = (92<<12)|(1<<4)|(1);這一行(為啥修改這一行?因為在這個switch代碼有個j=2),其中三個數分別代表M,P,S。這才是決定主頻的關鍵。
switch(j) {
case 0:
//240
key = 14;
mpll_val = (112<<12)|(4<<4)|(1);
break;
case 1:
//320
key = 14;
mpll_val = (72<<12)|(1<<4)|(1);
break;
case 2:
//400
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
case 3:
//420!!!
key = 14;
mpll_val = (97<<12)|(1<<4)|(1);
break;
default:
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
}
3)然後再 2440lib.c文件中,找到 ChangeClockDivider()函數,這個函數是控制分頻比的,代碼如下,這兩個一個控制h_div,一個控制p_div。其中case 18: hdivn=2; break;這一行控制H分頻,具體怎麼改可以參考手冊。
switch(hdivn_val) {
case 11: hdivn=0; break;
case 12: hdivn=1; break;
case 13:
case 16: hdivn=3; break;
case 14:
case 18: hdivn=2; break;
}
switch(pdivn_val) {
case 11: pdivn=0; break;
case 12: pdivn=1; break;
}
只需以上三步,就可以更改系統主頻以及分頻比,得到自己想要的Fclk和Pclk。
然後再說說我把上一個方案否定了以後,再仔細閱讀晶元手冊,發現串口的時鍾源可以有三種方式獲得:pclk,fclk/n,exclk,而且手冊上說採用外部時鍾的話,可以做到更高的波特率,但是這需要更改硬體,從指定那個引腳引入一個時鍾,然後還要更改驅動程序,所以放棄了,所以只剩下一個路可以走,就是採用fclk/n的方式作為串口的時鍾源,因為fclk頻率很高,所以時鍾源提高了,就可以把波特率提上來。然後就開始看linux內核源代碼,因為串口的驅動早就集成到了linux內核之中,然後我就跳進了一個大坑。
其實串口本身的驅動並不復雜,如果裸機開發的話我感覺不難(強調一下,這個串口的裸機開發我沒有做過,請做過的人不要噴我),因為串口被封裝到了linux系統中,並且是層層封裝,最終被封裝成了tty的形式,所以我就從tty的驅動看起,抽絲剝繭,從裡面尋找蛛絲馬跡,
首先發現了s3c2440.c這個文件,通過調試得知,初始化的時候調用了其中的s3c2440_serial_init()函數,剛開始以為在這個文件中就這個函數有用,其實後來才知道,這個文件中的s3c2440_serial_getsource()和s3c2440_serial_setsource()在驅動中多次被調用。
然後考慮到,在上位機設置波特率的時候,調用的是系統函數cfsetispeed(),後經調試得知,這個函數調用了Samsung.c這個文件中的s3c24xx_serial_set_termios()這個函數,所有與串口相關的配置都與這個函數有關,因此鎖定了方向,只要從這個函數中找到與波特率以及時鍾源相關的語句,更改成我想要的即可,而這個函數又調用了很多子函數,但真正與波特率及時鍾源相關的函數就是如下幾句
/*
* Ask the core to calculate the divisor for us.
*/
baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
/* check to see if we need to change clock source */
if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
s3c24xx_serial_setsource(port, clksrc);
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
ourport->baudclk = NULL;
}
clk_enable(clk);
ourport->clksrc = clksrc;
ourport->baudclk = clk;
}
其中,uart_get_baud_rate()函數用於計算出上位機程序到設置的波特率的值,經我調試得知,上位機波特率從2400到921600都可以被准確的計算出來;所以這個函數跳過,然後看最後那個if語句,這個語句的作用是產看目前的時鍾源是否與設置的時鍾源相同,如果不相同,則按照設置的時鍾源進行更改,這裡面還涉及linux下的關於管理時鍾的一個結構體clk結構體,參照博客http://blog.chinaunix.Net/uid-26583794-id-3208153.html以及http://wenku..com/view/13b4c686b9d528ea80c77904.html我找到了linux下的mach-smdk2440.c這個文件,這個文件中定義了串口所用的clk結構體,這也是linux系統啟動時對串口的初始化配置結構體都在這,但是我更改過這個地方,讓他初始化配置是首選fclk作為串口的時鍾源,但是我發現這並沒有效果,所以繼續尋找中。
這樣就剩下一個函數可以考慮了,s3c24xx_serial_getclk(),進入這個函數你會發現,這個函數是對串口時鍾及波特率一個全面的配置,進入這個函數中,就有個結構體tmp_clksrc,這個結構體很關鍵,他的內容如下:
static struct s3c24xx_uart_clksrc tmp_clksrc = {
.name = "pclk",
.min_baud
= 0,
.max_baud
= 0,
.divisor
= 1,
};
從這個名字中就可以看出,它把串口的時鍾源內定成為了pclk,這也是罪魁禍首,但是當我把name更改為fclk時,整個系統就無法啟動了,包括前面說的更改mach-smdk2440.c中初始化配置,也是無法啟動,後來在配置串口是做了一個判斷,當波特率低於200000時,才有系統源配置不變,當波特率高於200000時,不在採用tmp_clksrc這個結構體,而是採用我自己定義的一個結構體,當然就是把name改成fclk,發現雖然只是能夠更改 裡面部分參數的時鍾源,而正在的時鍾源還是pclk,說明我的更改根本么有生效,由於這個linux調用太龐雜了,我就抱著試試看的態度,也是沒有辦法的辦法,在配置完串口時鍾的代碼之後,添加了如下幾行代碼,直接更改S3C2440的寄存器,我知道這樣做是很不「道德」的,而且很容易引起系統混亂,但是我只是這么試試,沒想到還真的有用。
在 samsung.c文件中添加
if (baud >= 200000)
{
printk("baud >= 200000 @-------------samsung.c\n");
__raw_writel(0x1fc5,S3C24XX_VA_UART0 + S3C2410_UCON);
__raw_writel(0x0fc5,S3C24XX_VA_UART1 + S3C2410_UCON);
__raw_writel(0x8fc5,S3C24XX_VA_UART2 + S3C2410_UCON);
__raw_writel(32,S3C24XX_VA_UART0 + S3C2410_UCON+0x24);//保證控制台的波特率還是115200用於顯示
__raw_writel(3,S3C24XX_VA_UART1 + S3C2410_UCON+0x24);//921600
//__raw_writel(3,S3C24XX_VA_UART1 + S3C2410_UCON+0x24);
}
上面這段代碼經我多次試驗得到的,因為一開始用的系統主時鍾fclk為400M,這樣算出來UBRDIV1分頻應該為3,但是這樣的話錯誤率比較高,還是導致無法傳輸,至此我終於明白手冊上為什麼說pclk在60M 可以實現921600了,因為用60M時鍾計算的話,分頻UBRDIV1為3.069,最接近整數3,所以在這個錯誤率下可以實現921600的波特率傳輸,所以我將系統時鍾fclk設置為420M,其中MDIV=97,PDIV=1,SDIV=1,而ucon0=0x1fc5,ucon1=0x0fc5,ucon2=0x8fc5,這樣n=1+6=7,所以串口的時鍾源為fclk/n=60M,可以得到精確的921600波特率,所以實現我剛開始的目標,其實要實現其他的波特率也可以,比如460800,計算後主時鍾fclk(盡量算出的分頻UBRDIV1最貼近整數),然後就可以實現了。
在這還有個小想法,提高串口波特率,還可以使用USB轉串口,因為USB轉串口可以實現921600,而linux中以及集成了USB轉串口的驅動,只需要在調用串口的那個open函數中改為調用USB轉串口的節點即可,當然,這個方案我沒有試,因為我們就一個USB口,而且還被佔用了,所以希望有需要的朋友可以試一下。
⑷ linux下串口發送數據遇到一個非常奇怪的問題,請高手門指教。
連串口,中斷設定一般控制這幾個參數就可以了:
1。波特率 -》一般串口設置成115200 ,你的終端可內以輸出容訊息,這個參數應該沒問題
2。奇偶校驗 -》一般關閉
3。流控 -》 一般關閉
4。停止位 -》一般設置為無
5。有時候要設置數據位 -》8位
我一直是這么用的,目前還沒出過什麼問題 。
⑸ linux 嵌入式系統中,更改串口波特率,無法生效
如果是自己寫的驅動,先檢查驅動是否支持波特率的修改。
如果支持:
stty -F /dev/ttyS0 speed 115200 cs8 -parenb -cstopb -echo 修改 波特率115200 8 N 1
下位機採用相同的配置,並在linux終端輸入echo "hello" > /dev/ttyS0 看看是否能通信。
⑹ linux串口設置時struct termios中各個選項的具體意思是什麼
設置串口
最基本的設置串口包括波特率設置,效驗位和停止位設置。串口的設置主要是設置 struct termios 結構體的各成員值。
struct termio
{ unsigned short c_iflag; /* 輸入模式標志 */
unsigned short c_oflag; /* 輸出模式標志 */
unsigned short c_cflag; /* 控制模式標志*/
unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */
};
設置這個結構體很復雜,我這里就只說說常見的一些設置:
波特率設置 下面是修改波特率的代碼:
struct termios Opt;
tcgetattr(fd, &Opt);
cfsetispeed(&Opt,B19200); /*設置為19200Bps*/
cfsetospeed(&Opt,B19200);
tcsetattr(fd,TCANOW,&Opt);
一般簡單的問題,網路和google都有,搜索一下就有了。