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中监控到的数据收发状态:

     

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

     

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

  • 相关阅读:
    HDU 1874 畅通工程续(dijkstra)
    HDU 2112 HDU Today (map函数,dijkstra最短路径)
    HDU 2680 Choose the best route(dijkstra)
    HDU 2066 一个人的旅行(最短路径,dijkstra)
    关于测评机,编译器,我有些话想说
    测评机的优化问题 时间控制
    CF Round410 D. Mike and distribution
    数字三角形2 (取模)
    CF Round410 C. Mike and gcd problem
    CF Round 423 D. High Load 星图(最优最简构建)
  • 原文地址:https://www.cnblogs.com/foxclever/p/7594123.html
Copyright © 2011-2022 走看看