NXP JN5169使用UART发送数据


一、UART介绍

1、UART介绍

        JN5169具有两个通用异步接收器/发送器(UART)串行通信接口。 它们提供与以FIFO模式运行的行业标准16550A器件相似的操作功能。这些接口对传入的串行数据执行串行到并行转换,并对从CPU到外部设备的传出数据执行并行到串行转换。 在两个方向上,可配置的FIFO缓冲区(默认深度为16字节)使CPU可以在每个事务中读写多个字符。 这意味着,CPU不再需要逐个字符地处理数据,并且会增加相关的处理器开销。 UART具有以下功能:

  • 遵守行业标准NS16450和NS16550A。
  • 可配置的发送和接收FIFO缓冲区(每个缓冲区的默认深度为16字节),可直接访问每个缓冲区的填充级别。向/从串行数据中添加/删除标准的开始,停止和奇偶校验位。
  • 独立控制的发送,接收,状态和数据发送中断。
  • UART0上的可选调制解调器流控制信号CTS和RTS。
  • 完全可编程的数据格式:波特率,开始,停止和奇偶校验设置。
  • 错误的起始位检测,奇偶校验,成帧和FIFO超限错误检测和中断指示。
  • 内部诊断功能:用于通信链路故障隔离的环回控制。
  • 通过软件或通过硬件自动控制流量。

注:这里描述的 UART 操作假设外设时钟运行在 16MHz,时钟来自一个外部晶体振荡器。不建议用户在任何其他时钟下运行 UART。

2、UART系统图

在这里插入图片描述

3、UART引脚

        可以将UART0和UART1都配置为使用标准或备用DIO线,如表8所示。此外,可以将UART0配置为以2线模式使用(其中未配置CTS0和RTS0),并且可以配置UART1 在1线模式下(未配置RXD1)。 这些释放的DIO引脚随后可用于其他目的。
        可以使用函数vAHI_UartSetLocation()将UART0信号从DIO4-7移至DIO12-15。 可以使用相同的功能将UART1信号分别从DIO14和DIO15移至DIO11和DIO9。 如果需要此功能,则必须在启用UART之前调用它。

在这里插入图片描述
备注:在自动流控制阈值设置为15的情况下,当接收FIFO即将满时,UART模块中的硬件流控制将取消RTS。 在某些情况下,已经观察到,正在传输数据的远程设备不能对断言的CTS做出足够迅速的响应,而是继续传输数据。 在这些情况下,数据将在接收FIFO溢出中丢失。


UART 使用以下信号与一个外部设备相连:

  • 发送数据(TxD)输出 —— 连接到外部设备的 RxD
  • 接收数据(RxD)输入 —— 连接到外部设备的 TxD
  • 请求发送(RTS)输出 —— 连接到外部设备的 CTS
  • 清除发送(CTS)输入 —— 连接到外部设备的 RTS

如果 UART 只使用信号 RxD 和 TxD,就表明 UART 工作在 2 线模式。如果 UART 使用上面全部 4 个信号,就表明 UART 工作在 4 线模式并执行流控制。 在 JN5169 器件上:

  • UART0 可以工作在 4 线模式(默认情况)或 2 线模式;
  • UART1 可以工作在 2 线模式(默认情况)或 1 线(仅发送)模式;

4、UART操作

        UART 的发送和接收通路每个都有一个 FIFO 缓冲区,它允许和外部设备执行多字节的串行传输:

  • TxD 引脚连接到发送 FIFO;
  • RxD 引脚连接到接收 FIFO;

        FIFO 包含在 RAM 中,由应用来定义。每个 FIFO 的大小可以从 16 个字节直至 2047 个字节。
        在本地设备上,CPU 可以一次性向 FIFO 写入/读出一个字节和一个数据块。读/写通路互相独立,因此发送和接收单独出现。由一个 DMA(直接存储器存取)引擎来处理 FIFO 和 TxD/RxD之间的数据移动,不需要 CPU 的参与。

在这里插入图片描述

