1. 程式人生 > >樹莓派_Linux串列埠程式設計_實現自發自收

樹莓派_Linux串列埠程式設計_實現自發自收

串列埠是計算機上一種非常通用裝置通訊的協議,常用PC機上包含的是RS232規格的串列埠,具有連線線少,通訊簡單,得到廣泛的使用。
Linux對所有裝置的訪問是通過裝置檔案來進行的,串列埠也是這樣,為了訪問串列埠,只需開啟其裝置檔案即可操作串列埠裝置。在linux系統下面,每一個串列埠裝置都有裝置檔案與其關聯,裝置檔案位於系統的/dev目錄下面。如linux下的/ttyS0,/ttyS1分別表示的是串列埠1和串列埠2。
樹莓派UART埠的位置:見下圖的GPIO14(TXD)、GPIO 15(RXD)
本文是基於樹莓派的環境,樹莓派中可以使用串列埠/dev/ttyAMA0
要使用這個串列埠,必須先進行設定:
1.修改/boot/cmdline.txt
    輸入下面指令:    sudo nano /boot/cmdline.txt    刪除紅色部分:dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait    最終變為dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait 2.修改/etc/inittab    輸入下面指令:    sudo nano /etc/inittab    註釋掉最後一行內容: #
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
OK、重啟下raspberry pi現在就可以自己編寫程式測試串列埠了。我是把TXD與RXD短接,實現自發自收的。
程式如下:
recv.h
#ifndef _RECV_H
#define _RECV_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>

#define BAUDRATE B115200 ///Baud rate : 115200
#define DEVICE "/dev/ttyAMA0"
#define SIZE 1024

#endif

recv.c
#include "Recv.h"

int nFd = 0;
struct termios stNew;
struct termios stOld;

//Open Port & Set Port
int SerialInit()
{
	nFd = open(DEVICE, O_RDWR|O_NOCTTY|O_NDELAY);
	if(-1 == nFd)
	{
		perror("Open Serial Port Error!\n");
		return -1;
	}
	if( (fcntl(nFd, F_SETFL, 0)) < 0 )
	{
		perror("Fcntl F_SETFL Error!\n");
		return -1;
	}
	if(tcgetattr(nFd, &stOld) != 0)
	{
		perror("tcgetattr error!\n");
		return -1;
	}

	stNew = stOld;
	cfmakeraw(&stNew);//將終端設定為原始模式,該模式下所有的輸入資料以位元組為單位被處理

	//set speed
	cfsetispeed(&stNew, BAUDRATE);//115200
	cfsetospeed(&stNew, BAUDRATE);

	//set databits  
	stNew.c_cflag |= (CLOCAL|CREAD);
	stNew.c_cflag &= ~CSIZE;
	stNew.c_cflag |= CS8;

	//set parity  
    stNew.c_cflag &= ~PARENB;  
    stNew.c_iflag &= ~INPCK;

	//set stopbits  
    stNew.c_cflag &= ~CSTOPB;
	stNew.c_cc[VTIME]=0;	//指定所要讀取字元的最小數量
	stNew.c_cc[VMIN]=1;	//指定讀取第一個字元的等待時間,時間的單位為n*100ms
				//如果設定VTIME=0,則無字元輸入時read()操作無限期的阻塞
	tcflush(nFd,TCIFLUSH);	//清空終端未完成的輸入/輸出請求及資料。
    if( tcsetattr(nFd,TCSANOW,&stNew) != 0 )
	{
		perror("tcsetattr Error!\n");
		return -1;
	}

	return nFd;
}

int main(int argc, char **argv)
{
	int nRet = 0;
	char buf[SIZE];

	if( SerialInit() == -1 )
	{
		perror("SerialInit Error!\n");
		return -1;
	}

	bzero(buf, SIZE);
	while(1)
	{
		nRet = read(nFd, buf, SIZE);
		if(-1 == nRet)
		{
			perror("Read Data Error!\n");
			break;
		}
		if(0 < nRet)
		{
			buf[nRet] = 0;
			printf("Recv Data: %s\n", buf);
		}
	}

	close(nFd);
	return 0;
}

上面的是接受程式,可以接受字串資訊並列印,傳送程式跟上面一樣,只要把read改為write就行了,這裡就不記錄了。
程式執行結果:
參考文件: