4.14 C99 Modbus
개요
C99 Modbus 는 두 계층으로 나뉩니다. ArmHandle* 는 SDK 세션을 담당하고, ArmModbusSlaveHandle* 는 특정 슬레이브 컨텍스트를 담당합니다.
권장 호출 순서
| 단계 | 인터페이스 | 설명 |
|---|---|---|
| 1 | Arm_Connect | 로봇 세션을 생성합니다. |
| 2 | Arm_Modbus_GetParam | 필요에 따라 대상 채널의 시리얼 포트 파라미터를 읽습니다. |
| 3 | Arm_Modbus_GetSlave | 슬레이브 핸들을 생성합니다. 원격 슬레이브 상태는 이후 읽기/쓰기 결과로 확인합니다. |
| 4 | Arm_ModbusSlave_Read* / Arm_ModbusSlave_Write* | 코일, holding register, discrete input, input register에 대해 읽기/쓰기를 수행합니다. |
| 5 | Arm_ModbusSlave_SerialSend / Arm_ModbusSlave_SerialReceive | 필요에 따라 시리얼 포트 패스스루를 사용합니다. |
| 6 | Arm_ModbusSlave_Destroy | 슬레이브 핸들을 폐기합니다. |
인터페이스 시그니처
Arm_Modbus_GetSlave
c
int Arm_Modbus_GetSlave(ArmHandle* h, int channel, int32_t slaveId, int32_t masterId, ArmModbusSlaveHandle** outSlave);| 항목 | 설명 |
|---|---|
| 설명 | Modbus 슬레이브 핸들을 생성합니다. |
| 요청 파라미터 | h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.channel : int , Modbus 채널 열거값입니다.slaveId : int32_t , Modbus 슬레이브 ID입니다.masterId : int32_t , 마스터 파라미터 ID 또는 채널 컨텍스트 ID입니다.outSlave : ArmModbusSlaveHandle** , 출력 Modbus 슬레이브 핸들이며 성공 후 호출자가 폐기해야 합니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_Modbus_GetParam
c
int Arm_Modbus_GetParam(ArmHandle* h, int channel, int32_t masterId, ArmSerialParams* outParams);| 항목 | 설명 |
|---|---|
| 설명 | Modbus 채널의 시리얼 포트 파라미터를 읽습니다. |
| 요청 파라미터 | h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.channel : int , Modbus 채널 열거값입니다.masterId : int32_t , 마스터 파라미터 ID 또는 채널 컨텍스트 ID입니다.outParams : ArmSerialParams* , 시리얼 포트 파라미터 출력 구조체 포인터입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_Modbus_SetParam
c
int Arm_Modbus_SetParam(ArmHandle* h, const ArmSerialParams* params, int32_t* outId);| 항목 | 설명 |
|---|---|
| 설명 | Modbus 채널의 시리얼 포트 파라미터를 설정합니다. |
| 요청 파라미터 | h : ArmHandle* , C99 세션 핸들이며 일반적으로 Arm_Create() 에서 생성합니다. 비즈니스 인터페이스는 먼저 연결에 성공해야 합니다.params : const ArmSerialParams* , 시리얼 포트 파라미터 구조체 포인터입니다.outId : int32_t* , 파라미터 기록 ID 출력 포인터입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_ModbusSlave_Destroy
c
void Arm_ModbusSlave_Destroy(ArmModbusSlaveHandle* slave);| 항목 | 설명 |
|---|---|
| 설명 | Modbus 슬레이브 핸들을 폐기합니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다. |
| 반환값 | 반환값 없음 |
Arm_ModbusSlave_IsValid
c
int Arm_ModbusSlave_IsValid(ArmModbusSlaveHandle* slave);| 항목 | 설명 |
|---|---|
| 설명 | Modbus 슬레이브 핸들이 유효한지 확인합니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다. |
| 반환값 | 1 은 핸들이 유효함을, 0 은 핸들이 이미 무효화되었음을 의미합니다. slave == NULL 이거나 예외 상황이면 오류 코드를 반환합니다. |
Arm_ModbusSlave_GetParam
c
int Arm_ModbusSlave_GetParam(ArmModbusSlaveHandle* slave, ArmSerialParams* outParams);| 항목 | 설명 |
|---|---|
| 설명 | 슬레이브 컨텍스트 기준으로 시리얼 포트 파라미터를 읽습니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.outParams : ArmSerialParams* , 시리얼 포트 파라미터 출력 구조체 포인터입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_ModbusSlave_SetParam
c
int Arm_ModbusSlave_SetParam(ArmModbusSlaveHandle* slave, const ArmSerialParams* params, int32_t* outId);| 항목 | 설명 |
|---|---|
| 설명 | 슬레이브 컨텍스트 기준으로 시리얼 포트 파라미터를 설정합니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.params : const ArmSerialParams* , 시리얼 포트 파라미터 구조체 포인터입니다.outId : int32_t* , 파라미터 기록 ID 출력 포인터입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_ModbusSlave_ReadCoils
c
int Arm_ModbusSlave_ReadCoils(ArmModbusSlaveHandle* slave, int32_t addr, int32_t num, int32_t* outArray, size_t maxCount, size_t* outCount);| 항목 | 설명 |
|---|---|
| 설명 | 코일을 읽습니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.addr : int32_t , 시작 주소입니다.num : int32_t , 읽을 개수입니다.outArray : int32_t* , 호출자가 할당하는 출력 배열입니다.maxCount : size_t , 출력 배열 용량이며 호출자가 최대 몇 개의 요소를 받을 수 있는지를 나타냅니다.outCount : size_t* , 출력 개수 포인터이며 성공 시 실제 개수를 기록합니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
| 비고 | 배열 출력은 호출자가 할당합니다. maxCount 는 용량을 나타내고, outCount 는 실제 개수를 반환합니다. |
Arm_ModbusSlave_WriteCoils
c
int Arm_ModbusSlave_WriteCoils(ArmModbusSlaveHandle* slave, int32_t addr, const int32_t* values, size_t count);| 항목 | 설명 |
|---|---|
| 설명 | 코일에 씁니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.addr : int32_t , 시작 주소입니다.values : const int32_t* , 쓸 값 배열입니다.count : size_t , 배열 요소 개수입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_ModbusSlave_ReadHoldingRegs
c
int Arm_ModbusSlave_ReadHoldingRegs(ArmModbusSlaveHandle* slave, int32_t addr, int32_t num, int32_t* outArray, size_t maxCount, size_t* outCount);| 항목 | 설명 |
|---|---|
| 설명 | holding register를 읽습니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.addr : int32_t , 시작 주소입니다.num : int32_t , 읽을 개수입니다.outArray : int32_t* , 호출자가 할당하는 출력 배열입니다.maxCount : size_t , 출력 배열 용량이며 호출자가 최대 몇 개의 요소를 받을 수 있는지를 나타냅니다.outCount : size_t* , 출력 개수 포인터이며 성공 시 실제 개수를 기록합니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
| 비고 | 배열 출력은 호출자가 할당합니다. maxCount 는 용량을 나타내고, outCount 는 실제 개수를 반환합니다. |
Arm_ModbusSlave_WriteHoldingRegs
c
int Arm_ModbusSlave_WriteHoldingRegs(ArmModbusSlaveHandle* slave, int32_t addr, const int32_t* values, size_t count);| 항목 | 설명 |
|---|---|
| 설명 | holding register에 씁니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.addr : int32_t , 시작 주소입니다.values : const int32_t* , 쓸 값 배열입니다.count : size_t , 배열 요소 개수입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_ModbusSlave_ReadDiscreteInputs
c
int Arm_ModbusSlave_ReadDiscreteInputs(ArmModbusSlaveHandle* slave, int32_t addr, int32_t num, int32_t* outArray, size_t maxCount, size_t* outCount);| 항목 | 설명 |
|---|---|
| 설명 | discrete input을 읽습니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.addr : int32_t , 시작 주소입니다.num : int32_t , 읽을 개수입니다.outArray : int32_t* , 호출자가 할당하는 출력 배열입니다.maxCount : size_t , 출력 배열 용량이며 호출자가 최대 몇 개의 요소를 받을 수 있는지를 나타냅니다.outCount : size_t* , 출력 개수 포인터이며 성공 시 실제 개수를 기록합니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
| 비고 | 배열 출력은 호출자가 할당합니다. maxCount 는 용량을 나타내고, outCount 는 실제 개수를 반환합니다. |
Arm_ModbusSlave_ReadInputRegs
c
int Arm_ModbusSlave_ReadInputRegs(ArmModbusSlaveHandle* slave, int32_t addr, int32_t num, int32_t* outArray, size_t maxCount, size_t* outCount);| 항목 | 설명 |
|---|---|
| 설명 | input register를 읽습니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.addr : int32_t , 시작 주소입니다.num : int32_t , 읽을 개수입니다.outArray : int32_t* , 호출자가 할당하는 출력 배열입니다.maxCount : size_t , 출력 배열 용량이며 호출자가 최대 몇 개의 요소를 받을 수 있는지를 나타냅니다.outCount : size_t* , 출력 개수 포인터이며 성공 시 실제 개수를 기록합니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
| 비고 | 배열 출력은 호출자가 할당합니다. maxCount 는 용량을 나타내고, outCount 는 실제 개수를 반환합니다. |
Arm_ModbusSlave_WriteInputRegs
c
int Arm_ModbusSlave_WriteInputRegs(ArmModbusSlaveHandle* slave, int32_t addr, const int32_t* values, size_t count);| 항목 | 설명 |
|---|---|
| 설명 | input register에 씁니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.addr : int32_t , 시작 주소입니다.values : const int32_t* , 쓸 값 배열입니다.count : size_t , 배열 요소 개수입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_ModbusSlave_SerialSend
c
int Arm_ModbusSlave_SerialSend(ArmModbusSlaveHandle* slave, const char* msg);| 항목 | 설명 |
|---|---|
| 설명 | 시리얼 포트 패스스루 데이터를 전송합니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.msg : const char* , 시리얼 포트 패스스루 전송 텍스트입니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
Arm_ModbusSlave_SerialReceive
c
int Arm_ModbusSlave_SerialReceive(ArmModbusSlaveHandle* slave, char* outBuf, size_t bufSize);| 항목 | 설명 |
|---|---|
| 설명 | 시리얼 포트 패스스루 데이터를 수신합니다. |
| 요청 파라미터 | slave : ArmModbusSlaveHandle* , Arm_Modbus_GetSlave() 에서 생성한 Modbus 슬레이브 핸들입니다.outBuf : char* , 호출자가 할당하는 출력 문자열 버퍼입니다.bufSize : size_t , 출력 버퍼 크기이며 끝의 \0 공간을 포함합니다. |
| 반환값 | STATUS_CODE 정수값입니다. 0 은 성공을 의미하며, 그 외 값은 상태 코드에 따라 처리합니다. |
| 비고 | 문자열 출력은 호출자가 제공한 버퍼를 사용하며, 버퍼가 부족하면 상태 코드에 따라 반환합니다. |
자주 사용하는 타입
ArmModbusChannel
| 열거값 | 값 | 설명 |
|---|---|---|
ARM_MODBUS_CHANNEL_CONTROLLER_TCP_TO_485 | 2 | 컨트롤러 TCP-to-485 채널 |
ARM_MODBUS_CHANNEL_WRIST_485_0 | 3 | 손목 485_0 채널 |
ARM_MODBUS_CHANNEL_WRIST_485_1 | 4 | 손목 485_1 채널 |
ARM_MODBUS_CHANNEL_CONTROLLER_485 | 5 | 컨트롤러 485 채널 |
ArmModbusParity
| 열거값 | 값 | 설명 |
|---|---|---|
ARM_MODBUS_PARITY_NONE | 78 | 패리티 없음, ASCII N |
ARM_MODBUS_PARITY_ODD | 79 | 홀수 패리티, ASCII O |
ARM_MODBUS_PARITY_EVEN | 69 | 짝수 패리티, ASCII E |
ArmSerialParams
| 필드 | 타입 | 설명 |
|---|---|---|
id | int32_t | 파라미터 기록 ID |
channel | int32_t | ArmModbusChannel 열거값 |
ip | char[128] | 대상 IP |
port | int32_t | 포트 |
baud | int32_t | 보드레이트 |
dataBit | int32_t | 데이터 비트 |
stopBit | int32_t | 정지 비트 |
parity | int32_t | ArmModbusParity 열거값 |
timeout | int32_t | timeout, 밀리초 |
포인터 및 버퍼 규칙
| 시나리오 | 반환 |
|---|---|
h == NULL 또는 slave == NULL | 오류 코드를 반환합니다. |
필수 out 포인터가 NULL | INVALID_PARAMETER 를 반환합니다. |
배열 읽기 시 outArray == NULL 이고 outCount != NULL | 개수만 되돌려 씁니다. |
| 배열 읽기 버퍼 부족 | BUFFER_TOO_SMALL 을 반환하고 outCount 를 0 으로 설정합니다. |
Arm_ModbusSlave_SerialReceive 의 bufSize == 0 | BUFFER_TOO_SMALL 을 반환합니다. |
SerialReceive 실패 및 outBuf 유효 | 빈 문자열을 씁니다. |
파라미터 및 수명 주기
| 항목 | 규칙 |
|---|---|
| 연결 전제 | 먼저 Arm_Connect() 가 성공해야 합니다. |
addr | 시작 주소는 addr >= 0 이어야 합니다. |
| 읽기 개수 | num 은 1..120 이어야 합니다. |
| 쓰기 개수 | count 는 1..1024 여야 합니다. |
| 주소 상한 | addr + 개수 - 1 은 65535 를 초과할 수 없습니다. |
values | count > 0 이면 비어 있으면 안 됩니다. |
| 슬레이브 핸들 | 이를 생성한 ArmHandle* 에 의존하므로 Arm_Disconnect() 를 넘어 재사용할 수 없습니다. |
outId | SetParam 성공 시 컨트롤러가 확인한 파라미터 기록 ID를 씁니다. |
동작 규칙:
Arm_Modbus_GetSlave()는 로컬 핸들을 생성합니다. 원격 슬레이브 상태는 이후 읽기/쓰기 결과로 확인합니다.Arm_ModbusSlave_IsValid()는 로컬 핸들이 여전히 유효한 세션에 바인딩되어 있는지 확인합니다. 원격 온라인 상태는 읽기/쓰기 결과로 확인합니다.Arm_Modbus_GetParam()은ARM_MODBUS_CHANNEL_CONTROLLER_TCP_TO_485채널에서masterId를 컨트롤러로 보냅니다. 다른 채널은 일반적으로masterId를 무시합니다.- 시리얼 포트 패스스루는 채널 기준으로 동작합니다.
slaveId/masterId는 일반 Modbus 세션 컨텍스트에 사용됩니다. - 읽기 인터페이스는 컨트롤러가 반환한 정수 배열을 반환합니다. 코일 값도 컨트롤러 결과대로 표시합니다.
- 쓰기 인터페이스는 주소 범위와 개수를 검증합니다. 각
values요소의 비즈니스 의미는 컨트롤러가 처리합니다.
실패 기준
| 시나리오 | 반환 |
|---|---|
| 슬레이브 핸들이 유효하지 않음 | INVALID_SESSION |
| 채널 열거값 또는 패리티 열거값이 올바르지 않음 | INVALID_PARAMETER |
addr < 0 | INVALID_PARAMETER |
num < 1 또는 num > 120 | INVALID_PARAMETER |
count < 1 또는 count > 1024 | INVALID_PARAMETER |
addr + 개수 - 1 > 65535 | INVALID_PARAMETER |
| 컨트롤러가 예상과 다른 데이터 구조를 반환 | OTHER_ERR |
최소 호출 예제
c
#include <stdio.h> // Modbus 조회 결과 출력을 위해 printf를 포함합니다.
#include "c_arm_api.h" // C99 SDK 최상위 헤더를 포함합니다.
int main(void) // 예제 프로그램 진입점
{ // 예제 main 함수 시작
ArmHandle* h = Arm_Create(); // C99 세션 핸들을 생성합니다.
ArmModbusSlaveHandle* slave = NULL; // Modbus 슬레이브 핸들 수신을 준비합니다.
int32_t coils[8] = {0}; // 코일 값 수신 버퍼를 준비합니다.
size_t outCount = 0U; // 실제 읽은 개수 수신 변수를 준비합니다.
if (h == NULL) { // 세션 핸들 생성 실패 여부를 확인합니다.
return 1; // 생성 실패 시 종료합니다.
} // 핸들 생성 검사 종료
if (Arm_Connect(h, "10.27.1.254", NULL) != 0) { // 컨트롤러 또는 라우팅 주소에 연결합니다.
Arm_Destroy(h); // 연결 실패 시 세션 핸들을 폐기합니다.
return 1; // 오류 코드를 반환합니다.
} // 연결 검사 종료
if (Arm_Modbus_GetSlave(h, ARM_MODBUS_CHANNEL_CONTROLLER_485, 1, 0, &slave) != 0) { // 컨트롤러 485 채널의 슬레이브 핸들을 생성합니다.
Arm_Disconnect(h); // 생성 실패 시 로봇 연결을 해제합니다.
Arm_Destroy(h); // 생성 실패 시 세션 핸들을 폐기합니다.
return 1; // 오류 코드를 반환합니다.
} // 슬레이브 핸들 생성 검사 종료
int ret = Arm_ModbusSlave_ReadCoils(slave, 0, 2, coils, 8, &outCount); // 주소 0부터 코일 값 2개를 읽습니다.
if (ret == 0) { // 코일 읽기 성공 여부를 확인합니다.
printf("coil_count=%zu\n", outCount); // 실제 읽은 개수를 출력합니다.
} // 코일 읽기 검사 종료
Arm_ModbusSlave_Destroy(slave); // 슬레이브 핸들을 폐기합니다.
Arm_Disconnect(h); // 로봇 연결을 해제합니다.
Arm_Destroy(h); // 세션 핸들을 폐기합니다.
return ret == 0 ? 0 : 1; // 읽기 결과에 따라 예제 상태를 반환합니다.
} // 예제 main 함수 종료시나리오 예제
아래 조각은 연결에 성공한 ArmHandle* h 가 이미 있다고 가정합니다. 파라미터 설정, 레지스터 쓰기, 시리얼 포트 패스스루는 현장 장비에 영향을 주므로 확인 후 실행하세요.
시리얼 포트 파라미터 조회 및 설정
c
ArmSerialParams params = {0}; // 시리얼 포트 파라미터 출력 구조체를 준비합니다.
int32_t savedId = 0; // 컨트롤러가 확인한 파라미터 기록 ID 수신을 준비합니다.
int getRet = Arm_Modbus_GetParam(h, ARM_MODBUS_CHANNEL_CONTROLLER_485, 0, ¶ms); // 컨트롤러 485 채널 파라미터를 조회합니다.
params.channel = ARM_MODBUS_CHANNEL_CONTROLLER_485; // 설정할 채널을 지정합니다.
/* int setRet = Arm_Modbus_SetParam(h, ¶ms, &savedId); */ // 시리얼 포트 파라미터 설정은 컨트롤러 설정을 변경하므로 확인 후 실행합니다.
(void)getRet; // 예제에서 조회 상태 코드를 유지합니다.
(void)savedId; // 예제에서 설정 출력 변수를 유지합니다.슬레이브 읽기/쓰기
c
int32_t values[4] = {0}; // 읽기 출력 버퍼를 준비합니다.
int32_t writeValues[2] = {1, 0}; // 코일에 쓸 값을 준비합니다.
size_t outCount = 0U; // 읽기 개수 수신을 준비합니다.
int coilsRet = Arm_ModbusSlave_ReadCoils(slave, 0, 2, values, 4, &outCount); // 코일을 읽습니다.
int holdingRet = Arm_ModbusSlave_ReadHoldingRegs(slave, 0, 2, values, 4, &outCount); // holding register를 읽습니다.
int discreteRet = Arm_ModbusSlave_ReadDiscreteInputs(slave, 0, 2, values, 4, &outCount); // discrete input을 읽습니다.
int inputRet = Arm_ModbusSlave_ReadInputRegs(slave, 0, 2, values, 4, &outCount); // input register를 읽습니다.
/* int writeCoilsRet = Arm_ModbusSlave_WriteCoils(slave, 0, writeValues, 2); */ // 코일 쓰기는 슬레이브 상태를 변경하므로 확인 후 실행합니다.
(void)coilsRet; // 예제에서 코일 읽기 상태 코드를 유지합니다.
(void)holdingRet; // 예제에서 holding register 읽기 상태 코드를 유지합니다.
(void)discreteRet; // 예제에서 discrete input 읽기 상태 코드를 유지합니다.
(void)inputRet; // 예제에서 input register 읽기 상태 코드를 유지합니다.슬레이브 컨텍스트 기준 파라미터 조회 및 시리얼 포트 패스스루
c
ArmSerialParams params = {0}; // 시리얼 포트 파라미터 출력 구조체를 준비합니다.
char recvBuf[1024] = {0}; // 시리얼 포트 패스스루 수신 버퍼를 준비합니다.
int valid = Arm_ModbusSlave_IsValid(slave); // 슬레이브 핸들이 여전히 유효한지 확인합니다.
int getRet = Arm_ModbusSlave_GetParam(slave, ¶ms); // 슬레이브 컨텍스트 기준으로 시리얼 포트 파라미터를 조회합니다.
/* int sendRet = Arm_ModbusSlave_SerialSend(slave, "010300000002"); */ // 시리얼 포트 패스스루 전송은 현장 버스에 접근하므로 확인 후 실행합니다.
/* int recvRet = Arm_ModbusSlave_SerialReceive(slave, recvBuf, sizeof(recvBuf)); */ // 시리얼 포트 패스스루 수신은 현장 데이터를 기다리므로 확인 후 실행합니다.
(void)valid; // 예제에서 유효성 검사 결과를 유지합니다.
(void)getRet; // 예제에서 조회 상태 코드를 유지합니다.예제 코드
cpp
#include <stdio.h>
#include <string.h>
extern "C" {
#include "c_arm_api.h"
}
int main(void)
{
// [ZH] 本示例直接在源码中写死连接地址,不解析命令行参数。
// [EN] This example hard-codes the connection addresses in the source code and does not parse command-line arguments.
// [ZH] 创建并连接 SDK 句柄。
// [EN] Create the SDK handle and connect to the robot.
ArmHandle* handle = Arm_Create();
if (handle == NULL) {
printf("[c99_modbus] 创建句柄失败 / Failed to create the handle\n");
return 1;
}
int ret = Arm_Connect(handle, "10.27.1.2", "10.27.1.102");
if (ret != 0) {
printf("[c99_modbus] 连接失败 / Connect failed, 状态码 / Status code: %d\n", ret);
Arm_Destroy(handle);
return 1;
}
printf("[c99_modbus] 机器人连接成功 / Robot connected successfully\n");
// [ZH] 准备主站串口参数并读取当前值。
// [EN] Prepare master serial params and read the current values.
ArmSerialParams masterParams = {0};
int32_t paramId = 0;
snprintf(masterParams.ip, sizeof(masterParams.ip), "127.0.0.1");
masterParams.channel = ARM_MODBUS_CHANNEL_CONTROLLER_485;
masterParams.id = 1;
masterParams.port = 502;
masterParams.baud = 9600;
masterParams.dataBit = 8;
masterParams.stopBit = 1;
masterParams.parity = ARM_MODBUS_PARITY_NONE;
masterParams.timeout = 1000;
ret = Arm_Modbus_GetParam(handle, ARM_MODBUS_CHANNEL_CONTROLLER_485, 0, &masterParams);
printf("[c99_modbus] GetParam 状态码 / GetParam status code: %d, channel=%d, baud=%d\n", ret, masterParams.channel, masterParams.baud);
ret = Arm_Modbus_SetParam(handle, &masterParams, ¶mId);
printf("[c99_modbus] SetParam 状态码 / SetParam status code: %d, id=%d\n", ret, paramId);
// [ZH] 获取从站句柄并顺序执行全部从站接口。
// [EN] Acquire the slave handle and execute all slave APIs in sequence.
ArmModbusSlaveHandle* slave = NULL;
ret = Arm_Modbus_GetSlave(handle, ARM_MODBUS_CHANNEL_CONTROLLER_485, 1, 0, &slave);
printf("[c99_modbus] GetSlave 状态码 / GetSlave status code: %d\n", ret);
if (slave != NULL) {
int valid = Arm_ModbusSlave_IsValid(slave);
printf("[c99_modbus] Slave_IsValid / Slave_IsValid: %d\n", valid);
int32_t values[8] = {0};
size_t valueCount = 0U;
ret = Arm_ModbusSlave_ReadCoils(slave, 0, 2, values, 8U, &valueCount);
printf("[c99_modbus] ReadCoils 状态码 / ReadCoils status code: %d, count=%zu\n", ret, valueCount);
int32_t writeCoils[2] = {1, 0};
ret = Arm_ModbusSlave_WriteCoils(slave, 0, writeCoils, 2U);
printf("[c99_modbus] WriteCoils 状态码 / WriteCoils status code: %d\n", ret);
ret = Arm_ModbusSlave_ReadHoldingRegs(slave, 0, 2, values, 8U, &valueCount);
printf("[c99_modbus] ReadHoldingRegs 状态码 / ReadHoldingRegs status code: %d, count=%zu\n", ret, valueCount);
int32_t holdingRegs[2] = {1, 2};
ret = Arm_ModbusSlave_WriteHoldingRegs(slave, 0, holdingRegs, 2U);
printf("[c99_modbus] WriteHoldingRegs 状态码 / WriteHoldingRegs status code: %d\n", ret);
ret = Arm_ModbusSlave_ReadDiscreteInputs(slave, 0, 2, values, 8U, &valueCount);
printf("[c99_modbus] ReadDiscreteInputs 状态码 / ReadDiscreteInputs status code: %d, count=%zu\n", ret, valueCount);
ret = Arm_ModbusSlave_ReadInputRegs(slave, 0, 2, values, 8U, &valueCount);
printf("[c99_modbus] ReadInputRegs 状态码 / ReadInputRegs status code: %d, count=%zu\n", ret, valueCount);
int32_t inputRegs[2] = {3, 4};
ret = Arm_ModbusSlave_WriteInputRegs(slave, 0, inputRegs, 2U);
printf("[c99_modbus] WriteInputRegs 状态码 / WriteInputRegs status code: %d\n", ret);
ret = Arm_ModbusSlave_SetParam(slave, &masterParams, ¶mId);
printf("[c99_modbus] Slave_SetParam 状态码 / Slave_SetParam status code: %d, id=%d\n", ret, paramId);
ret = Arm_ModbusSlave_GetParam(slave, &masterParams);
printf("[c99_modbus] Slave_GetParam 状态码 / Slave_GetParam status code: %d, baud=%d\n", ret, masterParams.baud);
ret = Arm_ModbusSlave_SerialSend(slave, "hello from c99 example");
printf("[c99_modbus] SerialSend 状态码 / SerialSend status code: %d\n", ret);
char recvBuf[256] = {0};
ret = Arm_ModbusSlave_SerialReceive(slave, recvBuf, sizeof(recvBuf));
printf("[c99_modbus] SerialReceive 状态码 / SerialReceive status code: %d, 内容 / Text: %s\n", ret, recvBuf);
Arm_ModbusSlave_Destroy(slave);
printf("[c99_modbus] 从站句柄已释放 / Slave handle destroyed\n");
}
// [ZH] 断开连接并销毁句柄。
// [EN] Disconnect and destroy the handle.
Arm_Disconnect(handle);
Arm_Destroy(handle);
printf("[c99_modbus] 示例结束 / Example finished\n");
return 0;
}