5、2线模式

        在 2 线模式下,UART 只使用信号线 TxD 和 RxD。只要发送设备方便(例如,当发送 FIFO包含一些数据时),可以不做任何通知就发送数据。数据还也可以根据发送设备的方便不做任何通知就接收。这可能会产生问题和导致数据丢失,例如,接收设备可能在接收 FIFO 中没有足够的空间来接收发送过来的数据。

6、4线模式(带流控制)(仅适用UART0)

        在 4 线模式下,UART0 使用信号线 TxD、RxD、RTS 和 CTS,允许执行流控制,保证发送的数据总是能接收到。流控制的一般原理在下面描述。
        RTS 和 CTS 线是标志,用来指示数据在设备之间安全传输。一个设备上的 RTS 线连接到另一个设备的 CTS 线。
        目标设备命令源设备应该何时给它发送数据,如下所述:

  • 当目标设备准备好接收数据时,它激活 RTS 线来请求源设备发送数据。这种情况可能是目标设备的接收 FIFO填充水平(fill-level)降至低于一个预定义好的水平,并且 FIFO能够接收更多的数据;
  • 源设备将目标设备 RTS 线的激活看成是自己 CTS 线的激活,然后将数据从发送 FIFO中发送出去。

        流控制操作如下面所示。
在这里插入图片描述


7、1线模式(仅适用UART1)

        在 1 线模式下,UART1 根据发送设备方便,在不通知的情况下使用 TxD 线发送数据。该模式下不接收数据,也不使用 RxD 线(因此,相关的 DIO 引脚可以用作其他用途)




二、UART集成外设API函数介绍

NXP JN5169 UART集成外设API函数




三、实现代码

1、UART0 2线模式发送数据

#define UART                    E_AHI_UART_0

#define TRUE            (1)   /* page 207 K+R 2nd Edition */
#define FALSE           (0)

/* Value enumerations: UART */
#define E_AHI_UART_RATE_4800            (0)
#define E_AHI_UART_RATE_9600            (1)
#define E_AHI_UART_RATE_19200           (2)
#define E_AHI_UART_RATE_38400           (3)
#define E_AHI_UART_RATE_76800           (4)
#define E_AHI_UART_RATE_115200          (5)
#define E_AHI_UART_WORD_LEN_5           (0)
#define E_AHI_UART_WORD_LEN_6           (1)
#define E_AHI_UART_WORD_LEN_7           (2)
#define E_AHI_UART_WORD_LEN_8           (3)
#define E_AHI_UART_FIFO_LEVEL_1         (0)
#define E_AHI_UART_FIFO_LEVEL_4         (1)
#define E_AHI_UART_FIFO_LEVEL_8         (2)
#define E_AHI_UART_FIFO_LEVEL_14        (3)
#define E_AHI_UART_LS_ERROR             (0x80)
#define E_AHI_UART_LS_TEMT              (0x40)
#define E_AHI_UART_LS_THRE              (0x20)
#define E_AHI_UART_LS_BI                (0x10)
#define E_AHI_UART_LS_FE                (0x08)
#define E_AHI_UART_LS_PE                (0x04)
#define E_AHI_UART_LS_OE                (0x02)
#define E_AHI_UART_LS_DR                (0x01)
#define E_AHI_UART_MS_CTS               (0x10)
#define E_AHI_UART_MS_DCTS              (0x01)
#define E_AHI_UART_INT_MODEM            (0)
#define E_AHI_UART_INT_TX               (1)
#define E_AHI_UART_INT_RXDATA           (2)
#define E_AHI_UART_INT_RXLINE           (3)
#define E_AHI_UART_INT_TIMEOUT          (6)
#define E_AHI_UART_TX_RESET             (TRUE)
#define E_AHI_UART_RX_RESET             (TRUE)
#define E_AHI_UART_TX_ENABLE            (FALSE)
#define E_AHI_UART_RX_ENABLE            (FALSE)
#define E_AHI_UART_EVEN_PARITY          (TRUE)
#define E_AHI_UART_ODD_PARITY           (FALSE)
#define E_AHI_UART_PARITY_ENABLE        (TRUE)
#define E_AHI_UART_PARITY_DISABLE       (FALSE)
#define E_AHI_UART_1_STOP_BIT           (TRUE)
#define E_AHI_UART_2_STOP_BITS          (FALSE)
#define E_AHI_UART_RTS_HIGH             (TRUE)
#define E_AHI_UART_RTS_LOW              (FALSE)
#define E_AHI_UART_FIFO_ARTS_LEVEL_8    (0)
#define E_AHI_UART_FIFO_ARTS_LEVEL_11   (1)
#define E_AHI_UART_FIFO_ARTS_LEVEL_13   (2)
#define E_AHI_UART_FIFO_ARTS_LEVEL_15   (3)

