日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

单片机shell命令_MCU调试大法:使用串口实现简单shell功能

發布時間:2023/12/10 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单片机shell命令_MCU调试大法:使用串口实现简单shell功能 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MCU調試大法:使用串口實現簡單shell功能

[復制鏈接]

MCU程序調試方法有很多,比如軟/硬件仿真、添加數據打印等。

像Keil?MDK就支持不少單片機的軟件仿真,在沒有拿到單片機的情況下,就可以先仿真調試部分功能,查看代碼邏輯是否正確。硬件仿真則需要借助仿真器,如調試Cortex內核MCU常用的J-Link/ST-Link等。通過watch窗口可以查看變量的值:

在代碼中添加數據的打印,則需要借助MCU的串口功能,將運行時的關鍵數據通過串口打印至PC,便于觀察。這是我調試時非常喜歡使用的一個功能,因為需要打印哪些數據完全自主可控,而且可以做到基本不影響程序正常運行。

這里順便把如何使用printf的方法講一下,比較簡單,會的同學可以直接略過:

/@@* 頭文件不能少 */

#include <stdio.h>

/@@* 平臺的選擇 */

#ifdef __GNUC__

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /@@* __GNUC__ */

PUTCHAR_PROTOTYPE

{

/@@* 這里只需要實現一個字符ch的發送即可,以下以ST為例 */

HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);

return ch;

}

可交互的調試方法—shell

有了串口數據打印,尋找BUG方便了不少;但是隨著使用場景的增多:比如我需要在某個時刻打印某些數據、需要控制程序進入某個分支、調試算法時需要經常修改某些變量的值。此時光有打印就不行了,我需要一個可以實時和MCU進行交互的系統,那就是shell。

這里介紹一個體積極小的嵌入式shell,功能如下:

命令自動補全,使用tab鍵補全命令

命令長幫助,使用help [command]顯示命令長幫助

長幫助補全,輸入命令后雙擊tab鍵補全命令長幫助指令

快捷鍵,支持使用Ctrl + A~Z組合按鍵直接調用函數

shell變量,支持在shell中查看和修改變量值,支持變量作為命令參數

開始移植

1. 下載源碼并添加至工程中:

360截圖20191106140620843.jpg (5.14 KB, 下載次數: 0)

2019-11-6 14:06 上傳

360截圖20191106140437649.jpg (11.25 KB, 下載次數: 2)

2019-11-6 14:06 上傳

算上h文件,也就5個。

2. 初始化shell

定義shell全局實體:

SHELL_TypeDef shell;

在main中初始化,這里需要提供write函數,即字符發送函數:

/@@* 初始化shell */

shell.read = NULL; //采用中斷方式,所以不需要提供read方法

shell.write = user_shellWrite;

shellInit(&shell);

/@@* shell write定義 */

void user_shellWrite(const char ch)

{

/@@* 實現一個字符ch的發送功能,使用阻塞方式發送 */

HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);

}

3. shell調用

在串口接收中斷中,調用shellHandler處理函數:

void USART1_IRQHandler(void)

{

HAL_UART_IRQHandler(&huart1);

//將收到的字符實時送入shell處理

shellHandler(&shell, uart1_it_buf);

HAL_UART_Receive_IT(&huart1, (uint8_t *)&uart1_it_buf, 1);

}

4. 配置

將SHELL_DISPLAY_RETURN關閉,不然會打印shell函數返回值;SHELL_USING_CMD_EXPORT則根據個人喜好來,我這里將其關閉,所以以下將使用命令表來添加命令:

/@@**

* ?是否顯示命令調用函數返回值

* 使能此宏,則每次調用shell命令之后會以整形和十六進制的方式打印函數的返回值

*/

#define SHELL_DISPLAY_RETURN 0

/@@**

* @brief 是否使用命令導出方式

* 使能此宏后,可以使用`SHELL_EXPORT_CMD()`或者`SHELL_EXPORT_CMD_EX()`

* 定義shell命令,關閉此宏的情況下,需要使用命令表的方式

*/

#define SHELL_USING_CMD_EXPORT 0

5. 添加命令

因為定義了SHELL_USING_CMD_EXPORT為0,所以我們使用命令表來添加命令。在shell.c中,這里我們可以看到默認實現了兩個命令help和cls:

const SHELL_CommandTypeDef shellDefaultCommandList[] =

{

SHELL_CMD_ITEM_EX(help, shellHelp, command help, help [command] --show help info of command),

SHELL_CMD_ITEM(cls, shellClear, clear command line),

/@@* 在這里按照格式添加自己的命令,如顯示版本 */

SHELL_CMD_ITEM(version, shell_showVersion, show current version),

};

shell_showVersion的實現,可以在其他C文件中實現

/@@**

* @brief shell顯示當前軟件版本

*

*/

void shell_showVersion(void)

{

SHELL_TypeDef *shell = shellGetCurrent();

if (!shell)

{

return;

}

shellDisplay(shell, "\r\n V1.0.0\r\n");

shellDisplay(shell, "\r\n Build: "__DATE__" "__TIME__"\r\n");

return;

}

6. run

實際效果如下:

按TAB可以顯示所有命令,在輸入命令時按TAB還可以自動補全。

其他

這里只是完成了最基礎的移植工作,還有一些高級的功能就等著大家自行摸索啦。

有了shell調試起來肯定如虎添翼,呼呼哈哈!

還有一點,給客戶演示demo的時候,逼格也高了很多,哈哈哈!

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的单片机shell命令_MCU调试大法:使用串口实现简单shell功能的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。