beaglebone使用笔记(六):串口收发

一、前言

使用beagle bone的串口功能

二、步骤

1、查询外设名称

在linux中,外设以文件的形式存在,所以查询要加载的外设的文件地址依次打开外设。beaglebone的外设信息存放在 /lib/firmware 下,所以输入 ls /lib/firmware | grep UART 即可查询可加载的串口外设。本文使用UART1,所以文件地址是 /lib/firmware/BB-UART1-00A0.dtbo
在这里插入图片描述

2、加载外设(两种方法)

(1)、预加载

beaglebone开机的时候会按照 /boot/uEnv.txt 里面的内容加载外设,因此修改该文件就可以让beaglebone开机的时候自动加载串口,输入 sudo vim /boot/uEnv.txt,并在文件里添加
uboot_overlay_addr0=/lib/firmware/BB-UART1-00A0.dtbo保存退出重启beaglebone即可。
这里的 addr0 根据实际顺序进行修改。
在这里插入图片描述

(2)、即时加载

该加载方式需要beaglebone每次开机重新加载。

3、测试

将串口IO通过CH340与电脑连接,打开串口后
输入 echo “hello” > /dev/ttyS1 进行测试。
在这里插入图片描述

4、C语言使用串口

(1)、头文件:BBB_serial.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <error.h>
#include <termios.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/stat.h>

typedef struct serial_data {
    char rxbuff[32];//发送/接受数据
    char txbuff[32];//发送/接受数据
    int serfd;//串口文件描述符
}ser_Data;

//端口地址 串口句柄号 波特率 B9600 B115200
unsigned char serial_init(const char* port, int baudrate, ser_Data* serial);//读写模式打开串口

/********************线程接收串口数据示例************************/
void* sersend(void* arg);//串口发送线程函数
void* serrecv(void* arg);//串口发送线程函数

(2)、源文件:BBB_serial.cpp

#include <BBB_serial.h>
//该函数以读写模式打开串口
unsigned char serial_init(const char* port, int baudrate, ser_Data* serial)
{
	//读写方式打开串口文件
    serial->serfd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);//修改第二个参数改变打开方式
	//判断是否打开成功
	if (serial->serfd < 0) { printf("%s open faild\r\n", port);return -1;}
	else { printf("%s open success\r\n", port); }
	//串口参数设置
	termios* ter_s = (termios*)malloc(sizeof(*ter_s));//初始化串口参数结构体
	bzero(ter_s, sizeof(*ter_s));//初始化结构体,全部置零
    ter_s->c_cflag |= CLOCAL | CREAD; //激活本地连接与接受使能
    ter_s->c_cflag &= ~CSIZE;//失能数据位屏蔽
    ter_s->c_cflag |= CS8;//8位数据位
    ter_s->c_cflag &= ~CSTOPB;//1位停止位
    ter_s->c_cflag &= ~PARENB;//无校验位
    ter_s->c_cc[VTIME] = 10;
    ter_s->c_cc[VMIN] = 32;//读取32个
    /*1 VMIN> 0 && VTIME> 0
        VMIN为最少读取的字符数,当读取到一个字符后,会启动一个定时器,在定时器超时事前,
        如果已经读取到了VMIN个字符,则read返回VMIN个字符。如果在接收到VMIN个字符之前,
        定时器已经超时,则read返回已读取到的字符,注意这个定时器会在每次读取到一个字符后
        重新启用,即重新开始计时,而且是读取到第一个字节后才启用,也就是说超时的情况下,
        至少读取到一个字节数据。
        2 VMIN > 0 && VTIME== 0
        在只有读取到VMIN个字符时,read才返回,可能造成read被永久阻塞。
        3 VMIN == 0 && VTIME> 0
        和第一种情况稍有不同,在接收到一个字节时或者定时器超时时,read返回。如果是超时这种情况,read返回值是0。
        4 VMIN == 0 && VTIME== 0
        这种情况下read总是立即就返回,即不会被阻塞。----by 解释粘贴自博客园
    */
    cfsetispeed(ter_s, baudrate);//设置输入波特率
    cfsetospeed(ter_s, baudrate);//设置输出波特率
    tcflush(serial->serfd, TCIFLUSH);//刷清未处理的输入和/或输出
    if (tcsetattr(serial->serfd, TCSANOW, ter_s) != 0) {printf("com set error!\r\n");}
    free(ter_s);//释放内存
    return 0;
}

void* sersend(void* arg)//串口发送线程函数
{
    ser_Data* serial = (ser_Data*) arg;
    while (1) 
    {
        write(serial->serfd, "send\n", 5);
        sleep(1);
    }
    return NULL;
}

void* serrecv(void* arg)//串口接收线程函数
{
    
    ser_Data* serial = (ser_Data*)arg;
    int datanumber;
    while (1)
    {
        datanumber = read(serial->serfd, serial->rxbuff, 32);
        if (datanumber > 0)
        {
            printf("%d\n", datanumber);
        }
    }
    return NULL;
}

(3)主函数: main

#include <stdio.h>
#include <BBB_serial.h>

ser_Data serial = { 0 };//串口结构体

int main(void)
{
    unsigned char res = 0;
    res = serial_init("/dev/ttyS1", B9600, &serial);//打开串口
    if (res) return 0;
    pthread_t pid1, pid2;
    pthread_attr_t* pthread_arr1, * pthread_arr2;
    pthread_arr1 = NULL; pthread_arr2 = NULL;
    pthread_create(&pid1, pthread_arr1, serrecv, (void*)(&serial));//接收任务
    pthread_create(&pid2, pthread_arr2, sersend, (void*)(&serial));//发送任务
    pthread_join(pid1, NULL);
    pthread_join(pid2, NULL);

    while (1)
    {

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值