/*发送单个字符*/
PRIVATE void vPutChar(unsigned char c)
{
    
    
    while (!(u8AHI_UartReadLineStatus(UART) & E_AHI_UART_LS_THRE));    /*发送FIFO为空*/
    vAHI_UartWriteData(UART, c);   /*写入要发送的字符*/
    /*
       发送移位寄存器为空或者发送FIFO为空,即等待发送完毕
       E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT = 0x20 | 0x40 = 0x60
    */
    while ((u8AHI_UartReadLineStatus(UART) & (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT))
            != (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT)); 
}
/*发送字符串*/
PRIVATE void vPutStrs(unsigned char *str)
{
    
    
    while(*str){
    
    
    	vPutChar(*str++);
    }
}
/*初始化串口*/
PRIVATE void vUartInit(void)
{
    
    
#if (UART == E_AHI_UART_0)
    vAHI_UartSetRTSCTS(UART, FALSE); /* UART0 2线模式。Disable use of CTS/RTS       */
#endif
    vAHI_UartEnable(UART);
    //复位指定UART的发送和接收FIFO,并将FIFO触发级别设置为单字节触发
    vAHI_UartReset(UART,
                     TRUE, /* 复位收发FIFO*/
                     TRUE);
    vAHI_UartSetBaudRate(UART, E_AHI_UART_RATE_115200); /* 设置波特率*/
}
/*主函数*/
PUBLIC void AppColdStart (void)
{
    
    
	vAHI_WatchdogStop();
	(void)u32AHI_Init();

    vUartInit();

    vPutStrs((uint8*)"System Ready!\n");

    while (1) {
    
    
    	vPutStrs((uint8*)"System Ready!\n");
    }
}
/*热启动函数*/
PUBLIC void AppWarmStart (void)
{
    
    
    AppColdStart();
}

2、UART0 2线模式发送/接收数据

#define UART                    E_AHI_UART_0

#define RECV_MAX_LEN	30			//最长接收字符长度
uint8	recv_buf[RECV_MAX_LEN];		//接收缓冲区
uint8	recv_len;					//已接收的字符长度

PRIVATE void vAHI_DelayXms(uint32 n)
{
    
    
	uint32 temp;
	vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);               /* 关闭滴答定时器                */
	vAHI_TickTimerWrite(0);                                          /* 设置起始值                          */
	vAHI_TickTimerInterval(16000 * n);                              /* 设置参照值                          */
	vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_STOP);               /* 到达参考值停止计数                    */
	vAHI_TickTimerIntEnable(FALSE);                                   /* 关闭中断  */

	do{
    
    
		temp = u32AHI_TickTimerRead();
	}while(temp < 16000 * n);//向上计数
	vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);               /* 关闭滴答定时器                */
}

