要缓冲将在其他上下文中(在这种情况下,在ISR和“普通”线程之间)异步读取的数据,应使用FIFO或环形缓冲区,以便ISR可以继续写入缓冲区而普通线程正在读取和处理它。例如,给定:
#include <stdint.h>
#include <stdatomic.h>
#define BUFFLEN ((uint8_t)128u) // Must be a power of 2
#define BUFFMODMASK ((uint8_t)(BUFFLEN - 1)) // modulo BUFFLEN mask
typedef volatile struct
{
uint8_t write_idx ;
uint8_t read_idx ;
atomic_int count ;
uint8_t data[BUFFLEN] ;
} tRingBuf ;
void ringBufPut( tRingBuf* buffer,uint8_t ch )
{
if( buffer->count < BUFFLEN )
{
buffer->data[buffer->write_idx++] = ch ;
buffer->write_idx &= BUFFMODMASK ;
buffer->count++ ;
}
}
int ringBufGet( tRingBuf* buffer )
{
int ch = -1 ;
if( buffer->count > 0 )
{
ch = (int)buffer->data[buffer->read_idx++] ;
buffer->read_idx &= BUFFMODMASK ;
buffer->count-- ;
}
return ch ;
}
tRingBuf UART1RxBuffer = { 0,{0} } ;
然后,您的ISR将数据放入缓冲区中:
ringBufPut( &UART1RxBuffer,LPC_UART1->RBR ) ;
然后您的主线程可以读取数据,从而:
for( int i = 0; i < size_int; i++ )
{
int ch = ringBufGet( &UART1RxBuffer ) ;
if( ch > 0 )
{
uint8_t byte = (uint8_t)ch ;
// ... do something with the data here
// For example...
UART2_Printf( "%02X",(unsigned)byte ) ;
}
}
对于所有UART,以相同的方式(反转放置/获取)实现UART Tx可能会做得很好-您的ISR当前仅处理Rx。完全缓冲的I / O将带来更多确定性的时序。
,
感谢您的回应。几乎非常接近我需要做的事情。
我尝试使用环形缓冲区来工作,并且几乎做到了。
但是,当我尝试读取大文件(48kB) Update.BIN 文件时,
它正在读取完整的文件,但是当我将此读取的文件与实际文件进行比较时,会发现数据丢失和数据不匹配
(正在附加实际文件以及我随即阅读的内容)。
我通过UART环形缓冲区读取的文件:
https://www.dropbox.com/s/93k3i3r598jkxro/My_Read_file.log?dl=0
我尝试读取的实际文件:https://www.dropbox.com/s/bmh5wyurrdvvtqx/Update.BIN.txt?dl=0
我的环形缓冲区代码如下:
#define UART_RING_BUFSIZE 256
#define __BUF_MASK (UART_RING_BUFSIZE-1)
#define __BUF_IS_FULL(head,tail) ((tail&__BUF_MASK)==((head+1)&__BUF_MASK))
#define __BUF_WILL_FULL(head,tail) ((tail&__BUF_MASK)==((head+2)&__BUF_MASK))
#define __BUF_IS_EMPTY(head,tail) ((head&__BUF_MASK)==(tail&__BUF_MASK))
#define __BUF_RESET(bufidx) (bufidx=0)
#define __BUF_INCR(bufidx) (bufidx=(bufidx+1)&__BUF_MASK)
typedef struct
{
__IO uint32_t tx_head; /*!< UART Tx ring buffer head index */
__IO uint32_t tx_tail; /*!< UART Tx ring buffer tail index */
__IO uint32_t rx_head; /*!< UART Rx ring buffer head index */
__IO uint32_t rx_tail; /*!< UART Rx ring buffer tail index */
__IO uint8_t tx[UART_RING_BUFSIZE]; /*!< UART Tx data ring buffer */
__IO uint8_t rx[UART_RING_BUFSIZE]; /*!< UART Rx data ring buffer */
} UART_RING_BUFFER_T;
// UART Ring buffer
UART_RING_BUFFER_T rb;
// Current Tx Interrupt enable state
__IO FlagStatus TxIntStat;
中断IRQHandler:
void UART0_IRQHandler(void)
{
uint32_t intsrc,tmp,tmp1;
/* Determine the interrupt source */
intsrc = UART_GetIntId(LPC_UART0);
tmp = intsrc & UART_IIR_INTID_MASK;
// Receive Line Status
if (tmp == UART_IIR_INTID_RLS){
// Check line status
tmp1 = UART_GetLineStatus(LPC_UART0);
// Mask out the Receive Ready and Transmit Holding empty status
tmp1 &= (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE \
| UART_LSR_BI | UART_LSR_RXFE);
// If any error exist
if (tmp1) {
UART_IntErr(tmp1);
}
}
// Receive Data Available or Character time-out
if ((tmp == UART_IIR_INTID_RDA) || (tmp == UART_IIR_INTID_CTI)){
UART_IntReceive();
}
// Transmit Holding Empty
if (tmp == UART_IIR_INTID_THRE){
UART_IntTransmit();
}
}
用于接收数据:
void UART_IntReceive(void)
{
uint8_t temp;
uint32_t recv_byte;
while(1){
recv_byte = UART_Receive((LPC_UART_TypeDef *)LPC_UART0,&temp,1,NONE_BLOCKING);
// If data received
if (recv_byte){
if (!__BUF_IS_FULL(rb.rx_head,rb.rx_tail)){
rb.rx[rb.rx_head] = temp;
__BUF_INCR(rb.rx_head);
}
}
// no more data
else {
break;
}
}
}
用于传输数据:
void UART_IntTransmit(void)
{
// Disable THRE interrupt
UART_IntConfig((LPC_UART_TypeDef *)LPC_UART0,UART_INTCFG_THRE,DISABLE);
while (UART_CheckBusy((LPC_UART_TypeDef *)LPC_UART0) == SET);
while (!__BUF_IS_EMPTY(rb.tx_head,rb.tx_tail))
{
/* Move a piece of data into the transmit FIFO */
if (UART_Send((LPC_UART_TypeDef *)LPC_UART0,(uint8_t *)&rb.tx[rb.tx_tail],NONE_BLOCKING)){
/* Update transmit ring FIFO tail pointer */
__BUF_INCR(rb.tx_tail);
} else {
break;
}
}
if (__BUF_IS_EMPTY(rb.tx_head,rb.tx_tail)) {
UART_IntConfig((LPC_UART_TypeDef *)LPC_UART0,DISABLE);
// Reset Tx Interrupt state
TxIntStat = RESET;
}
else{
// Set Tx Interrupt state
TxIntStat = SET;
UART_IntConfig((LPC_UART_TypeDef *)LPC_UART0,ENABLE);
}
}
void UART_IntErr(uint8_t bLSErrType)
{
uint8_t test;
// Loop forever
while (1){
// For testing purpose
test = bLSErrType;
}
}
UART接收和发送功能在中断中使用:
uint32_t UART_Send(LPC_UART_TypeDef *UARTx,uint8_t *txbuf,uint32_t buflen,TRANSFER_BLOCK_Type flag)
{
uint32_t bToSend,bSent,timeOut,fifo_cnt;
uint8_t *pChar = txbuf;
bToSend = buflen;
// blocking mode
if (flag == BLOCKING) {
bSent = 0;
while (bToSend){
timeOut = UART_BLOCKING_TIMEOUT;
// Wait for THR empty with timeout
while (!(UARTx->LSR & UART_LSR_THRE)) {
if (timeOut == 0) break;
timeOut--;
}
// Time out!
if(timeOut == 0) break;
fifo_cnt = UART_TX_FIFO_SIZE;
while (fifo_cnt && bToSend){
UART_SendByte(UARTx,(*pChar++));
fifo_cnt--;
bToSend--;
bSent++;
}
}
}
// None blocking mode
else {
bSent = 0;
while (bToSend) {
if (!(UARTx->LSR & UART_LSR_THRE)){
break;
}
fifo_cnt = UART_TX_FIFO_SIZE;
while (fifo_cnt && bToSend) {
UART_SendByte(UARTx,(*pChar++));
bToSend--;
fifo_cnt--;
bSent++;
}
}
}
return bSent;
}
uint32_t UART_Receive(LPC_UART_TypeDef *UARTx,uint8_t *rxbuf,\
uint32_t buflen,TRANSFER_BLOCK_Type flag)
{
uint32_t bToRecv,bRecv,timeOut;
uint8_t *pChar = rxbuf;
bToRecv = buflen;
// Blocking mode
if (flag == BLOCKING) {
bRecv = 0;
while (bToRecv){
timeOut = UART_BLOCKING_TIMEOUT;
while (!(UARTx->LSR & UART_LSR_RDR)){
if (timeOut == 0) break;
timeOut--;
}
// Time out!
if(timeOut == 0) break;
// Get data from the buffer
(*pChar++) = UART_ReceiveByte(UARTx);
bToRecv--;
bRecv++;
}
}
// None blocking mode
else {
bRecv = 0;
while (bToRecv) {
if (!(UARTx->LSR & UART_LSR_RDR)) {
break;
} else {
(*pChar++) = UART_ReceiveByte(UARTx);
bRecv++;
bToRecv--;
}
}
}
return bRecv;
}
UART TX和RX功能:
uint32_t UARTSend(LPC_UART_TypeDef *UARTPort,uint8_t buflen)
{
uint8_t *data = (uint8_t *) txbuf;
uint32_t bytes = 0;
UART_IntConfig(UARTPort,DISABLE);
while ((buflen > 0) && (!__BUF_IS_FULL(rb.tx_head,rb.tx_tail)))
{
/* Write data from buffer into ring buffer */
rb.tx[rb.tx_head] = *data;
data++;
/* Increment head pointer */
__BUF_INCR(rb.tx_head);
bytes++;
buflen--;
}
if (TxIntStat == RESET) {
UART_IntTransmit();
}
else {
UART_IntConfig(UARTPort,ENABLE);
}
return bytes;
}
uint32_t UARTReceive(LPC_UART_TypeDef *UARTPort,uint8_t buflen)
{
uint8_t *data = (uint8_t *) rxbuf;
uint32_t bytes = 0;
UART_IntConfig(UARTPort,UART_INTCFG_RBR,DISABLE);
while ((buflen > 0) && (!(__BUF_IS_EMPTY(rb.rx_head,rb.rx_tail))))
{
/* Read data from ring buffer into user buffer */
*data = rb.rx[rb.rx_tail];
data++;
/* Update tail pointer */
__BUF_INCR(rb.rx_tail);
/* Increment data count and decrement buffer size count */
bytes++;
buflen--;
}
UART_IntConfig(UARTPort,ENABLE);
return bytes;
}
主要功能
void main(){
uint32_t idx=0,len[enter link description here][1]=0;
__IO FlagStatus exitflag;
uint8_t buffer[100]
// reset exit flag
exitflag = RESET;
while (exitflag == RESET)
{
len = 0;
while (len == 0)
{
len = UARTReceive((LPC_UART_TypeDef *)LPC_UART0,buffer,sizeof(buffer));
}
idx = 0;
while (idx < len)
{
UARTSend((LPC_UART_TypeDef *)LPC_UART0,&buffer[idx],1);
idx++;
}
}
}
此外,观察到读取.txt文件时不会在读取时遗漏任何字节。只是在读取.bin文件时出现的问题。
请让我知道哪里出了问题。
本文链接:https://www.f2er.com/3124921.html