目錄
1、串口基本認(rèn)知
2、USB轉(zhuǎn)TTL,使用ch340通信
2.1?TTL電平
2.2?串口接線方式
?3、串口通信常用的API
4、代碼通信實例
4.1 發(fā)送一個字符/字符串到串口
4.2?樹莓讀取串口數(shù)據(jù)(字符串)
4.3?雙方互相通信
4.3.1 樹莓派接收一個字符同時再發(fā)送字符到串口
4.3.2?樹莓派子進(jìn)程接收字符串父進(jìn)程每一秒打印一個字符串到串口
1、串口基本認(rèn)知
串行接口簡稱串口,也稱 串行通信 接口或 串行通訊接口 (通常指 COM 接口 ),是采用串行通信方 式的 擴(kuò)展接口 。串行 接口 ( Serial Interface )是指數(shù)據(jù)一位一位地順序傳送。其特點是 通信線路 簡 單,只要一對傳輸線就可以實現(xiàn)雙向通信(可以直接利用電話線作為傳輸線),從而大大降低了成本,特別適用于遠(yuǎn)距離通信,但傳送速度較慢
- 是設(shè)備間接線通信的一種方式
- 數(shù)據(jù)一位一位地順序傳送
- 雙向通信,全雙工
- 傳送速度相對較慢
串口通信經(jīng)常使用在多機(jī)通信中。不管是軟件還是硬件,都存在模塊化的編程思想。
●?半雙工:A傳數(shù)據(jù)給B,B只接收數(shù)據(jù),什么也不能做;
●?全雙工:A傳數(shù)據(jù)給B的同時,B也能給A傳輸數(shù)據(jù);
實現(xiàn)串口多機(jī)通信的協(xié)議設(shè)置:串口號,數(shù)據(jù)格式和波特率。
● 串口號:CH340軟件來接收或生成串口號;
● 波特率:好比人的語速,常用的115200,9600;
● 數(shù)據(jù)格式:可以比作人交流的語種。數(shù)據(jù)位;奇偶校驗位;停止位。
類似于人和人在交流溝通時,都必須使用同一種語言和語速,這樣通信雙方才能明白對方的內(nèi)容。
2、USB轉(zhuǎn)TTL,使用ch340通信
作用:將通信雙方識別的電平轉(zhuǎn)換為通信電平。
2.1?TTL電平
? ? ? ?筆記本電腦通過 TTL 電平與單片機(jī)通信? ? ? ?TX 發(fā)送線(端口) 3.1? ? ? ?RX 接收線 ( 端口) 3.0? ? ? ?USB 轉(zhuǎn) TTL ,使用 ch340 通信
● 我們常用的單片機(jī),引出來的串口,如果不加其他的接口電路,出來的信號就是TTL電平;
● 如果需要看串口的打印信息,一般是需要接一個上位機(jī)的,常規(guī)的就是電腦,而現(xiàn)在的電腦一般的通信接口只有USB;
● 對于USB口而言,是沒法和TTL串口直接通信的,因為接口不匹配,電平也不匹配,這時候就需要借助其它設(shè)備來實現(xiàn)接口與電平的轉(zhuǎn)換;
● 常規(guī)操作是使用CH340這種芯片所制作的USB轉(zhuǎn)串口模塊,這個模塊就可以實現(xiàn)TTL串口和USB之前的轉(zhuǎn)換。
2.2?串口接線方式
RXD :數(shù)據(jù)輸入引腳,數(shù)據(jù)接受;TXD :數(shù)據(jù)發(fā)送引腳,數(shù)據(jù)發(fā)送;
3、串口通信常用的API
使用時需要包含頭文件:#include <wiringSerial.h>
int serialOpen (char *device, int baud) | device:串口的地址,在Linux中就是設(shè)備所在的目錄。 默認(rèn)一般是"/dev/ttyAMA0",我的是這樣的。 baud:波特率 返回:正常返回文件描述符,否則返回-1失敗。 |
打開并初始串口 |
void serialClose (int fd) | fd:文件描述符 | 關(guān)閉fd關(guān)聯(lián)的串口 |
void? serialPutchar (int fd, unsigned char c) | fd:文件描述符 c:要發(fā)送的數(shù)據(jù) |
發(fā)送一個字節(jié)的數(shù)據(jù)到串口 |
void? serialPuts (int fd, char *s) | fd:文件描述符 s:發(fā)送的字符串,字符串要以'\0'結(jié)尾 |
發(fā)送一個字符串到串口 |
void? serialPrintf (int fd, char *message, …) | fd:文件描述符 message:格式化的字符串 |
像使用C語言中的printf一樣發(fā)送數(shù)據(jù)到串口 |
int?? serialDataAvail (int fd) | fd:文件描述符 返回:串口緩存中已經(jīng)接收的,可讀取的字節(jié)數(shù),-1代表錯誤 |
?獲取串口緩存中可用的字節(jié)數(shù)。 |
int serialGetchar (int fd) | fd:文件描述符 返回:讀取到的字符 |
從串口讀取一個字節(jié)數(shù)據(jù)返回。 如果串口緩存中沒有可用的數(shù)據(jù),則會等待10秒,如果10后還有沒,返回-1 所以,在讀取前,做好通過serialDataAvail判斷下。 |
void serialFlush (int fd) | fd:文件描述符 | 刷新,清空串口緩沖中的所有可用的數(shù)據(jù)。 |
*size_t read(int fd,void * buf ,size_t count); | fd:文件描述符 buf:需要發(fā)送的數(shù)據(jù)緩存數(shù)組 count:發(fā)送buf中的前count個字節(jié)數(shù)據(jù) 返回:實際寫入的字符數(shù),錯誤返回-1? |
這個是Linux下的標(biāo)準(zhǔn)IO庫函數(shù),需要包含頭文件#include <unistd.h> 當(dāng)要發(fā)送到的數(shù)據(jù)量過大時,wiringPi建議使用這個函數(shù)。 |
*size_t read(int fd,void * buf ,size_t count); | fd:文件描述符 buf:接受的數(shù)據(jù)緩存的數(shù)組 count:接收的字節(jié)數(shù). 返回:實際讀取的字符數(shù)。 |
這個是Linux下的標(biāo)準(zhǔn)IO庫函數(shù),需要包含頭文件#include <unistd.h> 當(dāng)要接收的數(shù)據(jù)量過大時,wiringPi建議使用這個函數(shù)。 |
注:初次使用樹莓串口編程,需要配置,不然容易出錯。
/* 修改 cmdline.txt文件 */
>cd /boot/
>sudo vim cmdline.txt
刪除【】之間的部分
dwc_otg.lpm_enable=0 【console=ttyAMA0,115200】 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
/*修改 inittab文件 */(有的有,有的沒有,沒有則不用修改)
>cd /etc/
>sudo vim inittab注釋掉最后一行內(nèi)容:,在前面加上 # 號
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
sudo reboot 重啟
4、代碼通信實例
4.1 發(fā)送一個字符/字符串到串口
#include<wiringPi.h>
#include<wiringSerial.h>
#include<stdio.h>
int main()
{
if(-1==wiringPiSetup()){
printf("初始化庫錯誤\n");
return -1;
}
int fd; //Linux 的思想是:將一切IO設(shè)備,都看做文件,fd就是代表串口抽象出來的文件
if((fd = serialOpen("/dev/ttyAMA0",9600))==-1) //初始化串口,波特率9600
{
printf("打開串口錯誤");
return -1;
}
while(1)
{
//serialPutchar (fd, 'w');//打印一個字符
serialPuts (fd, "wangjian niubi\r\n");//打印字符串
delayMicroseconds (1000000);//每一秒打印一次
}
return 0;
}
結(jié)果演示:
4.2?樹莓讀取串口數(shù)據(jù)(字符串)
#include <stdlib.h>
#include <wiringSerial.h>
#include <wiringPi.h>
#include <stdio.h>
#include<string.h>
#include <unistd.h>
int main()
{
int fd;
if(wiringPiSetup() == -1) {
printf("硬件接口初始化失敗!\n");
exit(-1);
}
fd=serialOpen("/dev/ttyAMA0",9600);//打開并初始化串口,波特率9600
if(fd != -1){
printf("serial open success\n");
printf("fd=%d\n",fd);
}
char cmd[128]={0};
int n=0;
while(1)
{
int i=0;
memset(cmd,0,128); //情況字符數(shù)組
while(serialDataAvail(fd)!=0)
{
char c=serialGetchar(fd); //接受一個字節(jié)
cmd[i]=c; //將接收到的每一個字節(jié)都存到數(shù)組中
i++;
if(i==7){ //當(dāng)字節(jié)數(shù)超過8個的時候,需要延時一會供串口緩存
delay(200); //延時200ms
}
}
i=0;
while(cmd[i]!=0)
{
printf("%c",cmd[i]); //將數(shù)組打印出來
i++;
}
if(i>0){
printf("\n"); //換行
}
}
return 0;
}
結(jié)果演示:
4.3?雙方互相通信
4.3.1 樹莓派接收一個字符同時再發(fā)送字符到串口
#include <stdlib.h>
#include <wiringSerial.h>
#include <wiringPi.h>
#include <stdio.h>
#include<string.h>
#include <unistd.h>
int main()
{
int fd;
if(wiringPiSetup() == -1){
printf("硬件接口初始化失敗!\n");
exit(-1);
}
fd=serialOpen("/dev/ttyAMA0",9600);//打開并初始化串口,波特率9600
if(fd != -1){
printf("serial open success\n");
printf("fd=%d\n",fd);
}
while(1)
{
while(serialDataAvail(fd)!=0)
{
char cmd = 0;
cmd = serialGetchar (fd);
printf("get data:%c\n",cmd);
if(cmd == '2'){
serialPuts(fd,"hello 2\r\n");//串口中換行\(zhòng)r\n結(jié)合使用
}
if(cmd == '3'){ //樹莓收到字符3時,就發(fā)送hello 3這個字符串到串口
serialPuts(fd,"hello 3\r\n");
}
if(cmd == '4'){
serialPuts(fd,"hello 4\r\n");
}
}
}
return 0;
}
結(jié)果演示:
4.3.2?樹莓派子進(jìn)程接收字符串父進(jìn)程每一秒打印一個字符串到串口
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
int main()
{
char cmd[128] = {0};
wiringPiSetup();
int fd =serialOpen("/dev/ttyAMA0",9600); //打開串口
if(fd == -1){ //如果打開串口失敗則退出程序
printf("serialOpen failed!\n");
return 0;
}
if(fork() == 0){ //創(chuàng)建子進(jìn)程讀取串口發(fā)送來的數(shù)據(jù)
while(1)
{
int i=0;
memset(cmd,0,128); //情況字符數(shù)組
while(serialDataAvail(fd)!=0)
{
char c=serialGetchar(fd); //接受一個字節(jié)
cmd[i]=c;
i++;
if(i==7) //當(dāng)字節(jié)數(shù)超過8個的時候,需要延時一會供串口緩存
{
delay(200); //延時200ms
}
}
i=0;
while(cmd[i]!=0)
{
printf("%c",cmd[i]); //打印十六進(jìn)制
i++;
}
if(i>0){
printf("\n"); //換行
}
}
}else{//父進(jìn)程
while(1)
{
serialPrintf(fd,"hello world!!\n"); //父進(jìn)程每隔三秒發(fā)送一次hello world!!
delay(1000);
}
}
return 0;
}
?結(jié)果演示:
上文串口相關(guān)API的部分內(nèi)容借鑒了下面的csdn:文章來源:http://www.zghlxwxcb.cn/news/detail-771583.html
https://www.cnblogs.com/lulipro/p/5992172.html文章來源地址http://www.zghlxwxcb.cn/news/detail-771583.html
到了這里,關(guān)于基于Linux的樹莓派和電腦之間的串口通信編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!