aple0807 发表于 2022-3-16 16:21

【GD32L233C-START评测】MODBUS测试

<p>&nbsp;&nbsp;&nbsp;&nbsp;疫情期间隔离了,没事做,今天在L233测试了下MODBUS。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp; L233的串口和其他系列的串口状态标志管理有些差别。比如帧错误,校验错误,TC标志需要手动清除,另外发送空中断标志在初始化后是0,发数据时单一像其他MCU那样开中断在中断中发数据是不行的,需要先发送一个数据产生发送空标志,然后开中断,剩余的数据在中断里面完成。</p>

<p>&nbsp;</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;为方便操作,定义下面一组串口操作宏:</p>

<pre>
<code>// 数据收发
#define UART_SEND_DAT(dat) USART_TDATA(mbPORT) = dat
#define UART_RCV_DAT() USART_RDATA(mbPORT)
       
// 缓冲状态
#define UART_RX_NE_ST() ((USART_STAT(mbPORT)&amp; USART_STAT_RBNE) != 0)        //rx not empty
#define UART_TX_NF_ST() (0 != (USART_STAT(mbPORT)&amp; USART_STAT_TBE))                //tx not full
#define UART_TX_TC_ST() (USART_STAT(mbPORT) &amp; (USART_STAT_TC))
#define UART_TX_TC_CLR() USART_INTC(mbPORT) = USART_INTC_TCC

// 接收控制
#define UART_RX_EN()USART_CTL0(mbPORT) |= USART_CTL0_UEN | USART_CTL0_REN
#define UART_RX_INT_EN()USART_CTL0(mbPORT) |= USART_CTL0_UEN | USART_CTL0_REN | USART_CTL0_RBNEIE
#define UART_RX_INT_DIS() USART_CTL0(mbPORT) &amp;= ~(USART_CTL0_REN | USART_CTL0_RBNEIE)

// 发送控制
#define UART_TX_EN()USART_CTL0(mbPORT) |= USART_CTL0_UEN | USART_CTL0_TEN
#define UART_TX_INT_EN()USART_CTL0(mbPORT) |= USART_CTL0_UEN | USART_CTL0_TBEIE | USART_CTL0_TEN
#define UART_TX_INT_DIS() USART_CTL0(mbPORT) &amp;= ~(USART_CTL0_TBEIE | USART_CTL0_TCIE)

// 错误标志及清除
#define UART_RX_ERR_FLAG (USART_STAT_PERR | USART_STAT_FERR)
#define UART_RX_ERR_CLR() USART_INTC(mbPORT) = USART_INTC_PEC | USART_INTC_FEC
</code></pre>

<p>modbus测试主要是串口收发管理程序的移植:<br />
应用层初始化,调用扫描即可:</p>

<pre>
<code>/******************************************************************************
* @brief Slave device handle.
*               
* @param   none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void modbus_task(const void *argv)
{
        mb_cmd_buff_type mcmd;

        mb_obj_init(&amp;mb.obj00);

        //master config
        mb00_Init(MB_RTU_SLAVE, mb_baud_tab, MB_PAR_NONE);
        mb.obj00.slave_id = 1;
        mb.obj00.rtu_master_delay_set = 3;
        mb.obj00.rcv_end_handle_comp = rcv_end_handle_comp;
        mb.obj00.os_event_send = mb_os_send;
        mb.obj00.os_event_base = 2 &lt;&lt; 4;
        mb.obj00.rtu_length_cut = 1;

        //cmd config
        mcmd.device_id = 0;
        mcmd.cmd = FUN_CODE_READ_COILS;
        mcmd.dat = mb_tst.pv_w;
        mcmd.dat_addr = 0;
        mcmd.amount = 48;
        mcmd.call_back = 0;
        mb.obj00.api-&gt;stc_cmd_req(0, &amp;mcmd);

        mcmd.cmd = FUN_CODE_READ_DISCRETE;
        mb.obj00.api-&gt;stc_cmd_req(1, &amp;mcmd);

        mcmd.cmd = FUN_CODE_W_R_MULTIPLE_REG;
        mb.obj00.api-&gt;stc_cmd_req(2, &amp;mcmd);

        mcmd.cmd = FUN_CODE_W_R_MULTIPLE_REG;
        mb.obj00.api-&gt;stc_cmd_req(3, &amp;mcmd);

        mcmd.cmd = FUN_CODE_WRITE_MULTIPLE_REG;
        mb.obj00.api-&gt;stc_cmd_req(4, &amp;mcmd);

        mcmd.cmd = FUN_CODE_WRITE_MULTIPLE_COIL;
        mb_tst.pv_w = 0;
        mb.obj00.api-&gt;stc_cmd_req(5, &amp;mcmd);

        //task handle
        for (;;)
        {
                osEvent event;

                // wait modbus event
                event = osSignalWait(0, 1000);

                (void)event;

                mb_poll(&amp;mb.obj00);

                mb_tst.obj_size = sizeof(mb.obj00);
        }
}</code></pre>

<p>本测试板子作为从机,测试结果如下</p>

<p></p>

<p>附上测试工程:</p>

<p></p>

freebsder 发表于 2022-3-16 18:43

<p>为啥不可以在中断中发送数据?有点怪异。</p>

aple0807 发表于 2022-3-16 19:16

freebsder 发表于 2022-3-16 18:43
为啥不可以在中断中发送数据?有点怪异。

<p>仅首次发送的时候要先发一字节产生TBF标志,剩余的在中断里面发。这是串口初始化后该标志为0导致的,其他MCU的该标志在初始化后是1,直接开中断就可以响应。</p>
页: [1]
查看完整版本: 【GD32L233C-START评测】MODBUS测试