FT93x最多可以支持4路硬件UART(FT930支持4路,FT931、FT932、FT933支持2路),注意由于管脚有共用,如果需要支持全功能串口则不能支持4路或2路。
这里仅考虑只使用RXD和TXD的情况,官方例程是D2XX Example UART Bridge。
USB转UART可以使用VCP驱动(非D2XX驱动),使用普通的串口工具,一个串口打开另外一个USB转串口,接FT930的UART0的RXD和TXD,一个串口工具打开FT930的USB转串口,测试结果如下:
可以修改程序将uart_configuration中UART0的波特率改为1M,同样测试会发现丢数据,如下图:
1. 目前的例程中FT930的USB转串口波特率设置并不起作用,所以左边的设定为19200或者任意值都可以正常工作,毕竟走的是USB协议,而例程中并没有通道可以通过工具设置FT930的UART波特率
2. FT930串口打印数据应该没有问题,但是从PC发送数据出去会没有打印,而从UART发送数据到PC会掉数据
基于D2XX Example 1参考UART Example 4的例程(使用UART的FIFO接收数据)修改为USB转串口程序:
1. 初始化UART0的IO口,以UART0为例
#if defined(__FT930__)
gpio_function(23, pad_uart0_txd); /* UART0 TXD */
gpio_function(22, pad_uart0_rxd); /* UART0 RXD */
#else
gpio_function(48, pad_uart0_txd); /* UART0 TXD */
gpio_function(49, pad_uart0_rxd); /* UART0 RXD */
#endif
2. 打开UART,其中参数idx表示第几个UART
ft900_uart_regs_t* const uart[] =
{
UART0, UART1,
#if defined(__FT930__)
UART2, UART3,
#endif
};
uint8_t const sys_device_uart[] =
{
sys_device_uart0, sys_device_uart1,
#if defined(__FT930__)
sys_device_uart2, sys_device_uart3
#endif
};
sys_enable(sys_device_uart[idx]);
// Open the UART using the coding required.
uart_open(uart[idx], /* Device */
1, /* Prescaler = 1 */
UART_DIVIDER_1000000_BAUD, /* Divider = 1302 */
uart_data_bits_8, /* No. buffer Bits */
uart_parity_none, /* Parity */
uart_stop_bits_1); /* No. Stop Bits */
波特率设置为1M,可以根据实际需求修改。
3. 设置UART的模式和trigger方式
/*Enable mode*/
uart_mode(uart[idx], UART_MODE);
/*Set trigger levels and flow controls*/
uart_set_trigger_level(uart[idx], UART_MODE, RX_TRIGGER_LEVEL, TX_TRIGGER_LEVEL, FCH, FCL);
/*Enable flow control*/
//uart_set_flow_control(UART0, uart_flow_rts_cts, XON, XOFF);
其中各个参数参考例程中的定义
#define UART_FIFO_SIZE 128
#define UART_BUF_SIZE (UART_FIFO_SIZE * 2)
#define UART_MODE uart_mode_16950
#define RX_LEVEL (127)
#define TX_LEVEL (0)
/*Receiver interrupt trigger level*/
#define RX_TRIGGER_LEVEL RX_LEVEL
/*Transmitter interrupt trigger level*/
#define TX_TRIGGER_LEVEL TX_LEVEL
#define FCH 112
#define FCL 64
/*XON and XOFF bytes for flow control*/
#define XON 0x11
#define XOFF 0x13
4. 初始化中断,中断函数采用每个UART一个中断函数,减少中断函数处理的时间,并且只处理接收中断,关掉发送中断。
/* Attach the interrupt so it can be called... */
interrupt_attach(interrupt_uart[idx], (uint8_t) interrupt_uart[idx], uart_ISR[idx]);
/* Enable the UART to fire interrupts when receiving data... */
uart_enable_interrupt(uart[idx], uart_interrupt_rx);
/* Enable the UART to fire interrupts when transmitting data... */
uart_disable_interrupt(uart[idx], uart_interrupt_tx);
/* Enable interrupts to be fired... */
uart_enable_interrupts_globally(uart[idx]);
参数:
void(*uart_ISR[])(void) =
{
uart0ISR, uart1ISR,
#if defined(__FT930__)
uart2ISR, uart3ISR
#endif
};
uint8_t const interrupt_uart[] =
{
interrupt_uart0, interrupt_uart1,
#if defined(__FT930__)
interrupt_uart2, interrupt_uart3
#endif
};
中断函数:
void uart0ISR(void)
{
uartISR(0);
}
void uart1ISR(void)
{
uartISR(1);
}
void uart2ISR(void)
{
uartISR(2);
}
void uart3ISR(void)
{
uartISR(3);
}
5. 中断处理函数uartISR,采用Ring Buffer的方式接收数据,在主循环中处理该数据。
//RX buffer
#define UART_BUF_SIZE (UART_FIFO_SIZE * 2)
uint8_t uartRxBuf[USB2UART_NUM][UART_BUF_SIZE] = {0};
volatile uint16_t uartRxWrIdx[USB2UART_NUM] = {0};
volatile uint16_t uartRxRdIdx[USB2UART_NUM] = {0};
void uartISR(uint8_t idx)
{
uint8_t count = 0, i = 0;
uint8_t buf[UART_FIFO_SIZE];
/* Receive interrupt... */
if (uart_is_interrupted(uart[idx], uart_interrupt_rx)
|| uart_is_interrupted(uart[idx], uart_interrupt_rx_time_out))
{
count = uart_get_rx_fifo_level(uart[idx]);
__asm__("streamin.b %0,%1,%2"::"r"(&buf[0]), "r"(&(uart[idx]->RHR_THR_DLL)), "r"(count));
for(i = 0; i < count; i++)
{
uartRxBuf[idx][uartRxWrIdx[idx]++] = buf[i];
uartRxWrIdx[idx] %= UART_BUF_SIZE;
}
}
}
6. 主循环中处理函数,从USB读到数据直接通过uart_write把数据发送到UART上,然后将接收Ring buffer中的数据发送给USB。
void usb2uartHandle(uint8_t idx)
{
int32_t count = 0;
uint8_t buf[USB2UART_BUF_MAX];
count = D2XX_Read(idx + 1, buf, USB2UART_BUF_MAX);
if(count > 0)
{
uint16_t i;
for(i = 0; i < count; i++)
{
uart_write(uart[idx], buf[i]);
}
}
if(uartRxRdIdx[idx] != uartRxWrIdx[idx])
{
uint16_t i;
if(uartRxWrIdx[idx] > uartRxRdIdx[idx])
{
count = uartRxWrIdx[idx] - uartRxRdIdx[idx];
}
else
{
count = UART_BUF_SIZE + uartRxWrIdx[idx] - uartRxRdIdx[idx];
}
for(i = 0; i < count; i++)
{
buf[i] = uartRxBuf[idx][uartRxRdIdx[idx]++];
uartRxRdIdx[idx] %= UART_BUF_SIZE;
}
count = D2XX_Write(idx + 1, buf, count);
}
}
7.测试方式: