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 }
原文地址:https://www.cnblogs.com/xiangtailiang/p/2693950.html