硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1509|回复: 7
收起左侧

[客户分享] 串口使能就立马进入发送完成中断问题

[复制链接]

9

主题

156

回帖

183

积分

初级会员

积分
183
发表于 2024-11-5 15:24:25 | 显示全部楼层 |阅读模式
类STM32的MCU很多遇到这个问题,串口是能就立马进入发送完成中断的问题。



能能中断后, 立马清除中断标志,不能解决问题, 代码如下:
[C] 纯文本查看 复制代码
gpio_init_type gpio_init_struct;
        
        gpio_default_para_init(&gpio_init_struct);
        /* 复用推挽输出 */
        gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
        gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
        /* PB6 PB7 */
        gpio_init_struct.gpio_pins = GPIO_PINS_6 | GPIO_PINS_7;
        gpio_init(GPIOB, &gpio_init_struct);
        /* 配置复用模式 */
        gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE6, GPIO_MUX_0);
        gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE7, GPIO_MUX_0);

        /* 初始化串口1 */
        crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
        usart_init(USART1, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
    usart_enable(USART1, TRUE);
    usart_receiver_enable(USART1, TRUE);
        usart_transmitter_enable(USART1, TRUE);

    /* 使能收发中断 */
        usart_interrupt_enable(USART1, USART_RDBF_INT, TRUE);
        usart_interrupt_enable(USART1, USART_TDC_INT, TRUE);

    /* 清除中断标志 */
    usart_flag_clear(USART1, USART_RDBF_FLAG);
    usart_flag_clear(USART1, USART_TDC_FLAG);

    /* 配置发送中断优先级 */
    nvic_irq_enable(USART1_IRQn, 15, 0);


经过搜索,总于找到答案, 网上有不少网友也遇到过类似的问题
分析初始化STM32串口后进入发送完成中断的现象-电子工程世界

我使用的是AT32F421, 文档介绍如下
下载 (1).png
确实,在开启发送器后,将会自动发送1个空闲帧,如果使能后立即清除标志,而空闲帧发送完成又在清除标志之后。那发送完成标志位又将置位。从而使能后,自动进入中断服务函数
以下是修改后的代码:
[C] 纯文本查看 复制代码
gpio_init_type gpio_init_struct;
        
        gpio_default_para_init(&gpio_init_struct);
        /* 复用推挽输出 */
        gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
        gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
        /* PB6 PB7 */
        gpio_init_struct.gpio_pins = GPIO_PINS_6 | GPIO_PINS_7;
        gpio_init(GPIOB, &gpio_init_struct);
        /* 配置复用模式 */
        gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE6, GPIO_MUX_0);
        gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE7, GPIO_MUX_0);

        /* 初始化串口1 */
        crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
        usart_init(USART1, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
    usart_enable(USART1, TRUE);
    usart_receiver_enable(USART1, TRUE);
        
    /* 使能发送, 将自动发送一个空闲帧 */
    usart_flag_clear(USART1, USART_TDC_FLAG);
    usart_transmitter_enable(USART1, TRUE);
        uint32_t cnt = 0;
    while (usart_flag_get(USART1, USART_TDC_FLAG) == FALSE) {cnt++;}
        DEBUG_RTT("cnt:%d\r\n", cnt);
        
    /* 使能收发中断 */
        usart_interrupt_enable(USART1, USART_RDBF_INT, TRUE);
        usart_interrupt_enable(USART1, USART_TDC_INT, TRUE);

    /* 清除中断标志 */
    usart_flag_clear(USART1, USART_RDBF_FLAG);
    usart_flag_clear(USART1, USART_TDC_FLAG);

    /* 配置发送中断优先级 */
    nvic_irq_enable(USART1_IRQn, 15, 0);

1.清除发送完成标志;
2.开启发送器;
3.等待发送完成标志位置位;
4.清除发送完成标志.

可以发现, 波特率越低, 等待的时间越长
2.png
3.png







回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-11-6 09:41:51 | 显示全部楼层
这种好像不能完美解决,STM32 大部分系列都有这个问题。

没处理好的时候,上电就会发送个0出来。
回复

使用道具 举报

9

主题

156

回帖

183

积分

初级会员

积分
183
 楼主| 发表于 2024-11-6 18:00:11 | 显示全部楼层
仅仅是解决了进入中断的问题,应该可以等串口都配置好了。再配置GPIO就没有问题了
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-11-7 09:34:16 | 显示全部楼层
tcs_stm32 发表于 2024-11-6 18:00
仅仅是解决了进入中断的问题,应该可以等串口都配置好了。再配置GPIO就没有问题了

下次我试试。
回复

使用道具 举报

9

主题

175

回帖

202

积分

高级会员

积分
202
发表于 2024-11-7 10:48:40 | 显示全部楼层

我也是这样处理的,先使能并配置 UART,然后再初始化 GPIO,测试是解决了上电自动发数据的问题
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-11-7 11:34:38 | 显示全部楼层
avita 发表于 2024-11-7 10:48
我也是这样处理的,先使能并配置 UART,然后再初始化 GPIO,测试是解决了上电自动发数据的问题

回复

使用道具 举报

9

主题

156

回帖

183

积分

初级会员

积分
183
 楼主| 发表于 2024-11-7 19:41:22 | 显示全部楼层
配置GPIO还是有技巧的,应该先配置复用模式, AF0~AFx, 在配置GPIO为复用模式,否则默认是AF0, AF0不一定是串口, 映射到其他外设,可能是0也可以是1
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-11-8 09:45:43 | 显示全部楼层
tcs_stm32 发表于 2024-11-7 19:41
配置GPIO还是有技巧的,应该先配置复用模式, AF0~AFx, 在配置GPIO为复用模式,否则默认是AF0, AF0不一定是 ...

这个建议很有意义。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 18:14 , Processed in 0.049643 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表