/*发送单个字符*/
PRIVATE void vPutChar(unsigned char c)
{
    
    
    while (!(u8AHI_UartReadLineStatus(UART) & E_AHI_UART_LS_THRE));    /*发送FIFO为空*/
    vAHI_UartWriteData(UART, c);   /*写入要发送的字符*/
    /*
       发送移位寄存器为空或者发送FIFO为空,即等待发送完毕
       E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT = 0x20 | 0x40 = 0x60
    */
    while ((u8AHI_UartReadLineStatus(UART) & (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT))
            != (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT));
}
/*发送字符串*/
PRIVATE void vPutStrs(unsigned char *str)
{
    
    
    while(*str){
    
    
    	vPutChar(*str++);
    }
}
/*UART0中断回调函数*/
PRIVATE void vCbUart0 (uint32 u32Device, uint32 u32ItemBitmap)
{
    
    
	uint8 recv;
	if(E_AHI_DEVICE_UART0 == u32Device){
    
    		//UART0中断
		if(E_AHI_UART_INT_RXDATA == u32ItemBitmap){
    
    		//接收数据可用中断
			recv = u8AHI_UartReadData(UART);
			if(recv != 0x0d && (recv_len < RECV_MAX_LEN - 2)){
    
    	//回车0x0d,换行0x0a
				recv_buf[recv_len++] = recv;
			}
			else{
    
    
				recv_buf[recv_len++] = '\0';
				vPutStrs(recv_buf);
				recv_len = 0;
			}
		}
	}
}
/*初始化串口*/
PRIVATE void vUartInit(void)
{
    
    
#if (UART == E_AHI_UART_0)
    vAHI_UartSetRTSCTS(UART, FALSE); /* UART0 2线模式。Disable use of CTS/RTS       */
#endif
    vAHI_UartEnable(UART);
    //复位指定UART的发送和接收FIFO,并将FIFO触发级别设置为单字节触发
    vAHI_UartReset(UART,
                     TRUE, /* 复位收发FIFO*/
                     TRUE);
    vAHI_UartSetBaudRate(UART, E_AHI_UART_RATE_115200); /* 设置波特率*/
    /*启用接收数据可用中断,将接收FIFO触发级别设置为单字节触发。*/
    vAHI_UartSetInterrupt(UART, FALSE, FALSE, FALSE, TRUE, E_AHI_UART_FIFO_LEVEL_1);
    /*UART0中断回调函数*/
    vAHI_Uart0RegisterCallback(vCbUart0);
}


PUBLIC void AppColdStart (void)
{
    
    
	vAHI_WatchdogStop();
	(void)u32AHI_Init();

	recv_len = 0;

    vUartInit();
    vAHI_DelayXms(100);
    vPutStrs((uint8*)"System Ready!\n");

    while (1) {
    
    
    	vAHI_DelayXms(500);
    	vPutStrs((uint8*)"System Ready!\n");
    }
}

PUBLIC void AppWarmStart (void)
{
    
    
    AppColdStart();
}

3、UART1 1线模式发送数据

#define UART                    E_AHI_UART_1

/*发送单个字符*/
PRIVATE void vPutChar(unsigned char c)
{
    
    
    while (!(u8AHI_UartReadLineStatus(UART) & E_AHI_UART_LS_THRE));    /*发送FIFO为空*/
    vAHI_UartWriteData(UART, c);   /*写入要发送的字符*/
    /*
       发送移位寄存器为空或者发送FIFO为空,即等待发送完毕
       E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT = 0x20 | 0x40 = 0x60
    */
    while ((u8AHI_UartReadLineStatus(UART) & (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT))
            != (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT)); 
}
/*发送字符串*/
PRIVATE void vPutStrs(unsigned char *str)
{
    
    
    while(*str){
    
    
    	vPutChar(*str++);
    }
}
/*初始化串口*/
PRIVATE void vUartInit(void)
{
    
    
#if (UART == E_AHI_UART_1)
    vAHI_UartTxOnly(UART, TRUE); /* UART1 1线模式*/
#endif
    vAHI_UartEnable(UART);
    //复位指定UART的发送和接收FIFO,并将FIFO触发级别设置为单字节触发
    vAHI_UartReset(UART,
                     TRUE, /* 复位收发FIFO*/
                     TRUE);
    vAHI_UartSetBaudRate(UART, E_AHI_UART_RATE_115200); /* 设置波特率*/
}
/*主函数*/
PUBLIC void AppColdStart (void)
{
    
    
	vAHI_WatchdogStop();
	(void)u32AHI_Init();

    vUartInit();

    vPutStrs((uint8*)"System Ready!\n");

    while (1) {
    
    
    	vPutStrs((uint8*)"System Ready!\n");
    }
}
/*热启动函数*/
PUBLIC void AppWarmStart (void)
{
    
    
    AppColdStart();
}

