2022.08.25 - [프로그래밍/C] - C ] 명령 프롬프트 구현 (함수포인터 사용)
이전에 콘솔에서 구현했었던 명령 프롬프트를 가져와 STM32에서 UART로 Command Line Interface를 구현하고 간단하게 델타로봇을 제어해봤다.
cli.h
/*
* cli.h
*
* Created on: Sep 4, 2022
* Author: J
*/
#ifndef INC_CLI_H_
#define INC_CLI_H_
#define MAX_CMD_NUM 10
typedef int cmd_func(int argc, char* argv[]);
struct Command_List
{
char* cmd;
cmd_func* func;
char* help_str;
};
int cmd_torque(int argc, char* argv[]);
int cdm_pump(int argc, char* argv[]);
int cmd_conveyorBelt(int argc, char* argv[]);
int cmd_pick(int argc, char* argv[]);
int cmd_throw(int argc, char* argv[]);
void parse_input_string(char* input_string, int* argc, char* argv[]);
void cmd_handler(char* cmd);
#endif /* INC_CLI_H_ */
cli.c
/*
* cli.c
*
* Created on: Sep 4, 2022
* Author: Jo soo hyun
*
*
*/
#include "cli.h"
#include "main.h"
#include <stdio.h>
#include <string.h>
#include "stm32f4xx_hal.h"
extern UART_HandleTypeDef huart3;
#include "cmsis_os.h"
extern osSemaphoreId UPSemHandle;
extern osSemaphoreId DOWMSemHandle;
extern osSemaphoreId ReadPosSemHandle;
extern osSemaphoreId TorqueOnSemHandle;
extern osSemaphoreId TorqueOffSemHandle;
extern osSemaphoreId ThrowSemHandle;
extern osSemaphoreId PumpOnSemHandle;
extern osSemaphoreId PumpOffSemHandle;
extern osSemaphoreId ConveyorRightOnSemHandle;
extern osSemaphoreId ConveyorLeftOnSemHandle;
extern osSemaphoreId ConveyorOffSemHandle;
int _write(int file, char* p, int len){
HAL_UART_Transmit(&huart3, (uint8_t*)p, len, 10);
return len;
}
struct Command_List CmdList[] =
{
{"torque", cmd_torque, "on/off Torque"},
{"pump", cdm_pump, "on/off Pump"},
{"cvbelt", cmd_conveyorBelt, "on/off Conveyor Belt. right/left"},
{"pick", cmd_pick, "no option. End effector Down + Pump On + default position"},
{"throw", cmd_throw, "no option. Throw + default position"},
{0,0,0}
};
int cmd_torque(int argc, char* argv[])
{
if (argv[1] == NULL) {
printf("wrong command pattern. \n");
}
else {
if (!strcmp(argv[1], "on")) {
osSemaphoreRelease(TorqueOnSemHandle);
}
else if (!strcmp(argv[1], "off")) {
osSemaphoreRelease(TorqueOffSemHandle);
}
}
return 0;
}
int cdm_pump(int argc, char* argv[])
{
if (argv[1] == NULL) {
printf("wrong command pattern. \n");
}
else {
if (!strcmp(argv[1], "on")) {
osSemaphoreRelease(PumpOnSemHandle);
}
else if (!strcmp(argv[1], "off")) {
osSemaphoreRelease(PumpOffSemHandle);
}
}
return 0;
}
int cmd_conveyorBelt(int argc, char* argv[])
{
if (argv[1] == NULL) {
printf("wrong command pattern. \n");
}
else {
if (!strcmp(argv[1], "on")) {
if (argv[2] == NULL) {
printf("wrong command pattern. \n");
}
else {
if (!strcmp(argv[2], "right")) {
osSemaphoreRelease(ConveyorRightOnSemHandle);
}
else if (!strcmp(argv[2], "left")) {
osSemaphoreRelease(ConveyorLeftOnSemHandle);
}else {
printf("wrong command pattern. \n");
}
}
}
else if (!strcmp(argv[1], "off")) {
osSemaphoreRelease(ConveyorOffSemHandle);
}
}
return 0;
}
int cmd_pick(int argc, char* argv[])
{
printf("pick up item on the conveyor belt. \n");
return 0;
}
int cmd_throw(int argc, char* argv[])
{
printf("throw item away \n");
return 0;
}
void parse_input_string(char* input_string, int* argc, char* argv[])
{
int found_arg = 1;
int argn = 0;
while (*input_string)
{
if (*input_string == '\n') {
*input_string = '\0';
break;
}
if (*input_string == ' ') {
found_arg = 1;
*input_string = '\0';
}
else if (found_arg) {
argv[argn++] = input_string;
found_arg = 0;
}
input_string++;
}
*argc = argn;
}
void cmd_handler(char* cmd)
{
struct Command_List* pCmdList = CmdList;
uint32_t command_found = 0;
int argc;
char* argv[MAX_CMD_NUM] = { 0, };
parse_input_string(cmd, &argc, argv);
if (argc)
{
while (pCmdList->cmd)
{
if (!strcmp((const char*)pCmdList->cmd, (const char*)cmd))
{
command_found = 1;
pCmdList->func(argc, argv);
break;
}
++pCmdList;
}
}
if (command_found == 0) printf("command not found!\n");
}
UART 수신부분
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART3){
if(rx3_data != '\n' && bufindex < BUFSIZE)
rx3buf[bufindex++] = rx3_data;
else {
cmd_handler((char*)rx3buf);
char temp[4]={0,};
sprintf(temp, ">> ");
HAL_UART_Transmit_IT(&huart3, (uint8_t*)temp, sizeof(temp));
memset(rx3buf,0,sizeof(rx3buf));
bufindex=0;
}
HAL_UART_Receive_IT(&huart3, &rx3_data, 1);
}
}
CLI는 나중에 매우 유용하게 쓸 수 있을거 같아서 나중에 시간이 있을 때 조금 손보고 재활용이 가능하도록 헤더와 소스파일을 만들어두려고 한다.
일단은 콜백함수 내에서 처리하게 해놨는데 나중에 처리하는 태스크를 따로 둘 것이다.
CLI만 테스트해본 프로젝트 파일
https://github.com/joeteo/uart_cli_test
그리고 이전에 했던 납땜이 너무 조악한것 같아서 공책에 회로를 그리고 보면서 다시 납땜을 했다.
'임베디드 개발 > STM32 (ARM Cortex-M)' 카테고리의 다른 글
STM32 + MFC ] 델타 로봇 티칭 시스템 구현, 파일입출력 기능 사용 티칭 데이터 관리, 쓰레드 활용 반복작업 수행 (0) | 2022.09.19 |
---|---|
STM32 + MFC ] 델타 로봇, RTOS 구조 변경 + 슬라이더 컨트롤을 통한 좌표 이동 제어 (7) | 2022.09.14 |
STM32 ] 델타로봇과 MFC 연동 + 컨베이어 벨트 추가 (4) (0) | 2022.08.28 |
STM32 ] USB CDC (Virtual Port Com) 사용하기 (0) | 2022.08.26 |
STM32 ] 역기구학(Inverse kinematics)을 통한 델타로봇 제어 (3) (0) | 2022.08.22 |