六、赛普拉斯EZ-USB FX3 UART

一、简介

        串口通讯(Serial Communication)是嵌入式中常用的一种串行通讯方式,因为它简单便捷,因此很多嵌入式设备都支持该通讯方式,在调试设备时也经常使用该通讯方式输出调试信息。

        FX3 通用异步收发器,简称UART(Universal Asynchronous Receiver and Transmitter),它是一个串行通信接口,不需要对外输出时钟从而进行全双工通信,数据是以一帧一帧的格式传输,每一帧包括起始位、数据、校验位、停止位。 

图1.0 UART接口 

        FX3支持的波特率范围,从100bps~460800bps,如果启用了流控制,只有激活CTS输入时,FX3的串口才会发送数据。此外,当就绪接收数据时,串口将激活RTS信号。

 图1.1 UART帧格式

二、程序

        串口设备初始化函数

        extern CyU3PReturnStatus_t
CyU3PUartInit (
        void);

        串口配置函数 

extern CyU3PReturnStatus_t
CyU3PUartSetConfig (
        CyU3PUartConfig_t *config,      /**< Pointer to structure containing config information. */
        CyU3PUartIntrCb_t cb            /**< UART callback function to be registered. */
        );

        设置串口发送大小函数

extern CyU3PReturnStatus_t
CyU3PUartTxSetBlockXfer (
        uint32_t txSize                 /**< Desired transfer size. */
        ); 

        设置串口接收大小函数

extern CyU3PReturnStatus_t
CyU3PUartRxSetBlockXfer (
        uint32_t rxSize                 /**< Desired transfer size. */
        );

        DMA通道创建函数

extern CyU3PReturnStatus_t
CyU3PDmaChannelCreate (
        CyU3PDmaChannel *handle,                /**< Pointer to channel structure that should be initialized. */
        CyU3PDmaType_t type,                    /**< Type of DMA channel desired. */
        CyU3PDmaChannelConfig_t *config         /**< Channel configuration parameters. */
        ); 

        设置DMA搬运大小函数

extern CyU3PReturnStatus_t
CyU3PDmaChannelSetXfer (
        CyU3PDmaChannel *handle,                /**< Handle to the channel to be modified. */
        uint32_t count                          /**< The desired transaction size in units corresponding to the
                                                     selected DMA mode. Channel will revert to idle state when the
                                                     specified amount of data has been transferred. Can be set to
                                                     zero to request an infinite data transfer. */
        );

        UART源文件 

#include "cyfx3_uart.h"
#include "cyu3error.h"
#include "cyu3os.h"
#include "cyu3dma.h"

extern  CyU3PEvent  UartEvebtHandler;
#define CYFX3_UART_DMA_BUF_SIZE  16	//16的倍数 (串口接收的数据要已16的倍数对齐,当不满16的倍数时需要补齐)
CyU3PDmaChannel UartDmaHandler;

CyFx3UartRx_t  CyFx3Uart = {0};

//串口DMA回调函数
void CyFx3DmaCallback(
        CyU3PDmaChannel *handle,
        CyU3PDmaCbType_t type,
        CyU3PDmaCBInput_t *input)
{
	uint16_t BuffSize = 0;

	if(type == CY_U3P_DMA_CB_PROD_EVENT)
	{
//		CyU3PDmaChannelCommitBuffer(handle,input->buffer_p.count,0); //回环

		BuffSize = (input->buffer_p.count > CYFX3_UART_BUF_SIZE)
				? CYFX3_UART_BUF_SIZE : input->buffer_p.count;

		strncpy((char*)CyFx3Uart.RxBuffer,(char*)input->buffer_p.buffer,BuffSize);
		CyU3PEventSet(&UartEvebtHandler,UART_RECEIVE_DATA_EVT,CYU3P_EVENT_OR);
	}
}

