前言
恩智浦“FRDM-MCXN947”評測活動由安富利和與非網(wǎng)協(xié)同舉辦。本篇內(nèi)容由與非網(wǎng)用戶發(fā)布,已獲轉(zhuǎn)載許可。原文可在與非網(wǎng)(eefocus)工程師社區(qū)查看。
背景
此次任務(wù)通過串口命令行控制RGB LED,相比較與上一次任務(wù)通過單個字符控制增加了FreeRTOS-CLI組件,支持更復(fù)雜的、帶參數(shù)的命令。
1. 搭建VSCode開發(fā)環(huán)境
2. 添加FreeRTOS組件,創(chuàng)建任務(wù)
3. 添加FreeRTOS-CLI組件,打通適配層
4. 添加FreeRTOS-CLI自定義命令,控制RGB LED
搭建VS Code開發(fā)環(huán)境
無論是使用MCUXpresso IDE還是VS Code開發(fā)環(huán)境,都必須要:
1. 安裝MCUXpresso IDE,因為IDE里有NXP支持的GCC工具鏈
2. 下載mcux_sdk_frdm_mcxn947 SDK
3. VS Code安裝插件MCUXPresso for VS Code
4. VS Code配置插件MCUXpresso for VS Code
前幾個步驟都好說,這里簡短演示下VS Code配置插件MCUXpresso for VS Code。
01 配置MCUXpresso for VS Code
1. 在VS Code側(cè)邊欄單擊MCUXpresso圖標(biāo)展開右側(cè)視圖
2. 單擊(2)處展開右側(cè)視圖。這里建議單擊Import Example from Repository,因為它比上面的Import Repository有更多的配置選型,可以直接從這里創(chuàng)建示例工程
3. 單擊(3)處選擇本地的SDK路徑,例如這里選擇已經(jīng)下載并解壓縮的mcux_sdk_frdm_mcxn947
4. 單擊(4)處選擇MCUXpresso IDE的GCC工具鏈
5. 單擊(5)處選擇開發(fā)板,一個SDK可以支持同類型的幾個開發(fā)板,根據(jù)需要選擇對應(yīng)的開發(fā)板
6. 單擊(6)處選擇示例工程模版,也可以輸入關(guān)鍵詞搜索
7. 編輯(7)處輸入框輸入新建的工程名字
8. 單擊(8)處選擇工程保存路徑
9. 最后點擊Create即可以創(chuàng)建工程
02 工程結(jié)構(gòu)
.vscode/包含一些配置選項、調(diào)試啟動文件
repo/是一個鏈接文件,執(zhí)行SDK所在文件夾
app/包含應(yīng)用代碼
armgcc包含CMakeLists.txt目錄程序以及一些bat、shell編譯腳本,如果新增了源文件和頭文件,需要修改此處的CMakeLists.txt文件
board/包含管腳、時鐘、外設(shè)初始化代碼,是MCUXpresso Config Tools自動生成的文件夾
iar/是IAR IDE工程文件和鏈接腳本
mdk/是MDK IDE工程文件和鏈接腳本
后綴名為*.mex是MCUXpresso Config Tools的輸入文件
readme.md是示例工程的說明文檔
03 編譯、下載、調(diào)試
采用CMake+GCC編譯此工程,圖簡便的話直接點擊MCUXpresso for VS Code中的圖標(biāo),如下圖所示。
04 添加FreeRTOS組件
嘗試過MCUXpresso IDE添加FreeRTOS組件,雖然把源碼拷貝過來添加到工程里,但是port層的源文件和頭文件缺失了,需要從例程拷貝復(fù)制,太麻煩了。
而VS Code中添加組件的方式特別簡單,如下添加FreeRTOS組件,簡直不要太爽了。
1. 鼠標(biāo)右鍵單擊工程名
2. 在彈出的菜單中選擇(2)配置工程
3. 然后選擇(3)管理組件
4. 在(4)處編輯框輸入kernel過濾組件
5. 在(5)處選擇合適的FreeRTOS類型
6. 在(6)處點擊確認(rèn)即可
添加FreeRTOS所做的更改體現(xiàn)在armgcc/config.cmake文件,如下圖所示文件中增加了幾處和freertos相關(guān)的配置選項。當(dāng)然FreeRTOS源碼不會拷貝過來,它依然存在于SDK路徑中,但是需要拷貝一份FreeRTOSConfig.h過來,自行修改其中的參數(shù)。
05 新建FreeRTOS任務(wù)
新建一個最簡單的FreeRTOS任務(wù),每隔兩秒鐘打印一次信息。
(滑動查看)
int main(void) { // 管腳復(fù)用和配置 BOARD_InitBootClocks(); BOARD_InitBootPeripherals(); BOARD_InitBootPins(); BOARD_InitSWD_DEBUGPins(); // 調(diào)試串口打印日志 BOARD_InitDebugConsole(); PRINTF(" "); PRINTF(" Build: %s %s ", __DATE__, __TIME__); if (xTaskCreate(zygote_task, "zygote_task", ZYGOTE_TASK_STACK_SIZE, NULL, ZYGOTE_TASK_PRIORITY, NULL) != pdPASS) { PRINTF("Task creation failed!. "); while (1) ; } vTaskStartScheduler(); for (;;) ; } static void zygote_task(void *pvParameters) { uint32_t zygote_loop_cnt = 0; for (;;) { zygote_loop_cnt++; PRINTF("zygote loop cnt: %u ", zygote_loop_cnt); vTaskDelay(pdMS_TO_TICKS(2000)); } }
FreeRTOS-CLI組件
01 組件介紹
FreeRTOS-CLI是FreeRTOS官方的組件,支持注冊多參數(shù)命令,命令接口可以是串口、網(wǎng)絡(luò)套接字等。
當(dāng)前使用的版本是FreeRTOS+CLI V1.0.4,適配層使用串口,注冊兩個多參數(shù)的命令,控制開發(fā)板上的RGB LED亮滅。
02 添加FreeRTOS-CLI組件
在源碼頂層目錄新建3rdparty目錄并拷貝FreeRTOS_Plus_CLI組件到此,目錄結(jié)構(gòu)如下:
FreeRTOS_Plus_CLI/ port/ serial.c serial.h src/ FreeRTOS_CLI.c FreeRTOS_CLI.h
我們只需要關(guān)心port/目錄即可,適配UART層在這里。
03 適配層
重點在以下幾個函數(shù)的適配:
xSerialPortInitMinimal()
xSerialPortInit()
vSerialPutString()
xSerialGetChar()
xSerialPutChar()
因為管腳初始化已經(jīng)由MCUXpresso Config Tools圖形化配置完成,通過Debug UART進(jìn)行輸入輸出,所以前兩個串口初始化函數(shù)可以留空,重點在于xSerialGetChar()和xSerialPutChar()的實現(xiàn),這里簡單實現(xiàn)一下,通過Debug UART進(jìn)行輸入輸出即可。
(滑動查看)
signed portBASE_TYPE xSerialGetChar(xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime) { #ifndef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING *pcRxedChar = GETCHAR(); return pdPASS; #else char data = 0; while (xBlockTime-- > 0) { if (kStatus_Success == DbgConsole_TryGetchar(&data)) { *pcRxedChar = data; return pdPASS; } else { vTaskDelay(pdMS_TO_TICKS(1)); } } return pdFAIL; #endif } signed portBASE_TYPE xSerialPutChar(xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime) { signed portBASE_TYPE ch = 0; ch = PUTCHAR(cOutChar); return ch; }
04 RGB LED控制命令
為了點亮、熄滅RGB LED,需要實現(xiàn)如下這樣的命令:
ledset r on點亮紅色LED,同理ledset g/b on點亮綠色、藍(lán)色LED
ledset r off熄滅紅色LED,同理ledset g/b off熄滅綠色、藍(lán)色LED
ledget r獲取紅色LED狀態(tài),如LEDR:OFF表示熄滅,LEDR:ON表示點亮
05 點亮、熄滅 LED命令的實現(xiàn)
(滑動查看)
// TODO: ledset r/g/b on/off // 作用:設(shè)置燈的狀態(tài) // 命令: ledset // 參數(shù)1:編號,這里以 r/g/b 縮寫分別表示 "RED/GREE/BLUE" 三個燈 // 參數(shù)2:開關(guān),這里以字符串 on/off 分別表示 "開燈/關(guān)燈" /** * @brief * * @param pcWriteBuffer * @param xWriteBufferLen * @param pcCommandString * @return BaseType_t */ static BaseType_t prvLedSetCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { configASSERT(pcWriteBuffer); /* param1: r/g/b */ const char *paramLedId = NULL; BaseType_t paramLedIdLength = 0; led_id_e mLedId = LED_ID_INVALID; /* param2: on/off */ const char *paramLedStatus = NULL; BaseType_t paramLedStatusLength = 0; led_status_e mLedStatus; // 首先清除輸出緩沖區(qū)舊的內(nèi)容 memset(pcWriteBuffer, 0, xWriteBufferLen); // TODO: 根據(jù)兩個參數(shù)打印返回的字符串 paramLedId = FreeRTOS_CLIGetParameter(pcCommandString, 1, ¶mLedIdLength); paramLedStatus = FreeRTOS_CLIGetParameter(pcCommandString, 2, ¶mLedStatusLength); if (strncmp("r", paramLedId, 1) == 0) { mLedId = LED_ID_RED; } else if (strncmp("g", paramLedId, 1) == 0) { mLedId = LED_ID_GREEN; } else if (strncmp("b", paramLedId, 1) == 0) { mLedId = LED_ID_BLUE; } else { mLedId = LED_ID_INVALID; } if (strncmp("on", paramLedStatus, 2) == 0) { mLedStatus = LED_ON; } else if (strncmp("off", paramLedStatus, 3) == 0) { mLedStatus = LED_OFF; } led_set_status(mLedId, mLedStatus); /* There is no more data to return after this single string, so return pdFALSE. */ return pdFALSE; }
06 獲取LED狀態(tài)命令的實現(xiàn)
(滑動查看)
// TODO: ledget r/g/b // 作用:獲取燈的狀態(tài) // 命令: ledget // 參數(shù)1:編號 /** * @brief * * @param pcWriteBuffer * @param xWriteBufferLen * @param pcCommandString * @return BaseType_t */ static BaseType_t prvLedGetCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { configASSERT(pcWriteBuffer); /* param1: r/g/b */ const char *paramLedId = NULL; BaseType_t paramLedIdLength = 0; led_id_e mLedId = LED_ID_INVALID; led_status_e mLedStatus; // 首先清除輸出緩沖區(qū)舊的內(nèi)容 memset(pcWriteBuffer, 0, xWriteBufferLen); paramLedId = FreeRTOS_CLIGetParameter(pcCommandString, 1, ¶mLedIdLength); if (strncmp("r", paramLedId, 1) == 0) { mLedId = LED_ID_RED; } else if (strncmp("g", paramLedId, 1) == 0) { mLedId = LED_ID_GREEN; } else if (strncmp("b", paramLedId, 1) == 0) { mLedId = LED_ID_BLUE; } else { mLedId = LED_ID_INVALID; } /* 獲取燈的狀態(tài) */ mLedStatus = led_get_status(mLedId); /* 輸出燈的狀態(tài),輸出到 pcWriteBuffer 緩沖區(qū)中 */ sprintf(pcWriteBuffer, "%s: %s ", led_helper_id_to_string(mLedId), led_helper_status_to_string(mLedStatus)); /* There is no more data to return after this single string, so return pdFALSE. */ return pdFALSE; }
07 注冊命令
先定義結(jié)構(gòu)體,把命令字符串和解析函數(shù)關(guān)聯(lián)在一起。
(滑動查看)
/* Structure that defines the "ledset" command line command. This generates a table that gives information on each task in the system. */ static const CLI_Command_Definition_t xLedSet = { "ledset", /* The command string to type. */ " ledset: set r/g/b led status example: ledset r on or ledset g off ", prvLedSetCommand, /* The function to run. */ 2 /* 2 parameters are expected. */ }; /* Structure that defines the "ledget" command line command. This generates a table that gives information on each task in the system. */ static const CLI_Command_Definition_t xLedGet = { "ledget", /* The command string to type. */ " ledget : get r/g/b led status example: ledget r or ledget g ", prvLedGetCommand, /* The function to run. */ 1 /* 1 parameters are expected. */ };
再在合適的時機(jī)注冊命令,如下所示:
(滑動查看)
void vRegisterBspCliCommands(void) { /* Register all the command line commands defined immediately above. */ FreeRTOS_CLIRegisterCommand( &xLedSet ); FreeRTOS_CLIRegisterCommand( &xLedGet ); }
static void zygote_task(void *pvParameters) { uint32_t zygote_loop_cnt = 0; /* FreeRTOS-CLI 任務(wù)創(chuàng)建 */ vUARTCommandConsoleStart(); extern void vRegisterSampleCLICommands(void); vRegisterSampleCLICommands(); vRegisterBspCliCommands(); for (;;) { zygote_loop_cnt++; PRINTF("zygote loop cnt: %u ", zygote_loop_cnt); vTaskDelay(pdMS_TO_TICKS(2000)); } }
08 驗證
發(fā)送命令ledset r on電量紅色LED
發(fā)送命令ledset r off熄滅紅色LED
發(fā)送命令ledget r獲取紅色LED點亮狀態(tài)
替換r/g/b可以正確執(zhí)行命令
-
恩智浦
+關(guān)注
關(guān)注
14文章
5981瀏覽量
116900 -
RGB
+關(guān)注
關(guān)注
4文章
807瀏覽量
59945 -
命令
+關(guān)注
關(guān)注
5文章
737瀏覽量
22887 -
開發(fā)環(huán)境
+關(guān)注
關(guān)注
1文章
242瀏覽量
17126
原文標(biāo)題:用戶測評(四):使用NXP MCX-N板卡新增命令控制
文章出處:【微信號:AvnetAsia,微信公眾號:安富利】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
恩智浦 MCX N系列之電源管理(MCX N94/54與MCX N23)

恩智浦MCX N23的官方評估板FRDM-MCXN236詳解

NXP推出有助于保護(hù)用戶隱私的遠(yuǎn)場語音控制和命令識別方案
恩智浦全新MCX N微控制器推出!助力實現(xiàn)高性能、低功耗的邊緣安全智能
貿(mào)澤電子開售適用于智能電機(jī)控制和機(jī)器學(xué)習(xí)應(yīng)用的 NXP Semiconductors MCX微控制器
基于MCX N和MCX A系列微控制器,NXP宣布推出無線多協(xié)議MCX W系列

富昌電子推薦兩款恩智浦的MCX A和MCX N系列微控制器
恩智浦發(fā)布全新MCX W系列微控制器
MCX N系列微控制器適用于安全、智能的電機(jī)控制和機(jī)器學(xué)習(xí)應(yīng)用
NXP MCX N23和MCX N94/54的不同之處

NXP MCX L微控制器 搭載超低功耗感應(yīng)域,功耗比其他MCX MCU低3倍
用戶測評之體驗NXP MCX-N板卡的NPU功能

使用NXP MCX-N板卡搭建環(huán)境及點燈

評論