aple0807 发表于 2023-10-29 10:39

【AT-START-F423测评】多通道MODBUS测试

本帖最后由 aple0807 于 2023-10-29 10:38 编辑

今天测试一下基于UART的MODBUS-RTU,AT32F423多大8路UART,做工业仪表是个不错的选择。
本次测试使用两个串口:
USART2配置为从机:9600,8N2, 站号1
USART3配置为主站:9600,8N2, 配置命令访问站号1

IO配置:
// U2
{GPIOA, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, GPIO_PINS_2 | GPIO_PINS_3},      
// U3
{GPIOB, GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MUX_7, GPIO_PINS_10 | GPIO_PINS_11},
串口初始化:

/*****************************************************************************
* @brief         com modle init .
* @param   none
* @returnnone
* @ Pass/ Fail criteria: none
*****************************************************************************/
static void qc_port_Init(uu8 qcMode, uint32_t ulBaudRate, mb_parity_type eParity)
{
      usart_data_bit_num_type dat_bits;
      usart_stop_bit_num_type stop_bits;
      usart_parity_selection_type parity;

      qc_port_hal_cfg();

      qc_cb_set();
      qc_obj.mode = qcMode;
      qc_obj.dat_send = qc_port_send;

      qc_byte_send = qc_rtu_byte_send;

      // rtu mode
      if (MB_PAR_NONE == eParity)
      {
                dat_bits = USART_DATA_8BITS;
                stop_bits = USART_STOP_2_BIT;
                parity = USART_PARITY_NONE;
      }
      else if (MB_PAR_NONE_1S == eParity)
      {
                dat_bits = USART_DATA_8BITS;
                stop_bits = USART_STOP_1_BIT;
                parity = USART_PARITY_NONE;
      }
      else if (MB_PAR_ODD == eParity)
      {
                dat_bits = USART_DATA_9BITS;
                stop_bits = USART_STOP_1_BIT;
                parity = USART_PARITY_ODD;
      }
      else
      {
                dat_bits = USART_DATA_9BITS;
                stop_bits = USART_STOP_1_BIT;
                parity = USART_PARITY_EVEN;
      }

      // rtu timer
      if (ulBaudRate > 19200)
      {
                qc_obj.tim_sv = 3;
      }
      else
      {
                qc_obj.tim_sv = (com_timer_cal(ulBaudRate, (35 * 11 + 9) / 10, 300, 12000) + 99) / 100;
      }

      usart_init(qc_port, ulBaudRate, dat_bits, stop_bits);
      usart_parity_selection_config(qc_port, parity);
      usart_enable(qc_port, TRUE);

      nvic_irq_set(qc_uart_irqn, 0x00, 1);

      qc_tx1_rx0_enable(0);

      UART_TX_EN();
}
中断处理:
/*****************************************************************************
* @brief UART interrupt routine.
* @param   none
* @returnnone
*****************************************************************************/
void qc_isr()
{
      volatile uint32_t IntSt;
      volatile uint8_t Data;

      IntSt = qc_port->sts;

      if (IntSt & USART_RDBF_FLAG)
      {
                Data = UART_RCV_DAT();

                if ((IntSt & UART_RX_ERR_FLAG) != 0)
                {
                        if (qc_obj.rx_cnt >= 1)
                        {
                              qc_obj.err_hal = 1;
                        }
                        UART_RX_ERR_CLR();
                }

                qc_data_rcv(&qc_obj, Data);
      }
      else if ((qc_obj.tx_size <= qc_obj.tx_cnt) && (IntSt & USART_TDC_FLAG))
      {
                qc_send_end(&qc_obj);
                qc_tx1_rx0_enable(0);
                UART_TX_TC_CLR();
      }
      else if (IntSt & USART_TDBE_FLAG)
      {
                if (qc_data_send(&qc_obj, qc_rtu_byte_send, 1))
                {
                        UART_TX_TC_EN();
                }
      }
      else
      {
      }
}
U3主站命令:
void qc_init(void)
{
      // master config
      qc03_Init(QC_MODE_MASTER, 9600, MB_PAR_NONE);
      mb.qc03.os_event_send = mb_os_send;

      mcmd.id = 1;
      mcmd.wdat = &mb_input.uval;
      mcmd.rdat = &mb_input.uval;
      mcmd.wa = 0;
      mcmd.wn = 96;
      mcmd.ra = 0x1800;
      mcmd.rn = 1;
      mcmd.callback = qc_callback;
      mcmd.attr = QC_MB_ATTR_HOLD_MW;
      mqc_stc_cmd_req(&mb.qc03, 0, &mcmd);
      
      mcmd.wdat = &mb_input.uval;
      mcmd.wa = 96;
      mcmd.wn = 96;
      mqc_stc_cmd_req(&mb.qc03, 1, &mcmd);

      // slave config
      qc02_Init(QC_MODE_SLAVE, 9600, MB_PAR_NONE);
      mb.qc02.os_event_send = mb_os_send;

      mcmd.id = 1;
      mcmd.wdat = &mb_input.uval;
      mcmd.rdat = &mb_input.uval;
      mcmd.wa = 16;
      mcmd.wn = 16;
      mcmd.ra = 0;
      mcmd.rn = 8;
      mcmd.callback = qc_callback;
      mcmd.attr = QC_MB_ATTR_HOLD_MW;
      mqc_stc_cmd_req(&mb.qc02, 0, &mcmd);
      mqc_stc_cmd_req(&mb.qc02, 1, &mcmd);
}
测试时,将评估板PA2连接PB10, PA3连接PB11可完成两个端口通信,运行结果如下:


为方便运行时观察,可以显示串口通信信息到OLED显示屏,效果如下:

任务资源信息:

至此,modbus移植测试成功,可以用来连接各种modbus接口的传感器和PLC设备了。

下面附上测试代码:

编译环境:IAR EW for Arm 9.40


wangwu1976@ 发表于 2024-1-24 13:48

做得真不错,顶一个
页: [1]
查看完整版本: 【AT-START-F423测评】多通道MODBUS测试