//DMA串口回环
CyU3PReturnStatus_t CyFx3UartDmaInit(void)
{
	CyU3PReturnStatus_t CyFx3Status = CY_U3P_SUCCESS;

//自动搬运模式
#if DMA_AUOT
	//DMA配置
	CyU3PDmaChannelConfig_t DmaConfig = {
		 .size = CYFX3_UART_DMA_BUF_SIZE,
		 .count = 2,
		 .prodSckId = CY_U3P_LPP_SOCKET_UART_PROD,  //生产者(源)
		 .consSckId = CY_U3P_LPP_SOCKET_UART_CONS,  //消费者(目标)
		 .dmaMode = CY_U3P_DMA_MODE_BYTE,
		 .notification = 0,
		 .cb = NULL,
		 .prodHeader = 0,
		 .prodFooter = 0,
		 .consHeader = 0,
		 .prodAvailCount = 0,
	};
	//自动搬运模式(有数据就搬运)
	CyFx3Status = CyU3PDmaChannelCreate(&UartDmaHandler,CY_U3P_DMA_TYPE_AUTO,&DmaConfig);
    if (CyFx3Status != CY_U3P_SUCCESS)
    {
       return CyFx3Status;
    }

#else
    //DMA配置
	CyU3PDmaChannelConfig_t DmaConfig = {
		 .size = CYFX3_UART_DMA_BUF_SIZE,
		 .count = 2,
		 .prodSckId = CY_U3P_LPP_SOCKET_UART_PROD,
		 .consSckId = CY_U3P_LPP_SOCKET_UART_CONS,
		 .dmaMode = CY_U3P_DMA_MODE_BYTE,
		 .notification = CY_U3P_DMA_CB_PROD_EVENT,
		 .cb = CyFx3DmaCallback,
		 .prodHeader = 0,
		 .prodFooter = 0,
		 .consHeader = 0,
		 .prodAvailCount = 0,
	};
	//手动搬运模式
	CyFx3Status = CyU3PDmaChannelCreate(&UartDmaHandler,CY_U3P_DMA_TYPE_AUTO,&DmaConfig);
	if (CyFx3Status != CY_U3P_SUCCESS)
	{
	   return CyFx3Status;
	}

#endif
    //设置串口发送大小
    CyFx3Status = CyU3PUartTxSetBlockXfer(0xFFFFFFFF);
    if (CyFx3Status != CY_U3P_SUCCESS)
    {
    	return CyFx3Status;
    }

    //设置串口接收大小
    CyFx3Status = CyU3PUartRxSetBlockXfer(0xFFFFFFFF);
    if(CyFx3Status != CY_U3P_SUCCESS)
    {
    	return CyFx3Status;
    }

    //设置搬运大小
    CyFx3Status = CyU3PDmaChannelSetXfer(&UartDmaHandler,0);
    if(CyFx3Status != CY_U3P_SUCCESS)
    {
    	return CyFx3Status;
    }

	return CyFx3Status;
}


CyU3PReturnStatus_t CyFx3UartInit(uint32_t Baudrate)
{
	CyU3PReturnStatus_t CyFx3Status = CY_U3P_SUCCESS;

	//初始化串口设备
	CyFx3Status = CyU3PUartInit();

	if(CyFx3Status != CY_U3P_SUCCESS)
	{
		return CyFx3Status;
	}

	//配置串口(使用DMA搬运数据)
	CyU3PUartConfig_t  UartConfig = {
		.txEnable = CyTrue,
		.rxEnable = CyTrue,
		.flowCtrl = CyFalse,
		.isDma    = CyTrue,
		.baudRate = Baudrate,
		.stopBit = CY_U3P_UART_ONE_STOP_BIT,
		.parity = CY_U3P_UART_NO_PARITY,
	};
	CyFx3Status = CyU3PUartSetConfig(&UartConfig,NULL);
	if(CyFx3Status != CY_U3P_SUCCESS)
	{
		return CyFx3Status;
	}

	//初始化DMA
	CyFx3Status = CyFx3UartDmaInit();
	if(CyFx3Status != CY_U3P_SUCCESS)
	{
		return CyFx3Status;
	}

	return CyFx3Status;
}

        UART头文件

#ifndef CYFX3_UART_H_
#define CYFX3_UART_H_

#include "cyu3uart.h"

#define DMA_AUOT    				0
#define UART_RECEIVE_DATA_EVT  		(0x01 << 0)

#define CYFX3_UART_BUF_SIZE      	256

typedef struct CyFx3UartRx_t
{
	uint16_t RxLen;
	uint8_t  RxBuffer[CYFX3_UART_BUF_SIZE];
}CyFx3UartRx_t;

