#traits #uart #serial

embedded-serial

一些特性描述嵌入式串行(UART)设备的功能

3个版本 (重大变更)

使用旧的Rust 2015

0.5.0 2017年2月1日
0.4.0 2017年1月29日
0.3.0 2016年11月19日

#44 in #uart


2 crate 中使用

MIT 协议

26KB
208

嵌入式串行特性

简介

此crate包含适合嵌入式开发的特性。这允许开发者创建依赖于通用UART功能的crate(例如,AT命令接口),使得应用程序开发者可以将crate与板上的特定UART结合起来。

它类似于C语言中使用函数 getcputc 来解耦IO设备与库的思想,但以一种更加Rust的风格。

特性有接收和发送、阻塞、带超时阻塞和非阻塞的变体。

未解答的问题

  • 如果不同的特性使用相同的函数名会更好吗?

lib.rs:

嵌入式串行特性

描述串行端口(UART)功能的特性。

在这里,串行端口是指一次可以顺序发送和/或接收一个八位字节的数据的设备。八位字节使用 u8 类型表示。我们在这里只谈论八位字节,而不是字符(尽管如果您使用ASCII或UTF-8对字符串进行编码,它们将成为一个八位字节的序列)。

此crate包含适合嵌入式开发的特性。这允许开发者创建依赖于通用UART功能的crate(例如,AT命令接口),使得应用程序开发者可以将crate与板上的特定UART结合起来。

它类似于C语言中使用函数 getcputc 来解耦IO设备与库的思想,但以一种更加Rust的风格。

以下是 MutBlockingTx 特性的示例。

use embedded_serial::MutBlockingTx;

struct SomeStruct<T> { uart: T };

impl<T> SomeStruct<T> where T: MutBlockingTx {
    fn new(uart: T) -> SomeStruct<T> {
        SomeStruct { uart: uart }
    }

    fn write_data(&mut self) -> Result<(), <T as MutBlockingTx>::Error> {
        self.uart.puts(b"AT\n").map_err(|e| e.1)?;
        Ok(())
    }
}

以下是 MutBlockingTxWithTimeout 特性的示例。

struct SomeStruct<T> { uart: T };

use embedded_serial::MutBlockingTxWithTimeout;

impl<T> SomeStruct<T> where T: MutBlockingTxWithTimeout {
    fn new(uart: T) -> SomeStruct<T> {
        SomeStruct { uart: uart }
    }

    fn write_data(&mut self, timeout: &<T as MutBlockingTxWithTimeout>::Timeout) -> Result<bool, <T as MutBlockingTxWithTimeout>::Error> {
        let len = self.uart.puts_wait(b"AT\n", timeout).map_err(|e| e.1)?;
        Ok(len == 3)
    }
}

以下是 MutNonBlockingTx 特性的示例。您将调用 write_data 函数,直到它返回 Ok(true)

use embedded_serial::MutNonBlockingTx;

struct SomeStruct<T> {
    sent: Option<usize>,
    uart: T
};

impl<T> SomeStruct<T> where T: MutNonBlockingTx {

    fn new(uart: T) -> SomeStruct<T> {
        SomeStruct { uart: uart, sent: Some(0) }
    }

    fn write_data(&mut self) -> Result<bool, <T as MutNonBlockingTx>::Error> {
        let data = b"AT\n";
        if let Some(len) = self.sent {
            match self.uart.puts_try(&data[len..]) {
                // Sent some or more of the data
                Ok(sent) => {
                    let total = len + sent;
                    self.sent = if total == data.len() {
                        None
                    } else {
                        Some(total)
                    };
                    Ok(false)
                }
                // Sent some of the data but errored out
                Err((sent, e)) => {
                    let total = len + sent;
                    self.sent = if total == data.len() {
                        None
                    } else {
                        Some(total)
                    };
                    Err(e)
                }
            }
        } else {
            Ok(true)
        }
    }
}

在这个示例中,我们从阻塞串行端口读取了三个八位字节。

use embedded_serial::MutBlockingRx;

pub struct SomeStruct<T> { uart: T }

impl<T> SomeStruct<T> where T: MutBlockingRx {
    pub fn new(uart: T) -> SomeStruct<T> {
        SomeStruct { uart: uart }
    }

    pub fn read_response(&mut self) -> Result<(), <T as MutBlockingRx>::Error> {
        let mut buffer = [0u8; 3];
        // If we got an error, we don't care any many we actually received.
        self.uart.gets(&mut buffer).map_err(|e| e.1)?;
        // process data in buffer here
        Ok(())
    }
}

在这个示例中,我们带超时从阻塞串行端口读取了三个八位字节。

use embedded_serial::MutBlockingRxWithTimeout;

pub struct SomeStruct<T> { uart: T }

impl<T> SomeStruct<T> where T: MutBlockingRxWithTimeout {
    pub fn new(uart: T) -> SomeStruct<T> {
        SomeStruct { uart: uart }
    }

    pub fn read_response(&mut self, timeout: &<T as MutBlockingRxWithTimeout>::Timeout) -> Result<bool, <T as MutBlockingRxWithTimeout>::Error> {
        let mut buffer = [0u8; 3];
        // If we got an error, we don't care any many we actually received.
        let len = self.uart.gets_wait(&mut buffer, timeout).map_err(|e| e.1)?;
        // process data in buffer here
        Ok(len == buffer.len())
    }
}

在这个示例中,我们从非阻塞串行端口读取了16个八位字节到一个向量中,该向量的大小正好等于我们迄今为止读取的量。您将调用 read_data 函数,直到它返回 Ok(true)。这与其他示例的不同之处在于,我们有一个对UART的不可变引用,而不是拥有它。

use embedded_serial::ImmutNonBlockingRx;

struct SomeStruct<'a, T> where T: 'a {
    buffer: Vec<u8>,
    uart: &'a T
};

const CHUNK_SIZE: usize = 4;
const WANTED: usize = 16;

impl<'a, T> SomeStruct<'a, T> where T: ImmutNonBlockingRx {

    fn new(uart: &T) -> SomeStruct<T> {
        SomeStruct { uart: uart, buffer: Vec::new() }
    }

    fn read_data(&mut self) -> Result<bool, <T as ImmutNonBlockingRx>::Error> {
        let mut buffer = [0u8; CHUNK_SIZE];
        if self.buffer.len() < WANTED {
            let needed = WANTED - self.buffer.len();
            let this_time = if needed < CHUNK_SIZE { needed } else { CHUNK_SIZE };
            match self.uart.gets_try(&mut buffer[0..needed]) {
                // Read some or more of the data
                Ok(read) => {
                    self.buffer.extend(&buffer[0..read]);
                    Ok(self.buffer.len() == WANTED)
                }
                // Sent some of the data but errored out
                Err((read, e)) => {
                    self.buffer.extend(&buffer[0..read]);
                    Err(e)
                }
            }
        } else {
            Ok(true)
        }
    }
}

没有运行时依赖