4、UART1 2线模式发送/接收数据

#define UART                    E_AHI_UART_1

#define RECV_MAX_LEN	30			//最长接收字符长度
uint8	recv_buf[RECV_MAX_LEN];		//接收缓冲区
uint8	recv_len;					//已接收的字符长度

PRIVATE void vAHI_DelayXms(uint32 n)
{
    
    
	uint32 temp;
	vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);               /* 关闭滴答定时器                */
	vAHI_TickTimerWrite(0);                                          /* 设置起始值                          */
	vAHI_TickTimerInterval(16000 * n);                              /* 设置参照值                          */
	vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_STOP);               /* 到达参考值停止计数                    */
	vAHI_TickTimerIntEnable(FALSE);                                   /* 关闭中断  */

	do{
    
    
		temp = u32AHI_TickTimerRead();
	}while(temp < 16000 * n);//向上计数
	vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);               /* 关闭滴答定时器                */
}

/*发送单个字符*/
PRIVATE void vPutChar(unsigned char c)
{
    
    
    while (!(u8AHI_UartReadLineStatus(UART) & E_AHI_UART_LS_THRE));    /*发送FIFO为空*/
    vAHI_UartWriteData(UART, c);   /*写入要发送的字符*/
    /*
       发送移位寄存器为空或者发送FIFO为空,即等待发送完毕
       E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT = 0x20 | 0x40 = 0x60
    */
    while ((u8AHI_UartReadLineStatus(UART) & (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT))
            != (E_AHI_UART_LS_THRE | E_AHI_UART_LS_TEMT));
}
/*发送字符串*/
PRIVATE void vPutStrs(unsigned char *str)
{
    
    
    while(*str){
    
    
    	vPutChar(*str++);
    }
}
/*UART1中断回调函数*/
PRIVATE void vCbUart1 (uint32 u32Device, uint32 u32ItemBitmap)
{
    
    
	uint8 recv;
	if(E_AHI_DEVICE_UART1== u32Device){
    
    		//UART1中断
		if(E_AHI_UART_INT_RXDATA == u32ItemBitmap){
    
    		//接收数据可用中断
			recv = u8AHI_UartReadData(UART);
			if(recv != 0x0d && (recv_len < RECV_MAX_LEN - 2)){
    
    	//回车0x0d,换行0x0a
				recv_buf[recv_len++] = recv;
			}
			else{
    
    
				recv_buf[recv_len++] = '\0';
				vPutStrs(recv_buf);
				recv_len = 0;
			}
		}
	}
}
/*初始化串口*/
PRIVATE void vUartInit(void)
{
    
    
    vAHI_UartEnable(UART);
    //复位指定UART的发送和接收FIFO,并将FIFO触发级别设置为单字节触发
    vAHI_UartReset(UART,
                     TRUE, /* 复位收发FIFO*/
                     TRUE);
    vAHI_UartSetBaudRate(UART, E_AHI_UART_RATE_115200); /* 设置波特率*/
    /*启用接收数据可用中断,将接收FIFO触发级别设置为单字节触发。*/
    vAHI_UartSetInterrupt(UART, FALSE, FALSE, FALSE, TRUE, E_AHI_UART_FIFO_LEVEL_1);
    /*UART1中断回调函数*/
    vAHI_Uart1RegisterCallback(vCbUart1);
}


PUBLIC void AppColdStart (void)
{
    
    
	vAHI_WatchdogStop();
	(void)u32AHI_Init();

	recv_len = 0;

    vUartInit();
    vAHI_DelayXms(100);
    vPutStrs((uint8*)"System Ready!\n");

    while (1) {
    
    
    	vAHI_DelayXms(500);
    	vPutStrs((uint8*)"System Ready!\n");
    }
}

PUBLIC void AppWarmStart (void)
{
    
    
    AppColdStart();
}

猜你喜欢

转载自blog.csdn.net/baidu_25117757/article/details/109349432