嵌入式技术论坛
直播中

最强海贼王

8年用户 1377经验值
擅长:MEMS/传感技术
私信 关注
[问答]

如果串口1已经用作FISH了,再用来接受数据不出错吧

前置环镜:RTT Studio基于STM32F407开发。
1.首先代码是在F407上验证过可以使用串口1-串口6整除收发数据的。
2.最近购买一个板卡,串口1-串口6都是RS485输出的。
3.自从把代码烧到这块板子后,就没有正常收到数据。一开始我怀疑是RS485收发器引脚没拉低电平,导致RS485都处于发送状态。但是引脚也拉低了的。就是收不到数据。系统正常跑,指示灯正常闪烁。

所以,我的问题是,如果串口1已经用作FISH了,在使用来接受数据不出错吧?接受是DMA接受。首先不考虑混用串口带来的数据混乱问题,就只是为了验证串口能收到数据。其他串口我也试了,也没收到数据。

回帖(11)

刘秀英

2022-8-22 14:09:04
强烈不建议这么做,运行 RT-Thread 操作系统最好单独留一个串口作为控制台的串口,在控制台中可以方便的看出来线程、定时器、信号量、互斥锁、内存等关键信息的运行情况,更方便监控整个系统的运行。

控制台线程的执行代码在文件 rt-threadcomponentsfinshshell.c 里面,如下所示。从中可以看出改线程在一直获取控制台串口的输入数据,也就是说该串口一收到数据就会被该线程读出来(该线程的优先级是 20),收到 “rn” 之后开始解析命令并执行对应的操作。如果将控制台串口和其他通讯功能合为一个,想实现除了解析命令还解析其他协议的话,那么就需要修改该函数的实现,如果修改不好会影响到控制台命令的解析,建议硬件设计时单独留出来一个串口作为控制台串口使用。

