zl程序教程

您现在的位置是:首页 >  其他

当前栏目

2023年 beagle bone black教程4-串口的使用

2023-04-18 14:23:57 时间

beagle bone black教程4-串口的使用

1. 简单使用

BeagleBone有六个板载串行端口。其中串口0已经被系统占用为串口终端了。在 BeagleBone Black wireless上,驱动好像都已经启用了。(debian 版本10.0)

我们进入设备文件夹观察。

cd /dev/
ls

可以看到有好多设备。其中ttyO0-ttyO5即我们要找的串口。
在这里插入图片描述
如果看不清,可以使用ls ttyO*,这样只列出ttyO开头的文件。
在这里插入图片描述
UART 映射到引脚和设备,如下所示:

RXTXCTSRTSDevice注释
UART0J1_4J1_5/dev/ttyO0系统终端
UART1P9_26P9_24P9_20P9_19/dev/ttyO1
UART2P9_22P9_21P8_37P8_38/dev/ttyO2
UART3P9_42P8_36P8_34/dev/ttyO3仅限 TX
UART4P9_11P9_13P8_35P8_33/dev/ttyO4
UART5P8_38P8_37P8_31P8_32/dev/ttyO5

这个引脚是怎么看到的呢,通过设备数可以观察。

cd /lib/firmware
ls 

在这里插入图片描述你会看到很多的设备树,这里我们只关心串口

ls BB-UART* #只列出BB-UART开头的文件

在这里插入图片描述
这里BB-UARTx-00A0.dtbo 格式的为我们所使用的。至于名字带有RTSCTS的是啥就不清楚了,问题不大。

我们打开一个文件看看。

cat BB-UART4-00A0.dtbo 

在这里插入图片描述
有乱码,不重要。我们还是可以看到信息的:P9.13 和P9.11就是所用串口的引脚。

为了让串口能用,我们需要先使能( 如果不使能,永远用不了,曾因此耗费了一天时间)。需要对/boot/uEnv.txt文件进行更改。添加如下语句。

# UART 1
uboot_overlay_addr0=/lib/firmware/BB-UART1-00A0.dtbo
# UART 2
uboot_overlay_addr1=/lib/firmware/BB-UART2-00A0.dtbo
# UART 4
uboot_overlay_addr2=/lib/firmware/BB-UART4-00A0.dtbo
# UART 5
uboot_overlay_addr3=/lib/firmware/BB-UART5-00A0.dtbo
# UART 3 (only TX). Note that in "uboot_overlay_addrX", the X need not be = UART id
uboot_overlay_addr4=/lib/firmware/BB-UART3-00A0.dtbo

另外,在文件末尾可能要加下面这句话(它是注释状态,所以应该没有影响,如果有问题再把注释去掉看看)

#cape_enable=capemgr.enable_partno=BB-UART1,BB-UART2,BB-UART4,BB-UART5

打开文件并添加。

 sudo nano /boot/uEnv.txt

在这里插入图片描述
如图便配置好了。图中使能了UART1-UART5,平时按需使能就好。这些配置使用的是默认的引脚。默认波特率为9600。

需要重启生效

使用USB-TTL模块连接 UART2的RX和TX(P9.22 和 P9.21)。

在串口终端往串口2写数据

echo "hello  I am UART 2" > /dev/ttyO2

在串口调试助手(连接USB-TTL模块),可以看到如下画面。
在这里插入图片描述
ok,没有问题。

2. 基本编程发送

直接上代码