extern CyFx3UartRx_t  CyFx3Uart;

CyU3PReturnStatus_t CyFx3UartInit(uint32_t Baudrate);
#endif /* CYFX3_UART_H_ */

        主函数

#include "cyfx3_uart.h"
#include "cyu3os.h"
#include "cyu3error.h"

CyU3PThread UartThreadHandler;
CyU3PEvent  UartEvebtHandler;

#define UART_THREAD_PRIORITY		8
#define UART_THREAD_STACK_SIZE		1024

void UartThread(uint32_t arg)
{
	uint32_t  Event;
	CyU3PReturnStatus_t CyFx3Status;

	CyFx3UartInit(115200);

	while(1)
	{
		CyFx3Status = CyU3PEventGet(&UartEvebtHandler,
									UART_RECEIVE_DATA_EVT,
									CYU3P_EVENT_OR_CLEAR,
									&Event,
									CYU3P_WAIT_FOREVER);
		if(Event & UART_RECEIVE_DATA_EVT)
		{
			CyU3PUartTransmitBytes(CyFx3Uart.RxBuffer,CyFx3Uart.RxLen,&CyFx3Status);
			memset(&CyFx3Uart,0,sizeof(CyFx3Uart));
		}
	}
}

void CyFxApplicationDefine(void)
{
	CyU3PEventCreate(&UartEvebtHandler);

	void *UartStackStart = CyU3PMemAlloc(UART_THREAD_STACK_SIZE);
	if(UartStackStart != NULL)
	{
		CyU3PThreadCreate((CyU3PThread*		 ) &UartThreadHandler,
						  (char*			 ) "21:Uart Thread 1",
						  (CyU3PThreadEntry_t) UartThread,
						  (uint32_t          ) 0,
						  (void*			 ) UartStackStart,
						  (uint32_t          ) UART_THREAD_STACK_SIZE,
						  (uint32_t          ) UART_THREAD_PRIORITY,
						  (uint32_t          ) UART_THREAD_PRIORITY,
						  (uint32_t          ) CYU3P_NO_TIME_SLICE,
						  (uint32_t          ) CYU3P_AUTO_START);
	}
}



int main(void)
{
	CyU3PReturnStatus_t CyFx3Status;

	//初始化FX3设备
	CyFx3Status = CyU3PDeviceInit(NULL);
	if(CyFx3Status != CY_U3P_SUCCESS)
	{
		goto HandleFatalError;
	}

	//初始化FX3内核缓存
	CyFx3Status = CyU3PDeviceCacheControl(CyTrue,CyTrue,CyTrue);
	if(CyFx3Status != CY_U3P_SUCCESS)
	{
		goto HandleFatalError;
	}

	//配置IO矩阵(16位数据总线 + UART + GPIO)
	CyU3PIoMatrixConfig_t MatrixcConfig = {
		.isDQ32Bit = CyFalse,
		.s0Mode = CY_U3P_SPORT_INACTIVE,
		.s1Mode = CY_U3P_SPORT_INACTIVE,
		.useUart   = CyTrue,
		.useI2C    = CyFalse,
		.useI2S    = CyFalse,
		.useSpi    = CyFalse,
		.lppMode   = CY_U3P_IO_MATRIX_LPP_UART_ONLY,
		.gpioSimpleEn[0]  = 0,
		.gpioSimpleEn[1]  = 0,
		.gpioComplexEn[0] = 0,
		.gpioComplexEn[1] = 0,
	};
	CyFx3Status = CyU3PDeviceConfigureIOMatrix(&MatrixcConfig);
    if (CyFx3Status != CY_U3P_SUCCESS)
    {
        goto HandleFatalError;
    }

    //初始化RTOS内核
	CyU3PKernelEntry();

HandleFatalError:
	//复位
	CyU3PDeviceReset(CyTrue);
}

三、验证

        验证的工程是采用DMA回环实验,DMA通道的缓冲大小只能是16的倍数,接收的数据不够16的倍数,需要补够。如果想接收不定长数据,需要在串口事件回调函数里面处理,因为我这里串口只是用来调试,所有就没写。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值