NXP JN5169使用UART发送数据
- 一、UART介绍
-
- 1、UART介绍
- 2、UART系统图
- 3、UART引脚
- 4、UART操作
- 5、2线模式
- 6、4线模式(带流控制)(仅适用UART0)
- 7、1线模式(仅适用UART1)
- 二、UART集成外设API函数介绍
- 三、实现代码
-
- 1、UART0 2线模式发送数据
- 2、UART0 2线模式发送/接收数据
- 3、UART1 1线模式发送数据
- 4、UART1 2线模式发送/接收数据
一、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)
#define FALSE (0)
#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));
vAHI_UartWriteData(UART, c);
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);
#endif
vAHI_UartEnable(UART);
//复位指定UART的发送和接收FIFO,并将FIFO触发级别设置为单字节触发
vAHI_UartReset(UART,
TRUE,
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));
vAHI_UartWriteData(UART, c);
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 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);
#endif
vAHI_UartEnable(UART);
//复位指定UART的发送和接收FIFO,并将FIFO触发级别设置为单字节触发
vAHI_UartReset(UART,
TRUE,
TRUE);
vAHI_UartSetBaudRate(UART, E_AHI_UART_RATE_115200);
vAHI_UartSetInterrupt(UART, FALSE, FALSE, FALSE, TRUE, E_AHI_UART_FIFO_LEVEL_1);
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));
vAHI_UartWriteData(UART, c);
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);
#endif
vAHI_UartEnable(UART);
//复位指定UART的发送和接收FIFO,并将FIFO触发级别设置为单字节触发
vAHI_UartReset(UART,
TRUE,
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));
vAHI_UartWriteData(UART, c);
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 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,
TRUE);
vAHI_UartSetBaudRate(UART, E_AHI_UART_RATE_115200);
vAHI_UartSetInterrupt(UART, FALSE, FALSE, FALSE, TRUE, E_AHI_UART_FIFO_LEVEL_1);
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();
}