发新帖本帖赏金 20.00元(功能说明)我要提问
返回列表
打印
[AT32F423]

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

[复制链接]
1067|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aple0807|  楼主 | 2023-10-29 10:39 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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},
串口初始化:

/*****************************************************************************
* [url=home.php?mod=space&uid=247401]@brief[/url]           com modle init .
* @param   none
* [url=home.php?mod=space&uid=266161]@return[/url]  none
* [url=home.php?mod=space&uid=72445]@[/url] 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();
}
中断处理:
/*****************************************************************************
* [url=home.php?mod=space&uid=247401]@brief[/url] UART interrupt routine.
* @param   none
* [url=home.php?mod=space&uid=266161]@return[/url]  none
*****************************************************************************/
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[0].uval;
        mcmd.rdat = &mb_input[0].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[0].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[0].uval;
        mcmd.rdat = &mb_input[0].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设备了。

下面附上测试代码:
AT32F423_EVAL.rar (4.59 MB)
编译环境:IAR EW for Arm 9.40


使用特权

评论回复

打赏榜单

ArterySW 打赏了 20.00 元 2024-01-24
理由:作品优秀

沙发
wangwu1976@| | 2024-1-24 13:48 | 只看该作者
做得真不错,顶一个

使用特权

评论回复
发新帖 本帖赏金 20.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

309

帖子

2

粉丝