CSR8675 使用串口 UART 收发功能

冷暖自知 提交于 2019-12-02 15:16:11

CSR8675 使用串口 UART 收发功能

CSR8675 实现 UART 功能有两种方式,一种是托管连接,另一种是直接连接

托管连接:不直接操作 Stream,通过 VM 层创建 Source 和 Sink 来实现数据传输,由库进行处理,实现比较方便。
直接连接:直接操作 Stream ,源是一个存储区域,通过对内存进行操作实现数据传输,处理数据传输效率更高。

此处暂时先用 托管连接 的方式来介绍,后面有空再更新 直接连接

1、使用 RAW 传输

在工程属性下,将 Transport 属性改为 RAW。
在这里插入图片描述

2、打开调试宏

在 sink_debug.h 中加入调试宏
在这里插入图片描述

3、编辑串口代码,实现 loopback 功能

主要实现4个函数

  1. 消息处理函数
  2. 串口初始化函数
  3. 串口接收函数
  4. 串口发送函数

<sink_uart.h>

#ifndef __UART_H_
#define __UART_H_

void UARTStreamMessageHandler (Task pTask, MessageId pId, Message pMessage);
void uart_data_stream_rx_data(Source src);
void uart_data_stream_tx_data(const uint8 *data, uint16 length);
void uart_data_stream_init(void);

#endif /* __UART_H_ */ 

<sink_uart.c>

#include <stream.h>
#include <sink.h>
#include <source.h>
#include <string.h>
#include <panic.h>
#include <message.h>
#include <app/uart/uart_if.h>
#include <stdio.h>
#include <string.h>
#include "uart.h"
#include "sink_debug.h"

#ifdef DEBUG_UART
#define UART_DEBUG(x) DEBUG(x)
#else
#define UART_DEBUG(x) 
#endif

typedef struct
{
    TaskData task;
    Sink uart_sink;
    Source uart_source;
}UARTStreamTaskData;

UARTStreamTaskData theUARTStreamTask;

void uart_data_stream_init(void)
{
    /* Assign task message handler */
    theUARTStreamTask.task.handler = UARTStreamMessageHandler;
    /* Configure uart settings */
    StreamUartConfigure(VM_UART_RATE_38K4, VM_UART_STOP_ONE, VM_UART_PARITY_NONE);
    /* Get the sink for the uart */
    theUARTStreamTask.uart_sink = StreamUartSink();
    if(theUARTStreamTask.uart_sink != 0)
        PanicNull(theUARTStreamTask.uart_sink);
    /* Get the source for the uart */
    theUARTStreamTask.uart_source = StreamUartSource();
    if(theUARTStreamTask.uart_source != 0)
        PanicNull(theUARTStreamTask.uart_source);
    /* Register uart source with task */
    MessageSinkTask(StreamSinkFromSource(theUARTStreamTask.uart_source),&theUARTStreamTask.task);
}

void uart_data_stream_tx_data(const uint8 *data, uint16 length)
{
    uint16 offset = 0;
    uint8 *dest = NULL;
    /* Claim space in the sink, getting the offset to it */
    offset = SinkClaim(theUARTStreamTask.uart_sink, length);
    if(offset == 0xFFFF) Panic();
    /* Map the sink into memory space */
    dest = SinkMap(theUARTStreamTask.uart_sink);
    PanicNull(dest);
    /* Copy data into the claimed space */
    memcpy(dest+offset, data, length);
    /* Flush the data out to the uart */
    PanicZero(SinkFlush(theUARTStreamTask.uart_sink, length));
}

void uart_data_stream_rx_data(Source src)
{
    uint16 length = 0;
    const uint8 *data = NULL;
    /* Get the number of bytes in the specified source before the next packet boundary */
    if(!(length = SourceBoundary(src)))
        return;
    /* Maps the specified source into the address map */
    data = SourceMap(src);
    PanicNull((void*)data);
    /* Transmit the received data */
    uart_data_stream_tx_data(data, length);
    
    UART_DEBUG(("UART: Rx: length = %d\n",length));
    /* Discards the specified amount of bytes from the front of the specified source */
    SourceDrop(src, length);
}

void UARTStreamMessageHandler (Task pTask, MessageId pId, Message pMessage)
{
    switch (pId)
    {
        case MESSAGE_MORE_DATA:
            uart_data_stream_rx_data(((MessageMoreData *)pMessage)->source);
        break;

        default:
        break;
    }
} 

4、调用函数,实现 loopback

修改PSKey
01EA UART_BITRATE 改为38400
在这里插入图片描述
01C2 UART_CONFIG_USR 改为 0880
在这里插入图片描述
在 main 函数中,MessageLoop()之前,调用串口初始化函数。
在这里插入图片描述
按F5下载到开发板上。
接上串口,打开串口工具,串口号在电脑的设备管理器查看,波特率设置为38400,数据位为8,停止位为1,奇偶校验位为none。
在这里插入图片描述
但是存在一个小问题,发了10个数据,在接收函数中打印一下数据长度,会发现进入了2次接收函数,第一次接收了1个字节,第二次将剩余的字节全部接收。
在这里插入图片描述
操作多几次验证,发现一个规律,就是第一次总是接收1个字节,然后剩下的数据接收的长度会随机改变,原因可能是底层库通过流的方式实现,此处用的是异步串口,没有硬件流控,而且CSR8675本身的串口 buffer 空间不大,才会导致接收的时候将数据截断。
因此,在使用异步串口过程中,需要根据实际情况,对接收的数据增加拼接的处理,同时加入自定义的协议,增加帧头、帧尾、数据长度、数据校验等信息,才能够保证接收到的内容是正确的。
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!