我有一个用于微控制器的C源代码,我将向您展示标题的第一部分:
#define USART_RX_BUFFER_SIZE 256
#define USART_TX_BUFFER_SIZE 256
#define USART_RX_BUFFER_MASK (USART_RX_BUFFER_SIZE - 1)
#define USART_TX_BUFFER_MASK (USART_TX_BUFFER_SIZE - 1)
#if (USART_RX_BUFFER_SIZE & USART_RX_BUFFER_MASK)
#error RX buffer size is not a power of 2
#endif
#if (USART_TX_BUFFER_SIZE & USART_TX_BUFFER_MASK)
#error TX buffer size is not a power of 2
#endif
typedef struct USART_Buffer {
volatile uint8_t RX[USART_RX_BUFFER_SIZE];
volatile uint8_t TX[USART_TX_BUFFER_SIZE];
volatile uint16_t RX_Head;
volatile uint16_t RX_Tail;
volatile uint16_t TX_Head;
volatile uint16_t TX_Tail;
} USART_Buffer_t;
typedef struct Usart_and_buffer {
USART_t *usart;
USART_DREINTLVL_t dreIntLevel;
USART_TXCINTLVL_t txcIntLevel;
USART_Buffer_t buffer;
PORT_t *rs485_Port;
uint8_t rs485_Pin;
bool rs485;
} USART_data_t;
uint8_t USART_RXBuffer_GetByte(USART_data_t *usart_data);
bool USART_RXComplete(USART_data_t *usart_data);
void USART_TransmitComplete(USART_data_t *usart_data);
...
还有其他一些类似的功能。
它们的实现通常同时使用USART_data_t
和USART_Buffer_t
,例如:
bool USART_TXBuffer_PutByte(USART_data_t *usart_data, uint8_t data) {
uint8_t tempCTRLA;
uint16_t tempTX_Head;
bool TXBuffer_FreeSpace;
USART_Buffer_t * TXbufPtr;
if (usart_data->rs485) usart_data->rs485_Port->OUTSET = usart_data->rs485_Pin;
TXbufPtr = &usart_data->buffer;
...
在我的实际应用程序中,我需要声明许多USART_data_t
结构,但只有其中几个需要如此大的缓冲区(256字节)。大多数将使用很小的字节,例如64甚至32字节。
我很容易用完内存,实际上所有空间都未使用。
我的目标是找到一种节省空间的方法。
肮脏的方法是克隆整个文件,将 all 重命名为变量/函数,以具有两个不同的版本,例如一个带有256字节的缓冲区,另一个带有64字节的缓冲区。 。 但是然后我还必须更改代码中的每个调用,否则我将避免这种情况。
此库非常快,因为它可在2的幂的循环缓冲区上工作,并且使用上面的定义,只需几个时钟周期即可完成所需的数学运算。因此,我真的不想重写整个库以使用内存的动态分配。
还有其他想法吗?
使用示例:
USART_data_t RS232B_USART_data;
USART_data_t RS232A_USART_data;
#define RS232B_BUFFER_SIZE 4
char RS232B_RxBuffer[RS232B_BUFFER_SIZE];
char RS232B_TxBuffer[RS232B_BUFFER_SIZE];
#define RS232A_BUFFER_SIZE 64
char RS232A_RxBuffer[RS232A_BUFFER_SIZE];
char RS232A_TxBuffer[RS232A_BUFFER_SIZE];
ISR(USARTC1_RXC_vect) { USART_RXComplete(&RS232B_USART_data); }
ISR(USARTC1_DRE_vect) { USART_DataRegEmpty(&RS232B_USART_data); }
ISR(USARTC1_TXC_vect) { USART_TransmitComplete(&RS232B_USART_data); }
ISR(USARTD0_RXC_vect) { USART_RXComplete(&RS232A_USART_data); }
ISR(USARTD0_DRE_vect) { USART_DataRegEmpty(&RS232A_USART_data); }
ISR(USARTD0_TXC_vect) { USART_TransmitComplete(&RS232A_USART_data); }
// ...
USART_InterruptDriver_Initialize(&RS232B_USART_data, &RS232B_USART, USART_DREINTLVL_LO_gc, USART_TXCINTLVL_LO_gc, false);
USART_Format_Set(RS232B_USART_data.usart, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
USART_RxdInterruptLevel_Set(RS232B_USART_data.usart, USART_RXCINTLVL_HI_gc);
USART_Baudrate_Set(&RS232B_USART, 2094, -7);
USART_Rx_Enable(RS232B_USART_data.usart);
USART_Tx_Enable(RS232B_USART_data.usart);
USART_InterruptDriver_Initialize(&RS232A_USART_data, &RS232A_USART, USART_DREINTLVL_LO_gc, USART_TXCINTLVL_LO_gc, false);
USART_Format_Set(RS232A_USART_data.usart, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
USART_RxdInterruptLevel_Set(RS232A_USART_data.usart, USART_RXCINTLVL_HI_gc);
USART_Baudrate_Set(&RS232A_USART, 2094, -7);
USART_Rx_Enable(RS232A_USART_data.usart);
USART_Tx_Enable(RS232A_USART_data.usart);
答案 0 :(得分:0)
您可能会重写USART_Buffer_t,使其仅包含指向rx / tx缓冲区的指针,并添加两个附加变量,这些变量设置为“附加”缓冲区的大小。
这都是写下来的,所以请期待错别字等,但希望您能理解。
typedef struct USART_Buffer {
volatile uint8_t* pRX;
volatile uint8_t* pTX;
volatile uint16_t RX_Size;
volatile uint16_t TX_Size;
volatile uint16_t RX_Head;
volatile uint16_t RX_Tail;
volatile uint16_t TX_Head;
volatile uint16_t TX_Tail;
} USART_Buffer_t;
然后您编写一个辅助函数,如
USART_InitBuffers(USART_data_t data, uint8_t* pTxBuffer, uint16_t sizeTxBuffer, uint8_t* pRxBuffer, uint16_t sizeRxBuffer) {
data.pRX = pTxBuffer;
// ... other assignments
}
这样,您可以为每个USART指定不同大小的数组:
uint8_t TxData1[100]
uint8_t RxData1[10]
uint8_t TxData2[255]
uint8_t RxData2[50]
USART_Buffer_t data1;
USART_Buffer_t data2;
main() {
USART_InitBuffers(&data1, TxData1, sizeof(TxData1), RxData1, sizeof(RxData1));
USART_InitBuffers(&data2, TxData2, sizeof(TxData2), RxData2, sizeof(RxData2));
}
最后,您必须调整库函数,以使用RX_Size和TX_Size而不是使用USART_RX_BUFFER_SIZE和USART_TX_BUFFER_SIZE。