STM32
直播中

张强

7年用户 1373经验值
私信 关注
[问答]

串口发送宽度为9位数据的实现方法

串口发送宽度为9位数据的实现方法

回帖(1)

王睦羽

2021-12-3 10:51:43

最近为了配置一个芯片使用到了串口发送9位数据位的情况,在此小记一下。


1. 串口硬件和参数初始化
将数据位宽度配置成:UART_WORDLENGTH_9B ,其他参数和常规配置一样。


UART_HandleTypeDef husart3;


void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{


  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART3)
  {
         __HAL_RCC_GPIOC_CLK_ENABLE();//IO时钟使能
  
    GPIO_InitStruct.Pin = USARTx_Tx_GPIO_PIN|USARTx_Rx_GPIO_PIN;//PB10和PB11
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = USARTx_AFx;
    HAL_GPIO_Init(USARTx_Tx_GPIO, &GPIO_InitStruct);
   
    GPIO_InitStruct.Pin = USARTx_Rx_GPIO_PIN;
    HAL_GPIO_Init(USARTx_Rx_GPIO, &GPIO_InitStruct);
  }
}


void MX_USART3_Init(void)
{
         __HAL_RCC_USART3_CLK_ENABLE();//串口3时钟使能
  
    huart3.Instance = USART3;
    huart3.Init.BaudRate = USART3_BAUDRATE;
    huart3.Init.WordLength = UART_WORDLENGTH_9B;//数据位宽度改为9位
    huart3.Init.StopBits = UART_STOPBITS_1;//一位停止位
    huart3.Init.Parity = UART_PARITY_NONE;//无奇偶校验位
    huart3.Init.Mode = UART_MODE_TX_RX;
    huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart3.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart3);
   
    HAL_UART_Receive_IT(&huart3,Usart3_TempData,1);  
        HAL_NVIC_SetPriority(USART3_IRQn, 2, 2);
    HAL_NVIC_EnableIRQ(USART3_IRQn);
}


2. 串口发送相关库函数的修改
看了下库函数,如果想要收发数据位宽度为9位的数据,貌似只能够通过阻塞模式发送,如下是阻塞模式下串口发送数据的库函数(省略部分函数,只留取了最关键的代码):


/**
  * @brief  Sends an amount of data in blocking mode.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  pData: Pointer to data buffer
  * @param  Size: Amount of data to be sent
  * @param  Timeout: Timeout duration  
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
      ...省略
      if(huart->Init.WordLength == UART_WORDLENGTH_9B)
      {
            ...省略
                tmp = (uint16_t*) pData;
                huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
                ...省略
      }
      ...省略
}


我发现这个库函数发送数据宽度为9位数据时时这样的,如果第9位数据为0的话,本质就是在停止位前添加一位数据0,如果第九位想发1的话,那就不需要这个函数了,即通过正常的8N1格式发送即可,直接用停止位当第9位就可以.


这样的话是可以实现,只是比较麻烦。比如在使用9位数据宽度配置一些传感器时需要反复的将第9位变为1或0,如果按照官方提供的这种库函数来实现的话,那就得反复将串口配置成8B或9B的模式,非常的不方便,也很不直观。所以我把这个函数做了一些简单的修改,多加了一个第9位位选择的参数。


程序如下:


/**
  * @brief  Sends an amount of data in blocking mode.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  pData: Pointer to data buffer
  * @param  Size: Amount of data to be sent
  * @param  Bit_9 : bit 9 state
  * @param  Timeout: Timeout duration  
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Transmit_9B(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint8_t Bit_9, uint32_t Timeout)
{
      ...省略
      if(huart->Init.WordLength == UART_WORDLENGTH_9B)
      {
          ...省略  
          tmp = (uint16_t*) pData;
          //huart->Instance->DR = (*tmp & (uint16_t)0x01FF);之前的数据处理方式屏蔽掉
          //以下是自己添加的第九位数据位处理的相关代码
          if(Bit_9 == 1)
          {
              huart->Instance->DR = (*tmp | (uint16_t)0x0100);//将第九位置1
          }
          else
          {
              huart->Instance->DR = (*tmp & (uint16_t)0x00FF);//将第九位置0
          }
              ...省略
      }
      ...省略
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分