zoukankan      html  css  js  c++  java
  • STM32L476应用开发之三:串行通讯实验

    在我们的项目需求中,有两个串口应用需求,一个是与炭氢传感器的通讯,另一个是与显示屏的通讯。鉴于此,我们需要实验串行通讯。

    1、硬件设计

    串行通讯一个采用RS232接口,另一个直接采用TTL方式。我们在STM32L476RG开发板中,发现USART1和USART3的输入输出端口已经引出来,所以我们使用这两个串口。

    USART1_TX           PA9              CN5-1

    USART1_RX          PA10     CN9-3

    USART3_TX           PC4              CN10-34

    USART3_RX          PC5              CN10-6

    如下图红色方框中所示:

     

    对于RS232接口我们采用了周立功RSM232模块来做实验,其推荐的连接方式如下图:

     

    在实验过程中我们不需要这些保护措施,根据以上的分析我们可以对串口通讯做如下设计。RS232接口原理图如下:

     

    对于单总线TTL通讯,我们采用如下原理图来实现:

     

    2、软件设计

    完成硬件连接后我们可以开始软件开发了,首先我们在STM32CubeMX中对硬件部分进行配置。其中USART1和USART3的配置如下图所示:

     

    而后对串口部分做参数配置,波特率等按要求配置好,很简单在此不多说了。接下来编写测试代码。

    static void Test_UART_Configuration(void)
    {
      huart1.Instance = USART1;
      huart1.Init.BaudRate = 115200;
      huart1.Init.WordLength = UART_WORDLENGTH_8B;
      huart1.Init.StopBits = UART_STOPBITS_1;
      huart1.Init.Parity = UART_PARITY_NONE;
      huart1.Init.Mode = UART_MODE_TX_RX;
      huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    
      if (HAL_UART_Init(&huart1) != HAL_OK)
      {
        Error_Handler();
      }

    定义一个简单的类Modbus通讯协议,采用中断方式来实现数据接收。中断处理函数如下:

    void USART1_ReceiveDataHandle(void)
    {
      if(ozonatorRxLength>=RETURNING_DATA_LENGTH)
      {
        ozonatorRxLength=0;
      }
      /*接收寄存器为空,等待字节被对应的串口完全接收*/
    if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET)
      {
        uint8_t rData;
        /*获取接收到的字节*/
        HAL_UART_Receive(&huart1,&rData,1,1000);
        TestRxBuffer[ozonatorRxLength++] = rData;
      }
    }

    对接收到的信息进行解析,并根据请求命令完成放回信息的编码并回传。

    /*解析接收到的信息,并返回合成的回复信息和信息的字节长度,通过回调函数*/
    uint16_t ParsingMasterAccessCommand(uint8_t *receivedMessage,uint8_t *respondBytes,uint16_t rxLength)
    {
      uint16_t respondLength=0;
      /*判断是否是本站,如不是不处理*/
      uint8_t slaveAddress=*receivedMessage;
      if(slaveAddress!=StationAddress)
      {
        return 0;
      }
    
      /*判断功能码是否有误*/
      FunctionCode fc=(FunctionCode)(*(receivedMessage+1));
      if(CheckFunctionCode(fc)!=MB_OK)
      {
        return 0;
      }
    
      /*信息校验,如不正确则为错误信息不用处理*/
      uint16_t dataLength=8;
      if((fc==WriteMultipleCoil)||(fc==WriteMultipleRegister))
      {
        dataLength=(uint16_t)(*(receivedMessage+6))+9;
        if(rxLength<dataLength)//尚未接收完整
        {
          return 65535;
        }
      }
    
      bool chechMessageNoError=CheckRTUMessageIntegrity(receivedMessage,dataLength);
      if(!chechMessageNoError)
      {
        return 0;
      } 
    
      uint16_t startAddress=(uint16_t)(*(receivedMessage+2));
      startAddress=(startAddress<<8)+(uint16_t)(*(receivedMessage+3));
      uint16_t quantity=(uint16_t)(*(receivedMessage+4));
      quantity=(quantity<<8)+(uint16_t)(*(receivedMessage+5));
      uint8_t index=(fc>0x08)?(fc-0x09):(fc-0x01);
    
      respondLength=HandleMasterCommand[index](startAddress,quantity,receivedMessage,respondBytes);
    
      return respondLength;
    }

    3、测试结果

    通过USB转RS232接口的模块接入电脑通过AccessPort和串口出手来对通讯进行测试。下图是在AccessPort中监控到的数据收发状态:

     

    下图是在串口助手中发送命令及接收反馈的截图:

     

    串口通讯方式测试完成,完全能符合我们的要求。

  • 相关阅读:
    SQL数据库inner join ,join,left join,full join(转)
    CSRF攻击(转)
    BZOJ1853: [Scoi2010]幸运数字
    BZOJ1935: [Shoi2007]Tree 园丁的烦恼
    BZOJ3289Mato的文件管理
    树状数组
    莫队算法
    如何在win上用Linux编c++
    Hash的应用
    关于指数循环节的证明
  • 原文地址:https://www.cnblogs.com/foxclever/p/7594123.html
Copyright © 2011-2022 走看看