Command Line Interface - CLI via UART

前言

製作一個UART的CLI模版,這只是一個最基本的架構,功能會依需求持續修改



操作環境

  • Board:32F072BDISCOVERY
  • IDE:STM32CubeIDE
  • Code:STM32CubeMX

MCU I/O配置

  • UART:TX(PA9),RX(PA10)

1. STM32CubeMX

勾選USART1,選 Asynchronous,bardrate:115200 bps

這裡的USART1不是公板上內建的介面,須要另外搭配UART模組


勾選中斷功能


2. STM32CubeIDE

在main.c加入下列程式

main.c

/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */

完善 printf 指令

/* USER CODE BEGIN PV */
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
  return ch;
}
/* USER CODE END PV */

CLI函式所需用到的變數 buffer

/* USER CODE BEGIN PFP */
uint8_t uart_rx[2];
char	cli_data[80];
char 	*cli_pointer = cli_data;
uint8_t	cli_key_enter;
/* USER CODE END PFP */

CLI函式

/* USER CODE BEGIN 0 */
void CLI(void)
{
	uint8_t values[10];
	uint8_t i = 0;
	char *token;
//	extern USBD_HandleTypeDef hUsbDeviceFS;

	if(cli_key_enter != 1) return;
	cli_key_enter = 0;

	token = strtok(cli_data, " ");
//    while (token != NULL) {
//        //printf("%s\n", token);
//        token = strtok(NULL, " ");
//    }
	while(token != NULL)
	{
		//values[i++] = atoi( token );
		values[i++] = strtol(token, NULL, 16);
		token = strtok(NULL, " ");
	}

	if(i>0)
	{
//		USBD_HID_SendReport(&hUsbDeviceFS,values, i);
//		HAL_Delay(15);
//		memset(values, 0, i);
//		USBD_HID_SendReport(&hUsbDeviceFS,values, i);
//		HAL_Delay(15);
	}else{
		printf("--- CLI console ---\n\r");
		printf("Key in multi hex values A0 00 10 and press ENTER to execute\n\r");
		printf("-------------------\n\r");
		printf("\n");
	}
	cli_pointer = cli_data;
	memset(cli_data, 0, sizeof(cli_data));
}
/* USER CODE END 0 */

main loop

UART的中斷接收 HAL_UART_Receive_IT 要先執行一次

int main(void)
{
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart1, uart_rx, 1);
  printf("Halo CLI\r\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	CLI();
  }
  /* USER CODE END 3 */
}

UART接收中斷程序

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_Receive_IT(&huart1, uart_rx, 1);
	HAL_UART_Transmit(&huart1, uart_rx, 1, HAL_MAX_DELAY);

	switch(uart_rx[0])
	{
	case '\r'://"Enter 0x13"
		printf("\n");
		cli_key_enter = 1;
		break;
	case 0x7F://"backspace"
		if(cli_pointer > cli_data) cli_pointer--;
		break;
	case 0x1B://"ESC"
		cli_pointer = cli_data;
		printf("\r");
		break;
	default:
		if((cli_pointer - cli_data) >=80) cli_pointer = cli_data;
		*(cli_pointer++) = (char)uart_rx[0];
		break;
	}
//	int size = (cli_pointer) - (cli_data);
}
/* USER CODE END 4 */


3. 成果

上電後先列印出"Halo CLI"

在沒有任何輸入時按下 Enter 則顯示CLI內容

可以輸入16進制的數值;但沒有任何功能

留言

2024

