串口初始化
void MX_USART3_UART_Init(void)
{
UART3_Handler.Instance = USART3;
UART3_Handler.Init.BaudRate = 2400;
UART3_Handler.Init.WordLength = UART_WORDLENGTH_9B; //发送8位和9位是一样的道理
UART3_Handler.Init.StopBits = UART_STOPBITS_1;
UART3_Handler.Init.Parity = UART_PARITY_NONE;
UART3_Handler.Init.Mode = UART_MODE_TX_RX;
UART3_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UART3_Handler.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&UART3_Handler) != HAL_OK) //这个函数中会调用下面这个函数//HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//Error_Handler(); //我的实验工程中没有实现这个函数
}
}
UART底层初始化,时钟使能,引脚配置,中断配置,使用的是MX主动生成的函数,其实道理一样就是初始化串口,将相关的数据填入对应的寄存器,我试过自己直接操作寄存器(像操作单片机一样),实现也使用一样,为了方便
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//如果是串口3,进行串口3 MSP初始化
if(huart->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* USART3 clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USART3 interrupt Init */
HAL_NVIC_EnableIRQ(USART3_IRQn);
HAL_NVIC_SetPriority(USART3_IRQn, 3, 3);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
}
/*************************************************************************
*串口3:中断服务程序
*************************************************************************/
void USART3_IRQHandler(void)
{
HAL_UART_IRQHandler(&UART3_Handler); //调用HAL库中断处理公用函数
}
/*************************************************************************
*工程中只要调用这个函数即可以发生数据
*************************************************************************/
void modules_common_total(void)
{
if(modules_commt_send.commt_send_state)
{
if(modules_commt_send.commt_send_second_dat_signl == 0)
{
modules_commt_send.commt_send_second_dat_signl = 1;
HAL_UART_Transmit(&UART3_Handler,(uint8_t *)modules_commt_send.commt_send_dat_buf,modules_commt_send.commt_send_dat_count,0xffff);
}
}
if(modules_commt_send.commt_send_state == 0)
{
.......
}
}
这里要说明的是,串口监视软件的使用,我使用的是9位数据发送,一般的串口监控只有8位,那么需要使用的是将校验位设置为“0校验”(STC下载程序的软件里有个串口助手具备这个功能),这样就能监控到传输的前八位是否正常)最高位没有办法,若有能监控到9位的软件,望朋友告知
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
uint16_t* tmp;
uint32_t tmp1 = 0;
tmp1 = huart->State;//串口状态
if((tmp1 == HAL_UART_STATE_READY) || (tmp1 == HAL_UART_STATE_BUSY_RX))//准备就绪,正在接收状态,反正发送不忙
{
if((pData == NULL ) || (Size == 0))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Check if a non-blocking 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;
}
huart->TxXferSize = Size;
huart->TxXferCount = Size; //剩余发送数量
while(huart->TxXferCount > 0)
{
huart->TxXferCount--;
/*
//实验时自己在这里添加的几句
if(huart->TxXferCount == 0)
{
modules_commt_send.commt_send_state = 0;
}
*/
if(huart->Init.WordLength == UART_WORDLENGTH_9B) //9位数据模式
{
if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, Timeout) != HAL_OK)
{ //上面这里是检测SR中是否为TXE=1,为1表示DR中可以接受新的数据,上个数据已经开始发送
return HAL_TIMEOUT;
}
tmp = (uint16_t*) pData;
huart->Instance->DR = (*tmp & (uint16_t)0x01FF); //写入数据后会自动启动发送
if(huart->Init.Parity == UART_PARITY_NONE) //#define UART_PARITY_NONE ((uint32_t)0x00000000)
{ //在初始化串口的时候会有这句 UART3_Handler.Init.Parity = UART_PARITY_NONE;
pData +=2;
}
else
{
pData +=1;
}
}
else
{
if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
}
}
if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
/* Check if a non-blocking receive 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;
}
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
从上面这个函数看出,这里是个死循环,一直会等到发送完成,但是要注意了,这个函数调用后并不能进入发送中断回调函数HAL_UART_TxCpltCallback(),这是因为没有置位TXEIE,不会产生中断,而UART_Transmit_IT(huart);函数中有会程序如下
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
uint32_t tmp = 0;
tmp = huart->State;
if((tmp == HAL_UART_STATE_READY) || (tmp == 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;
}
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Transmit data register empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE); 这一句很重要,
它是这样的
#define UART_IT_TXE ((uint32_t)(UART_CR1_REG_INDEX << 28 | USART_CR1_TXEIE))
这就能形成中断,我尝试在HAL_StatusTypeDef HAL_UART_Transmit()中合适的位置添加这样一句__HAL_UART_ENABLE_IT(huart, UART_IT_TXE); 也将产生中断,
遗憾的是 HAL_UART_Transmit_IT()不支持9位数据发送,需要直接进行修改,接下来我只能自己改了
中断程序如下
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t tmp1 = 0, tmp2 = 0;
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_PE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE);
/* UART parity error interrupt occurred ------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
__HAL_UART_CLEAR_PEFLAG(huart);
huart->ErrorCode |= HAL_UART_ERROR_PE;
}
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_FE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
/* UART frame error interrupt occurred -------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
__HAL_UART_CLEAR_FEFLAG(huart);
huart->ErrorCode |= HAL_UART_ERROR_FE;
}
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_NE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
/* UART noise error interrupt occurred -------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
__HAL_UART_CLEAR_NEFLAG(huart);
huart->ErrorCode |= HAL_UART_ERROR_NE;
}
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
/* UART Over-Run interrupt occurred ----------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
__HAL_UART_CLEAR_OREFLAG(huart);
huart->ErrorCode |= HAL_UART_ERROR_ORE;
}
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
/* UART in mode Receiver ---------------------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
UART_Receive_IT(huart);
}
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE);
/* UART in mode Transmitter ------------------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
UART_Transmit_IT(huart);
}
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_TC);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC);
/* UART in mode Transmitter end --------------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
UART_EndTransmit_IT(huart);
}
if(huart->ErrorCode != HAL_UART_ERROR_NONE)
{
/* Set the UART state ready to be able to start again the process */
huart->State = HAL_UART_STATE_READY;
HAL_UART_ErrorCallback(huart);
}
}
中断与这几个函数有关UART_Receive_IT(huart); UART_Transmit_IT(huart);UART_EndTransmit_IT(huart);但是与HAL_UART_Transmit();无关,