AT91SAM7SE应用 - UART 数据块的发送方式
最近一直在调试代码,在短短的时间内产生了大量的代码,还没有来得及总结。
现在就总结一下用 UART 发送数据块的方式,为什么采用数据块发送呢?
一、块数据发送的方式可以提高发送效率;
二、在需要发送一个数据帧的格式时,数据块的发送更实用。
这里采用的是中断的方式,因此,缓冲区是必须的,笔者为这个通信方式设计了一个环形缓冲区,
可以检测空信号,但不检测满信号。
缓冲区的代码如下:
View Code
1 #define BUFF_SIZE 16000 2 3 typedef struct 4 { 5 char data[BUFF_SIZE]; 6 volatile int read_pt, write_pt; 7 } FIFO; 8 9 10 //求队列的长度 11 int fifo_len(FIFO *p_fifo) 12 { 13 return p_fifo->write_pt - p_fifo->read_pt; 14 } 15 16 void fifo_init(FIFO *p_fifo) 17 { 18 p_fifo->read_pt = 0; 19 p_fifo->write_pt = 0; 20 memset(p_fifo->data, 0, BUFF_SIZE); 21 } 22 23 //判断队列是否为空 24 int fifo_empty(FIFO *p_fifo) 25 { 26 return (p_fifo->write_pt == p_fifo->read_pt); 27 } 28 29 //元素入队列 30 int fifo_push(FIFO *p_fifo, char e) 31 { 32 p_fifo->data[p_fifo->write_pt] = e; 33 p_fifo->write_pt++; 34 if (p_fifo->write_pt == BUFF_SIZE) 35 { 36 p_fifo->write_pt = 0; 37 } 38 return 1; 39 }
UART初始化程序:
View Code
1 /****************************************************************************** 2 * Function Name : Usart_init 3 * Object : USART initialization 4 * Input Parameters : none 5 * Output Parameters : TRUE 6 ******************************************************************************/ 7 void uart_init(void) 8 //* Begin 9 { 10 11 COM0 = AT91C_BASE_US0; 12 13 //* Define RXD and TXD as peripheral 14 //AT91F_US0_CfgPIO(); 15 AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, // PIO controller base address 16 ((unsigned int)AT91C_PA5_RXD0) | ((unsigned int)AT91C_PA6_TXD0) | ((unsigned int)AT91C_PA7_RTS0) | ((unsigned int)AT91C_PA8_CTS0), 0); 17 18 // First, enable the clock of the PIOB 19 AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_US0); 20 21 // Usart Configure 22 //AT91F_US_Configure(COM0, MCK, AT91C_US_ASYNC_MODE, USART_BAUD_RATE, 0); 23 AT91F_US_Configure(COM0, MCK, AT91C_US_ASYNC_MODE, 115200, 0); 24 25 // Enable usart 26 COM0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; 27 28 //* Set the PDC Interrupt mode 29 BlockMode = false; 30 31 AT91F_US_EnableIt(COM0, AT91C_US_RXRDY); 32 33 //* open Usart 1 interrupt 34 AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_US0, USART_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, Usart_c_irq_handler); 35 AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_US0); 36 37 fifo_init(p_uart_buffer); 38 39 }
例化一个串口缓冲区,全局变量:
FIFO uart_buffer; FIFO *p_uart_buffer = &uart_buffer;
数据块发送程序:
View Code
1 static int first_send_flag = 0; 2 void uart_send_buffer(FIFO *p, char *data, int n) 3 { 4 int i; 5 BlockSize = n; 6 7 for (i = 0; i < n; i++) 8 { 9 fifo_push(p, data[i]); 10 } 11 if (first_send_flag == 0) 12 { 13 first_send_flag = 1; 14 15 //* clean all param 16 AT91F_US_DisableIt(COM0, AT91C_US_ENDTX | AT91C_US_TXBUFE); 17 COM0->US_TCR = 0; 18 COM0->US_TNCR = 0; 19 BlockMode = (char)true; 20 21 //* Start PDC 22 //* ---- Set the first Block 23 COM0->US_TPR = (unsigned int) &(p->data[p->read_pt]); 24 COM0->US_TCR = n; 25 p_uart_buffer->read_pt = (p_uart_buffer->read_pt + BlockSize) % BUFF_SIZE; 26 AT91F_US_EnableIt(COM0, AT91C_US_TXBUFE); 27 28 } 29 else 30 { 31 AT91F_US_EnableIt(COM0, AT91C_US_TXBUFE); 32 } 33 34 }
当发送完一个数据块(8字节)后,会进入中断,中断处理函数如下:
View Code
1 __irq void Usart_c_irq_handler(void) 2 { 3 unsigned int status; 4 char rx_dat; 5 //* get Usart status register 6 status = COM0->US_CSR; 7 // check if interrupt is present and available 8 if ((status &AT91C_US_TXBUFE) &(COM0->US_IMR &AT91C_US_TXBUFE)) 9 { 10 //AT91F_US_DisableIt(COM0, AT91C_US_TXBUFE); 11 //p_uart_buffer->read_pt = (p_uart_buffer->read_pt + BlockSize ) % BUFF_SIZE; 12 if (p_uart_buffer->read_pt == p_uart_buffer->write_pt) 13 { 14 AT91F_US_DisableIt(COM0, AT91C_US_TXBUFE); 15 send_buffer_done = 1; 16 } 17 else 18 { 19 COM0->US_TPR = (unsigned int) &(p_uart_buffer->data[p_uart_buffer->read_pt]); 20 COM0->US_TCR = BlockSize; 21 p_uart_buffer->read_pt = (p_uart_buffer->read_pt + BlockSize) % BUFF_SIZE; 22 AT91F_US_EnableIt(COM0, AT91C_US_TXBUFE); 23 } 24 } 25 26 //* Reset the satus bit 27 COM0->US_CR = AT91C_US_RSTSTA; 28 AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC); 29 }