#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int uart_fd;
void uart4_init(void)
{
    uart_fd = open("/dev/ttyO4",O_RDWR|O_NOCTTY|O_NONBLOCK);//可读写 非终端设备 不阻塞(不加这个有时候会卡死)
    if(uart_fd < 0) {
        perror("open error");   
        exit(-1); 
    }   
    
    struct termios new_cfg;
    memset(&new_cfg,0,sizeof(struct termios));
    cfmakeraw(&new_cfg);//配置为原生模式
    
    new_cfg.c_cflag |= CREAD;//接受使能
    cfsetspeed(&new_cfg,B115200);//波特率115200
    new_cfg.c_cflag &= ~CSIZE; //将数据位相关的比特位清零
    new_cfg.c_cflag|=CS8;//8 位bites
    
    new_cfg.c_cflag &= ~PARENB;//无校验位
    new_cfg.c_iflag &= ~INPCK;//无校验位
    
    new_cfg.c_cflag&= ~CSTOPB;//1个停止位
    
    new_cfg.c_cc[VTIME] = 0;//不等待。 单位 0.1s
    new_cfg.c_cc[VMIN] = 0;//最小等待接收字符数量0 不等待
    
    tcflush(uart_fd,TCIOFLUSH);//清除缓冲
    tcsetattr(uart_fd,TCSANOW,&new_cfg);//配置生效
}

int main(void)
{
    printf("start
"); 
    uart4_init(); 

    while(1){
       printf("work
");
       write(uart_fd,"this is uart 4 test
",20);
        sleep(1);
    }
   
}

在vscode终端里,编译与执行(你用环境或者文件名与我不一样就自行操作 )

cd ~/code_test/
gcc -o uart uart.c
./uart

在这里插入图片描述
在这里插入图片描述
如果有乱码。重启板子即可。

3.编程+poll接收

/************************* uart_poll.c ****************************/
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <pthread.h>

int uart_fd;
void thread_uart_start(void);
static void uart_handle(unsigned char res);
void uart4_init(void)
{
    uart_fd = open("/dev/ttyO4",O_RDWR|O_NOCTTY|O_NONBLOCK);//串口3 可读可写 非终端模式 不阻塞(不加这个可能有问题)
    if(uart_fd < 0) perror("open error");   
    
    struct termios new_cfg;
    memset(&new_cfg,0,sizeof(struct termios));
    cfmakeraw(&new_cfg);    //配置为原生模式
    
    new_cfg.c_cflag |= CREAD;//接受使能
    cfsetspeed(&new_cfg,B115200);//波特率115200
    new_cfg.c_cflag &= ~CSIZE; //将数据位相关的比特位清零
    new_cfg.c_cflag|=CS8;//8 位bites
    
    new_cfg.c_cflag &= ~PARENB;//无校验位
    new_cfg.c_iflag &= ~INPCK;//无校验位
    
    new_cfg.c_cflag&= ~CSTOPB;//1个停止位
    
    new_cfg.c_cc[VTIME] = 0;//不等待。此时对串口得操作为非阻塞模式
    new_cfg.c_cc[VMIN] = 0;//对接收字符没有要求
    
    tcflush(uart_fd,TCIOFLUSH);//清除缓冲
    tcsetattr(uart_fd,TCSANOW,&new_cfg);//配置生效

}

void thread_uart_start(void)
{
    printf("uart thread started
");
    uart4_init();

     struct pollfd fds;  
    fds.fd=uart_fd;     //串口
    fds.events=POLLIN;  //
    fds.revents=0;//
    
    while(1){
        int ret=poll(&fds,1,-1);//2 表示fds里元素个数为1 -1为一直阻塞   阻塞接收数据
        if(ret<0) perror("poll error");
    
        if(fds.revents & POLLIN){//串口有数据
            unsigned char buf;
            ret = read(uart_fd,&buf,1);
            if(ret>0) printf("串口读取%d bytes
",ret);//打印数据个数
            uart_handle(buf);
        }
    }
}


static void uart_handle(unsigned char res)
{
    static int i=0;
    static unsigned char buf[50]; 
    i++;
    printf("%d rer:%c
",i,res);//打印数据

}

int main(void)
{
    pthread_t tid_uart;
    pthread_create(&tid_uart, NULL, (void *)thread_uart_start, NULL);//创建串口接收线程
    while(1)
    {
        sleep(1);
        printf("I am running
");
        write(uart_fd, "test
", 5);
    }  
}
gcc -o uart_poll uart_poll.c -lpthread

./uart_poll

就是板子间隔一段时间打印一次“I am running”,然后往串口写入:“test”。 如果串口中断有接收,则把它打印出来。