11-27SPI Flash 操作 (Read/Write/Erase)
11-19Rotary Encoder Switch 旋轉編碼開關
11-14Command Line Interface - CLI via UART
11-14【STM32】USB HID - Volume Control
11-13【STM32】USB Custom HID
11-12【STM32】USB HID Keyboard + Mouse
11-12【STM32】USB HID Keyboard
11-12【STM32】USB HID Mouse
10-15SSD1306 128x64 OLED 【五】Wokwi Animator
09-2432F429IDISCOVERY - - LTDC [3] + FMC (SDRAM) + FatFS
09-2432F429IDISCOVERY - - LTDC [2] + FMC (SDRAM)
09-20STM32 + FatFs + SD card via SPI【三】FatFS指令操作II
09-19STM32 + FatFs + SD card via SPI【二】FatFS指令操作
09-18STM32 + FatFs + SD card via SPI【一】移植FatFS
09-0232F429IDISCOVERY - - LTDC [1]
04-17SSD1306 128x64 OLED 【四】Adafruit / GFX Library
04-17Arduino - Serial Plotter繪圖儀
04-16SSD1306 128x64 OLED 【三】
04-15SSD1306 128x64 OLED 【二】 Datasheet
04-12SSD1306 128x64 OLED 【一】I2C版本
03-20【freeRTOS】vTaskDelay 與 vTaskDelayUntil 的差異
03-19【freeRTOS】API功能列表
03-18【freeRTOS】Day1
03-08MBR和Blank project的差別
03-05刪除註冊檔registry的資料
02-27DFU over Bluetooth Low Energy
02-27nRF Util - 使用手冊
02-26nRF Command Line Tools
02-20建立BootLoader settings
02-19Secure DFU packet (ZIP) build 建立含袐鑰的Zip檔
02-19Secure DFU via BLE
02-19Secure DFU via UART
02-16nRF Util 安裝
01-16nRF52840 ic升級成nRF52840 Dongle的程式

2023

11-21[ SEGGER Embedded Studio ] 新增header files
11-21[ SEGGER Embedded Studio ] 編譯nRF52840時遇到的問題
11-07Arduino Nano ESP32 - Debugging除錯模式
11-03Git快速入手 - 使用Git GUI
10-30Git快速入手 - 使用Git Bash
10-12程式碼高亮顯示 -- google-code-prettify

2022

11-30[EZ-PD] CCG6DF CCG6SF的Host SDK遇到編譯錯誤(一)

2019

05-27[ Eagle PCB ] 合板成品
05-23#CASE_001_USB_TOOL_RL78_G12
05-22[ Eagle PCB ] 初次洗板
05-21[ Eagle PCB ] Panelize 併板
05-20[ Eagle PCB ] 建立自己的Library及元件
05-20[ Eagle PCB ] 添加library及元件
05-20[ Eagle PCB ] Introduce

2018

04-25[ TCP test Tool ] 好用的TCP Server/Client工具
01-16RZ/A1H -[0]- Renesas RZ/A1H YR0K77210S009BE BSP環境架設

2017

12-11EZ USB Suit使用JLink online debug FX3
10-20RL78 -[12]- CS+_CACX_Lab5_LowPower mode
10-16RL78 -[11]- CS+_CACX_Lab4_ADC_溫度感測
10-13RL78 -[10]- CS+_CACX_Lab4_ADC_內部參考電壓
10-13RL78 -[9]- CS+_Lab3_I2C + MPU6050
10-13RL78 -[8]- CS+_Lab2_Uart transmit
10-12RL78 -[7]- Renesas Flash Programmer 獨立燒錄軟體
10-12RL78 -[6]- CS+_雜記
10-12RL78 -[5]- CS+_tracking variables on debug mode
10-12RL78 -[4]- CS+_顯示ROM與RAM的使用size
10-12RL78 -[3]- CS+_Lab1_Led blinking
10-12RL78 -[2]- CS+專案建立
10-12RL78 -[1]- 開發環境介紹
10-06ESP-01 -[0]- 硬體設置
10-06LinkIt 7688 program Renesas RL78/G12 by 1-wire
10-06LinkIt Smart 7688 -[3]- Build the firmware from source codes
10-06LinkIt Smart 7688 -[2]- 使用UART進入bootloader / kernel console
10-06LinkIt Smart 7688 -[1]- 使用SSH連接kernel console
10-06LinkIt Smart 7688 -[0]- 初次使用
07-14LinkIt Smart 7688 -[9]- Using MRAA SPI in Python
07-13LinkIt Smart 7688 -[8]- Using MRAA UART in Python
07-12LinkIt Smart 7688 -[7]- Using MRAA I2C in Python
07-12LinkIt Smart 7688 -[6]- Using MRAA PWM in Python
07-12LinkIt Smart 7688 -[5]- Using MRAA GPIO in Python
07-10LinkIt Smart 7688 -[4]- 雜記
06-29輕乳酪蛋糕 Cotton Cheesecake
06-26VirtualBox 的 Ubuntu與Windows 共用資料夾

2015

04-29偵測USB PnP