void finsh_thread_entry(void *parameter)
{
    int ch;
    /* normal is echo mode */
#ifndef FINSH_ECHO_DISABLE_DEFAULT
    shell->echo_mode = 1;
#else
    shell->echo_mode = 0;
#endif
#if !defined(RT_USING_POSIX) && defined(RT_USING_DEVICE)
    /* set console device as shell device */
    if (shell->device == RT_NULL)
    {
        rt_device_t console = rt_console_get_device();
        if (console)
        {
            finsh_set_device(console->parent.name);
        }
    }
#endif
#ifdef FINSH_USING_AUTH
    /* set the default password when the password isn't setting */
    if (rt_strlen(finsh_get_password()) == 0)
    {
        if (finsh_set_password(FINSH_DEFAULT_PASSWORD) != RT_EOK)
        {
            rt_kprintf("Finsh password set failed.n");
        }
    }
    /* waiting authenticate success */
    finsh_wait_auth();
#endif
    rt_kprintf(FINSH_PROMPT);
    while (1)
    {
        ch = (int)finsh_getchar();
        if (ch < 0)
        {
            continue;
        }
        /*
         * handle control key
         * up key  : 0x1b 0x5b 0x41
         * down key: 0x1b 0x5b 0x42
         * right key:0x1b 0x5b 0x43
         * left key: 0x1b 0x5b 0x44
         */
        if (ch == 0x1b)
        {
            shell->stat = WAIT_SPEC_KEY;
            continue;
        }
        else if (shell->stat == WAIT_SPEC_KEY)
        {
            if (ch == 0x5b)
            {
                shell->stat = WAIT_FUNC_KEY;
                continue;
            }
            shell->stat = WAIT_NORMAL;
        }
        else if (shell->stat == WAIT_FUNC_KEY)
        {
            shell->stat = WAIT_NORMAL;
            if (ch == 0x41) /* up key */
            {
#ifdef FINSH_USING_HISTORY
                /* prev history */
                if (shell->current_history > 0)
                    shell->current_history --;
                else
                {
                    shell->current_history = 0;
                    continue;
                }
                /* copy the history command */
                memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
                       FINSH_CMD_SIZE);
                shell->line_curpos = shell->line_position = strlen(shell->line);
                shell_handle_history(shell);
#endif
                continue;
            }
            else if (ch == 0x42) /* down key */
            {
#ifdef FINSH_USING_HISTORY
                /* next history */
                if (shell->current_history < shell->history_count - 1)
                    shell->current_history ++;
                else
                {
                    /* set to the end of history */
                    if (shell->history_count != 0)
                        shell->current_history = shell->history_count - 1;
                    else
                        continue;
                }
                memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
                       FINSH_CMD_SIZE);
                shell->line_curpos = shell->line_position = strlen(shell->line);
                shell_handle_history(shell);
#endif
                continue;
            }
            else if (ch == 0x44) /* left key */
            {
                if (shell->line_curpos)
                {
                    rt_kprintf("b");
                    shell->line_curpos --;
                }
                continue;
            }
            else if (ch == 0x43) /* right key */
            {
                if (shell->line_curpos < shell->line_position)
                {
                    rt_kprintf("%c", shell->line[shell->line_curpos]);
                    shell->line_curpos ++;
                }
                continue;
            }
        }
        /* received null or error */
        if (ch == '' || ch == 0xFF) continue;
        /* handle tab key */
        else if (ch == 't')
        {
            int i;
            /* move the cursor to the beginning of line */
            for (i = 0; i < shell->line_curpos; i++)
                rt_kprintf("b");
            /* auto complete */
            shell_auto_complete(&shell->line[0]);
            /* re-calculate position */
            shell->line_curpos = shell->line_position = strlen(shell->line);
            continue;
        }
        /* handle backspace key */
        else if (ch == 0x7f || ch == 0x08)
        {
            /* note that shell->line_curpos >= 0 */
            if (shell->line_curpos == 0)
                continue;
            shell->line_position--;
            shell->line_curpos--;
            if (shell->line_position > shell->line_curpos)
            {
                int i;
                rt_memmove(&shell->line[shell->line_curpos],
                           &shell->line[shell->line_curpos + 1],
                           shell->line_position - shell->line_curpos);
                shell->line[shell->line_position] = 0;
                rt_kprintf("b%s  b", &shell->line[shell->line_curpos]);
                /* move the cursor to the origin position */
                for (i = shell->line_curpos; i <= shell->line_position; i++)
                    rt_kprintf("b");
            }
            else
            {
                rt_kprintf("b b");
                shell->line[shell->line_position] = 0;
            }
            continue;
        }
        /* handle end of line, break */
        if (ch == 'r' || ch == 'n')
        {
#ifdef FINSH_USING_HISTORY
            shell_push_history(shell);
#endif
            if (shell->echo_mode)
                rt_kprintf("n");
            msh_exec(shell->line, shell->line_position);
            rt_kprintf(FINSH_PROMPT);
            memset(shell->line, 0, sizeof(shell->line));
            shell->line_curpos = shell->line_position = 0;
            continue;
        }
        /* it's a large line, discard it */
        if (shell->line_position >= FINSH_CMD_SIZE)
            shell->line_position = 0;
        /* normal character */
        if (shell->line_curpos < shell->line_position)
        {
            int i;
            rt_memmove(&shell->line[shell->line_curpos + 1],
                       &shell->line[shell->line_curpos],
                       shell->line_position - shell->line_curpos);
            shell->line[shell->line_curpos] = ch;
            if (shell->echo_mode)
                rt_kprintf("%s", &shell->line[shell->line_curpos]);
            /* move the cursor to new position */
            for (i = shell->line_curpos; i < shell->line_position; i++)
                rt_kprintf("b");
        }
        else
        {
            shell->line[shell->line_position] = ch;
            if (shell->echo_mode)
                rt_kprintf("%c", ch);
        }
        ch = 0;
        shell->line_position ++;
        shell->line_curpos++;
        if (shell->line_position >= FINSH_CMD_SIZE)
        {
            /* clear command line */
            shell->line_position = 0;
            shell->line_curpos = 0;
        }
    } /* end of device read */
}
举报

