打印
[APM32F4]

【APM32F411V Tiny Board测评】+串口shell移植nr_micro_shell和letter_shell

[复制链接]
1063|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 WoodData 于 2024-5-22 15:00 编辑

上期已经搞定了APM32F411的串口通信,本期就移植一下串口shell,方便命令控制。目前shell比较好的有nr_micao_shell和letter shell这2种。其中nr_micro_shell比较简单,只是基本的shell命令。
而letter shell相对复杂一些,但是功能也更多。有用户权限控制和密码控制。

下面就开始我的移植过程。由于之前也移植到其他平台MCU,所以本次移植也非常简单了。
首先下载nr_micao_shell和letter shell的代码,添加到keil工程中。加入头文件路径。

然后就是实现串口发送接收。接收要使用中断模式,使用FIFO缓存接收,防止数据丢失。
串口初始化和发送接收:
void APM_TINY_COMInit(USART_T * com, uint32_t baud)
{
    GPIO_Config_T GPIO_configStruct;
    USART_Config_T usartConfigStruct;

    GPIO_ConfigStructInit(&GPIO_configStruct);
    if (USART1 == com)
    {
        /* Enable GPIO clock */
        RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);
        RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1);
        
        /* Connect PXx to USARTx_Tx */
        GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_9, GPIO_AF_USART1);
        /* Connect PXx to USARTx_Rx */
        GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_10, GPIO_AF_USART1);
        /* Configure USART Tx as alternate function push-pull */
        GPIO_configStruct.mode = GPIO_MODE_AF;
        GPIO_configStruct.pin  = GPIO_PIN_9;
        GPIO_configStruct.speed = GPIO_SPEED_50MHz;
        GPIO_Config(GPIOA, &GPIO_configStruct);
        /* Configure USART Rx as input floating */
        GPIO_configStruct.mode = GPIO_MODE_AF;
        GPIO_configStruct.pin  = GPIO_PIN_10;
        GPIO_Config(GPIOA, &GPIO_configStruct);
    }
    else if (USART2 == com)
    {
        RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);
        RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_USART2);
        
        /* Connect PXx to USARTx_Tx */
        GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_2, GPIO_AF_USART2);
        /* Connect PXx to USARTx_Rx */
        GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_3, GPIO_AF_USART2);
        /* Configure USART Tx as alternate function push-pull */
        GPIO_configStruct.mode = GPIO_MODE_AF;
        GPIO_configStruct.pin  = GPIO_PIN_2;
        GPIO_configStruct.speed = GPIO_SPEED_50MHz;
        GPIO_Config(GPIOA, &GPIO_configStruct);
        /* Configure USART Rx as input floating */
        GPIO_configStruct.mode = GPIO_MODE_AF;
        GPIO_configStruct.pin  = GPIO_PIN_3;
        GPIO_Config(GPIOA, &GPIO_configStruct);
    }
   
    /* USART1 configuration */
    usartConfigStruct.baudRate = baud;
    usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
    usartConfigStruct.mode = USART_MODE_TX_RX;
    usartConfigStruct.parity = USART_PARITY_NONE;
    usartConfigStruct.stopBits = USART_STOP_BIT_1;
    usartConfigStruct.wordLength = USART_WORD_LEN_8B;
    /* USART configuration */
    USART_Config(com, &usartConfigStruct);
   
    /* Enable USART1 RXBNEinterrput */
    USART_EnableInterrupt(com,USART_INT_RXBNE);
    USART_ClearStatusFlag(com,USART_FLAG_RXBNE);
    NVIC_EnableIRQRequest(USART1_IRQn,1,0);
   
    /* Enable USART */
    USART_Enable(com);
}

void shell_usart_init(void)
{
    APM_TINY_COMInit(USART1,115200);
   
#ifdef UART_SHELL
#if UART_SHELL == 1
    userShellInit(); //LETTER_SHELL
#elif UART_SHELL == 2
    shell_init();   //NR_MICRO_SHELL
#endif
#endif
}
fifo结构体定义

typedef struct fifo_buffer
{
    volatile uint32_t    read_i;
    volatile uint32_t    write_i;
    uint8_t     buff[128];
}fifo_buffer;

extern fifo_buffer  shell_uart_rx;
接收数据处理:
void shell_usart_loop(void)
{
    if(shell_uart_rx.read_i != shell_uart_rx.write_i)
    {
#ifdef UART_SHELL
        #if UART_SHELL == 1
            shellHandler(&shell, shell_uart_rx.buff[shell_uart_rx.read_i++]); //letter shell
        #elif UART_SHELL == 2
            shell(shell_uart_rx.buff[shell_uart_rx.read_i++]);
        #endif
#endif
        shell_uart_rx.read_i &= 0x7f;
    }
}

