STM32的USART发送数据时如何使用TXE和TC标志

在USART的发送端有2个寄存器,一个是程序可以看到的USART_DR寄存器(下图中阴影部分的TDR),另一个是程序看不到的移位寄存器(下图中阴影部分Transmit Shift Register)。

对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送结束;对照下图,当TDR中的数据传送到移位寄存器后,TXE被设置,此时移位寄存器开始向TX信号线按位传输数据,但因为TDR已经变空,程序可以把下一个要发送的字节(操作USART_DR)写入TDR中,而不必等到移位寄存器中所有位发送结束,所有位发送结束时(送出停止位后)硬件会设置TC标志。

另一方面,在刚刚初始化好USART还没有发送任何数据时,也会有TXE标志,因为这时发送数据寄存器是空的。

TXEIE和TCIE的意义很简单,TXEIE允许在TXE标志为'1'时产生中断,而TCIE允许在TC标志为'1'时产生中断。

至于什么时候使用哪个标志,需要根据你的需要自己决定。但我认为TXE允许程序有更充裕的时间填写TDR寄存器,保证发送的数据流不间断。TC可以让程序知道发送结束的确切时间,有利于程序控制外部数据流的时序。





STM32设置了很多非常有用和灵活的控制和状态位,只要你很好地掌握了它们的用法,可以让你的应用更加精确和高效。



这是STM32技术参考手册中的一页:


点击开大图

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用DMA中断实现STM32F103 USART1接收和发送的示例代码: ```c #include "stm32f10x.h" #define USART1_DR_Address 0x40013804 #define BUFFER_SIZE 256 uint8_t RxBuffer[BUFFER_SIZE]; uint8_t TxBuffer[BUFFER_SIZE]; volatile uint16_t RxCounter = 0; volatile uint16_t TxCounter = 0; volatile uint8_t RxComplete = 0; volatile uint8_t TxComplete = 0; void RCC_Configuration(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } void USART_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } void DMA_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)USART1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)USART1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); } void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void DMA1_Channel4_IRQHandler(void) { if (DMA_GetITStatus(DMA1_IT_TC4) == SET) { DMA_ClearITPendingBit(DMA1_IT_TC4); RxComplete = 1; } } void DMA1_Channel5_IRQHandler(void) { if (DMA_GetITStatus(DMA1_IT_TC5) == SET) { DMA_ClearITPendingBit(DMA1_IT_TC5); TxComplete = 1; } } void USART1_DMA_Send(uint8_t* buffer, uint16_t size) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); DMA_Cmd(DMA1_Channel5, DISABLE); while (DMA_GetCmdStatus(DMA1_Channel5) == ENABLE); DMA_SetCurrDataCounter(DMA1_Channel5, size); DMA_MemoryTargetConfig(DMA1_Channel5, (uint32_t) buffer, DMA_Memory_0); DMA_Cmd(DMA1_Channel5, ENABLE); } void USART1_DMA_Receive(uint8_t* buffer, uint16_t size) { DMA_Cmd(DMA1_Channel4, DISABLE); while (DMA_GetCmdStatus(DMA1_Channel4) == ENABLE); DMA_SetCurrDataCounter(DMA1_Channel4, size); DMA_MemoryTargetConfig(DMA1_Channel4, (uint32_t) buffer, DMA_Memory_0); DMA_Cmd(DMA1_Channel4, ENABLE); } int main(void) { RCC_Configuration(); GPIO_Configuration(); USART_Configuration(); DMA_Configuration(); NVIC_Configuration(); USART1_DMA_Receive(RxBuffer, BUFFER_SIZE); while (1) { if (RxComplete) { RxComplete = 0; RxCounter = BUFFER_SIZE - DMA_GetCurrDataCounter(DMA1_Channel4); // 处理接收到的数据 // ... USART1_DMA_Send(TxBuffer, TxCounter); } if (TxComplete) { TxComplete = 0; TxCounter = 0; // 发送完成 } } } ``` 代码中使用了DMA的循环模式,接收和发送缓冲区大小均为256字节,可以根据需要进行修改。接收完成后会触发DMA中断,处理接收到的数据发送响应数据发送完成后会触发DMA中断,可以进行下一次发送
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值