最强海贼王

2022-8-22 14:09:24
嗯嗯,好的,感谢答复。我现在几个串口都收不到数据。我想问个问题哈,就是串口接受数据一定要像官方例程那样,先做个回调函数,再把数据通过消息队列放到消息队列里。再通过消息队列有无消息读取串口数据吗?

可不可以直接通过信号量或者其他方式,主动去rt_device_read ( _dev , 0 , buf + len , bufsz );呢?
举报

最强海贼王

2022-8-22 14:09:39
比如能不能直接这样读串口设备的数据?
1.jpg
int rs485_receive ( uint8_t *buf , int bufsz , int timeout , int bytes_timeout )
{
        int len = 0;
        while (1)
        {
                rt_sem_control ( _rx_sem , RT_IPC_CMD_RESET , RT_NULL );
                int rc = rt_device_read ( _dev , 0 , buf + len , bufsz );
                if (rc > 0)
                {
                        timeout = bytes_timeout;
                        len += rc;
                        bufsz -= rc;
                        if (bufsz == 0)
                                break;
                        continue;
                }
                if (rt_sem_take ( _rx_sem , rt_tick_from_millisecond ( timeout ) ) != RT_EOK)
                        break;
                timeout = bytes_timeout;
        }
        return len;
}
举报

刘秀英

2022-8-22 14:09:50
如果使用rtt的框架,在接收回调里面相当于中断的回调,执行回调函数了说明串口收到了数据。如果直接读就要不停的轮询会耗费mcu的资源,不建议这么写。
举报

最强海贼王

2022-8-22 14:10:01
嗯嗯,我是采用RTT框架的,只是现在收不到数据,所以我才尝试各种接收方式的可行性。并去验证不是代码的问题,至少不是串口接收方式不对的问题。
举报

刘秀英

2022-8-22 14:10:12
是基于芯片创建的工程吗?串口的话直接按照官方文档 串口设备使用示例 进行操作就行,在 boatrd.h 中定义串口号和使用的引脚,在cubemx软件中配置对应的串口
举报

最强海贼王

2022-8-22 14:10:32
确实是这么做的,而且以前都是正常通信的。我先找找有没有其他板子来换先。
举报

最强海贼王

2022-8-22 14:10:41
对咯,我确认个事情哈。就是串口这块,引脚我不需要在board.c里初始化了吧?只需要在board.h里说明使用哪个引脚就行?我现在使用uart6作为控制台输出。直接在rtt setting里将uart6设为输出口就行?
1.jpg
是否还需要在board.c里写入串口1-串口6引脚的初始化过程?

1.jpg
举报

刘秀英

2022-8-22 14:10:53
是的,串口设备定义使用的串口和引脚号就行。串口初始化流程如下

|-> rt_device_find(device.c)      // 查找注册串口设备
  |-> rt_device_open(device.c)      // 打开串口设备
    |-> device_init(device.c)
    |-> rt_serial_init(serial.c)  // 串口设备初始化
      |-> serial->ops->configure(serial, &serial->config);(serial.c)
      |-> stm32_configure(drv_usart.c)
        |-> stm32_gpio_configure(drv_usart.c)  // 串口引脚和时钟初始化
        |-> HAL_UART_Init(stm32f4xx_hal_uart.c)
举报

最强海贼王

2022-8-22 14:11:06
那就奇怪了,我在board.h里写明了串口1-串口6的引脚号。也在控制台输出那里选了串口6,但是串口6就是没有输出。我使用LOG_I()打印日志,就是没发现有日志输出。
举报

刘秀英

2022-8-22 14:11:33
你单步调试跟踪一下呢?看看串口的寄存器是否已经配置好了。
使用串口1做控制台可以正常输出吗?
举报

更多回帖

发帖
×
20
完善资料,
赚取积分