使用的是stm32f103 V1.40版本的库
发送函数
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
发送完毕之后成功的回调函数也正常,可是再次发送的时候就发不出去了。一直返回错误。
我们看下这个函数的代码
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
uint32_t *tmp;
uint32_t tmp_state = 0;
tmp_state = huart->State;
if((tmp_state == HAL_UART_STATE_READY) || (tmp_state == HAL_UART_STATE_BUSY_RX))
{
if((pData == NULL ) || (Size == 0))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Check if a receive process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_RX)
{
huart->State = HAL_UART_STATE_BUSY_TX_RX;
}
else
{
huart->State = HAL_UART_STATE_BUSY_TX;
}
/* Set the UART DMA transfer complete callback */
huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;
/* Set the UART DMA Half transfer complete callback */
huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;
/* Set the DMA error callback */
huart->hdmatx->XferErrorCallback = UART_DMAError;
/* Enable the UART transmit DMA channel */
tmp = (uint32_t*)&pData;
HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t*)tmp, (uint32_t)&huart->Instance->DR, Size);
/* Clear the TC flag in the SR register by writing 0 to it */
__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
/* Enable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
代码中可以看出,发送之前先判断状态标志,不是在发送状态才进行发送,这也正常。但是,发送一次之后,状态就被至为发送状态,发送完毕也没有清楚,这就导致了下次再发送,判断为忙,就发不出去了。我们看下他发送成功的处理部分。
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
/* DMA Normal mode*/
if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
{
huart->TxXferCount = 0;
/* Disable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
/* DMA Circular mode */
else
{
HAL_UART_TxCpltCallback(huart);
}
}
代码中可以看到,并没有清除发送的状态,这就导致了下次发送不成功的问题。
难道要自己发送之前清除一下状态,我想这应该不是库函数的本意。
我们对比看下接收成功是如何处理的
static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
/* DMA Normal mode*/
if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
{
huart->RxXferCount = 0;
/* Disable the DMA transfer for the receiver request by setting the DMAR bit
in the UART CR3 register */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Check if a transmit process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
{
huart->State = HAL_UART_STATE_BUSY_TX;
}
else
{
huart->State = HAL_UART_STATE_READY;
}
}
HAL_UART_RxCpltCallback(huart);
}
接收成功之后有正确清除状态标志,发送成功应该也是同样的,所以可能是漏掉了。我们加上即可
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
/* DMA Normal mode*/
if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
{
huart->TxXferCount = 0;
/* Disable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
/* Check if a transmit process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
{
huart->State = HAL_UART_STATE_BUSY_RX;
}
else
{
huart->State = HAL_UART_STATE_READY;
}
}
/* DMA Circular mode */
else
{
HAL_UART_TxCpltCallback(huart);
}
}
测试,可以正常发送了····
HAL的库flash对比标准库变化还是挺大的,写保护这块需要手动去配置。
上代码
FLASH_OBProgramInitTypeDef obProgram;
__HAL_FLASH_PREFETCH_BUFFER_DISABLE();
HAL_FLASHEx_OBGetConfig(&obProgram);
if (obProgram.RDPLevel == OB_RDP_LEVEL_0)
{
obProgram.OptionType = OPTIONBYTE_WRP; //读写保护
obProgram.WRPState = OB_WRPSTATE_ENABLE; //使能
obProgram.WRPPage = OB_WRP_ALLPAGES; //所有页
obProgram.Banks = FLASH_BANK_1;
obProgram.RDPLevel = OB_RDP_LEVEL_1;
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
HAL_FLASHEx_OBProgram(&obProgram);
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
}
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();