void USART1_IRQHandler(void)
{
    uint32_t ch;
   
    if(USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == SET)
    {
        ch = USART_RxData(USART1);
        if(((shell_uart_rx.write_i+1)&0x7f) != shell_uart_rx.read_i)
        {
            shell_uart_rx.buff[shell_uart_rx.write_i++] = ch & 0xff;
            shell_uart_rx.write_i &= 0x7f;
        }
        USART_ClearStatusFlag(USART1,USART_FLAG_RXBNE);
    }
}
在main中调用,2个shell是通过宏定义选择编译。


接下来是修改nr_micro_shell配置移植,主要修改nr_micro_shell_config.h配置。
关键的串口部分:


letter shell的修改主要在port部分,shell_port.c文件内

#include "shell_cfg_user.h"
#include "shell_uart.h"
#include "shell.h"


Shell shell;
char shellBuffer[512];


/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 用户shell写
*
* @param data 数据
* @param len 数据长度
*
* [url=home.php?mod=space&uid=266161]@return[/url] short 实际写入的数据长度
*/
short userShellWrite(char *data, unsigned short len)
{
    for(uint32_t i=0;i<len;i++)
        USART_PutChar(data[i]);
    return len;
}


/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 用户shell读
*
* @param data 数据
* @param len 数据长度
*
* [url=home.php?mod=space&uid=266161]@return[/url] short 实际读取到
*/
short userShellRead(char *data, unsigned short len)
{
    uint32_t rlen = 0;
    for(uint32_t i=0;i<len;i++)
    {
        if(shell_uart_rx.read_i != shell_uart_rx.write_i)
        {
            data[rlen++] = shell_uart_rx.buff[shell_uart_rx.read_i++];
            shell_uart_rx.read_i &= 0x7f;
        }
    }
    return rlen;
}

/**
* @brief 用户shell上锁
*
* @param shell shell
*
* @return int 0
*/
int userShellLock(Shell *shell)
{
    return 0;
}

/**
* @brief 用户shell解锁
*
* @param shell shell
*
* @return int 0
*/
int userShellUnlock(Shell *shell)
{
    return 0;
}

/**
* @brief 用户shell初始化
*
*/
void userShellInit(void)
{
    shell.write = userShellWrite;
    shell.read = userShellRead;
//    shell.lock = userShellLock;
//    shell.unlock = userShellUnlock;
    shellInit(&shell, shellBuffer, 512);

}
配置在shell_cfg_user.h文件内。

下面来编译烧录测试一下。首先选择nr_micro_shell。定义#define UART_SHELL  2


再来测试一下letter shell。定义#define UART_SHELL  1。然后编译下载测试。




代码工程:
游客,如果您要查看本帖隐藏内容请回复







使用特权

评论回复
沙发
lemonhub| | 2024-5-22 14:23 | 只看该作者
本帖最后由 lemonhub 于 2024-5-22 14:41 编辑

学习学习,之前移植的时候,有部分功能没有成功,工程里面缺少shell_uart文件

使用特权

评论回复
板凳
WoodData|  楼主 | 2024-5-22 15:01 | 只看该作者
lemonhub 发表于 2024-5-22 14:23
学习学习,之前移植的时候,有部分功能没有成功,工程里面缺少shell_uart文件 ...

哦,重新上传了附近,缺的补上了

使用特权

评论回复
地板
szt1993| | 2024-5-23 16:49 | 只看该作者
shell—uart对于shell文本支持怎样?

使用特权

评论回复
5
WoodData|  楼主 | 2024-5-23 17:36 | 只看该作者
szt1993 发表于 2024-5-23 16:49
shell—uart对于shell文本支持怎样?

什么文本??

使用特权

评论回复
6
piaozi2008| | 2024-8-13 19:07 | 只看该作者
支持楼主2

使用特权

评论回复
7
chenjun89| | 2024-8-13 19:38 | 只看该作者
这两个shell楼主更推荐用哪个?

使用特权

评论回复
8
WoodData|  楼主 | 2024-8-13 22:45 | 只看该作者
chenjun89 发表于 2024-8-13 19:38
这两个shell楼主更推荐用哪个?

看你需求了,我一般只用nr_micro_shell就够了。如果需要用户控制和密码控制的用lettershell

使用特权

评论回复
9
binbin3944| | 2024-8-22 22:58 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

119

主题

4600

帖子

27

粉丝