I was quarantined during the epidemic and had nothing to do, so I tested MODBUS on L233 today.
The serial port status flag management of L233 is slightly different from that of other series. For example, the frame error, check error, and TC flag need to be cleared manually. In addition, the send empty interrupt flag is 0 after initialization. When sending data, it is not possible to open an interrupt and send data in the interrupt like other MCUs. You need to send a data first to generate the send empty flag, then open the interrupt, and the remaining data is completed in the interrupt.
For easy operation, define the following set of serial port operation macros:
// 数据收发
#define UART_SEND_DAT(dat) USART_TDATA(mbPORT) = dat
#define UART_RCV_DAT() USART_RDATA(mbPORT)
// 缓冲状态
#define UART_RX_NE_ST() ((USART_STAT(mbPORT)& USART_STAT_RBNE) != 0) //rx not empty
#define UART_TX_NF_ST() (0 != (USART_STAT(mbPORT)& USART_STAT_TBE)) //tx not full
#define UART_TX_TC_ST() (USART_STAT(mbPORT) & (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) &= ~(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) &= ~(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
Modbus testing is mainly the transplantation of the serial port transceiver management program:
application layer initialization, call scanning:
/******************************************************************************
* [url=home.php?mod=space&uid=159083]@brief[/url] Slave device handle.
*
* @param none
*
* [url=home.php?mod=space&uid=784970]@return[/url] none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void modbus_task(const void *argv)
{
mb_cmd_buff_type mcmd;
mb_obj_init(&mb.obj00);
//master config
mb00_Init(MB_RTU_SLAVE, mb_baud_tab[MB_BAUD_115200], 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 << 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->stc_cmd_req(0, &mcmd);
mcmd.cmd = FUN_CODE_READ_DISCRETE;
mb.obj00.api->stc_cmd_req(1, &mcmd);
mcmd.cmd = FUN_CODE_W_R_MULTIPLE_REG;
mb.obj00.api->stc_cmd_req(2, &mcmd);
mcmd.cmd = FUN_CODE_W_R_MULTIPLE_REG;
mb.obj00.api->stc_cmd_req(3, &mcmd);
mcmd.cmd = FUN_CODE_WRITE_MULTIPLE_REG;
mb.obj00.api->stc_cmd_req(4, &mcmd);
mcmd.cmd = FUN_CODE_WRITE_MULTIPLE_COIL;
mb_tst.pv_w[0] = 0;
mb.obj00.api->stc_cmd_req(5, &mcmd);
//task handle
for (;;)
{
osEvent event;
// wait modbus event
event = osSignalWait(0, 1000);
(void)event;
mb_poll(&mb.obj00);
mb_tst.obj_size = sizeof(mb.obj00);
}
}
This test board is used as a slave, and the test results are as follows
Attached is the test project:
software.rar
(1.83 MB, downloads: 85)
|