查看: 8603|回复: 11

RT1052——12.纪念贴与eDMA不定长接收

[复制链接]
  • TA的每日心情
    慵懒
    2024-2-8 09:39
  • 签到天数: 217 天

    [LV.7]常住居民III

    92

    主题

    1111

    帖子

    29

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    7576

    热心会员

    最后登录
    2024-4-17
    发表于 2018-11-19 20:45:04 | 显示全部楼层 |阅读模式
    这次的标题虽然是飞凌RT1052,可实际上它已经离我远去了,这个题目只是做一个纪念(555~~~)

    那是11月5号的一个晚上,那时的我正在调spi oled,代码已经通了。不过我使用的供电方式有点特殊,直接使用io作为vcc和gnd(按RT1052的io输出能力应该完全没问题啊~)。之所以这么用,是因为飞凌的板子上2.54的排针实在太少了,而且从前搞别的单片机的时候,也经常这么供电。一开始,一切正常,没有一点问题。我打开了QQ,去聊天。大约有3个小时吧。打算开始写贴子(这时候还在正常运行)。我把手伸向板子的时候。突然,oled就灭了,我就懵了。然后就不亮了。核心板的电源指示灯也不亮了。芯片击穿了。现在的我也不明白到地发生了什么。。。。。。然后联系飞凌的工作人员,板子就寄回去了。没得玩了。

    后来回了一趟学校(大四,实习狗),去了一趟实验室(智能车出身),他们有兴趣用RT1052做车(之前玩飞凌的板子也是因为这个,结果还差几个关键的外设没研究)。我就拿了那里的野火的mini,美名调试。又有板子玩了

    然后昨天看到一个论坛有人问rt1052的串口dma不定长接收,感觉很有意思,今天下班回来就写了一个。也算为了回答它的问题。

    大概思想就是利用串口的空闲中断,空闲就是在串口没有发送没有接收的时候的状态,当然强大的1052还能设置多少位没接收到时就进入空闲(可以看飞凌RT1052——5.串口的发送与接收https://www.nxpic.org.cn/module/foru ... 174&fromuid=3469866,这个贴子,里面有我翻译的那一个控制位)。空闲中断就是在进入空闲状态时候可以触发的。这样就有一个接收不定长串口数据,而且还不占用mcu资源的一个写法。就是利用dma接收数据。然后数据发完一大段之后。进入空闲中断,然后中断处理数据。然后继续dma接收。(其实我感觉rt1052可能还有另一种写法,随缘更新吧)

    工程是基于野火的mini板,工程也是直接改的。不过对于飞凌的板子来说,只要复制全部的main.c里面的东西,然后添加一下库文件,就ok了。

    工程很乱,毕竟是很短的时间写出来的,很多地方没有优化,不要太在意了(又想起死去的飞凌rt1052)。这次就不进行分析了(反正也没人看。。。自己理解就好了)

    效果截图
    QQ截图20181119204343.png

    eDMA串口不定长接收.zip (1.63 MB, 下载次数: 443)
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2018-4-20 15:04
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    49

    主题

    188

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2947
    最后登录
    2023-7-24
    发表于 2018-11-20 00:04:17 | 显示全部楼层
    那个问空闲中断问题的是我,看了你的代码,原来我已经写好了99%的东西,差一步就完成了。
    今天心情不错
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-4-20 15:04
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    49

    主题

    188

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2947
    最后登录
    2023-7-24
    发表于 2018-11-20 00:20:27 | 显示全部楼层
    void LPUART1_IRQHandler()
    {
            int count;
        if((kLPUART_IdleLineInterruptEnable)&LPUART_GetStatusFlags(LPUART1))
        {
                            LPUART_TransferGetReceiveCountEDMA(LPUART1,&g_lpuartEdmaHandle,&count);
                            printf("%d\n",count);
                           
                            LPUART_ClearStatusFlags(LPUART1,kLPUART_IdleLineInterruptEnable);
                           
                            LPUART_TransferAbortReceiveEDMA(LPUART1, &g_lpuartEdmaHandle);   //eDMA终止接收数据
                            LPUART_ReceiveEDMA(LPUART1, &g_lpuartEdmaHandle, &receiveXfer);  //使用eDMA接收
        }
    }


    RT1052串口DMA接收里面最关键的这句终止DMA接收我忘记加了,因此之前的代码中,收到的DMA数据长度会一直累加,这样跟空闲中断实现的DMA接收的思想不符,加上这句之后,count的数值每次都会刷新,随着收到数据长度改变而改变,也就是完全符合空闲中断+DMA接收的思想。不过楼主的代码还不算是最好的处理方式,最好的处理方式是在主循环中做出处理,这样会少漏掉一些因中断服务时间片而无法接收的数据,详情看我一会发出的帖子。

    今天心情不错
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-2-8 09:39
  • 签到天数: 217 天

    [LV.7]常住居民III

    92

    主题

    1111

    帖子

    29

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    7576

    热心会员

    最后登录
    2024-4-17
     楼主| 发表于 2018-11-20 08:10:08 | 显示全部楼层
    donatello1996 发表于 2018-11-20 00:20
    void LPUART1_IRQHandler()
    {
            int count;

    肯定不是最好的方式啊,在中断里面用阻塞发送就是个很大的问题,这里就是实验。看看就行了。具体使用还需要修改。这个edma代码的优化空间还很大。很多地方都可以替换成寄存器的。而且中断服务函数里面完全可以只放一个标志位,不过我感觉那样写不如这样写清晰。最后有啥好玩的记得分享一下
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    1

    主题

    8

    帖子

    0

    新手上路

    Rank: 1

    积分
    25
    最后登录
    2021-9-13
    发表于 2021-9-9 10:19:08 | 显示全部楼层
    如果用DMA的方式用同一个串口把收到的数据发送回去,发送完成后也会进入这个中断服务函数,这个时候怎么清除发送完成flag呢?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-4-9 17:01
  • 签到天数: 1478 天

    [LV.10]以坛为家III

    203

    主题

    2万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    92609
    最后登录
    2024-4-9
    发表于 2021-9-9 14:18:06 | 显示全部楼层
    有病 发表于 2021-9-9 10:19
    如果用DMA的方式用同一个串口把收到的数据发送回去,发送完成后也会进入这个中断服务函数,这个时候怎么清 ...

    NXP的一般习惯是向那个中断对应位写入1,你可以测试一下 TS1 - 副本 (3).jpg TS1 - 副本 (4).jpg TS1 - 副本 (2).jpg TS1 - 副本 (7).jpg TS1 - 副本 (10).jpg TS1 - 副本 (8).jpg TS1 - 副本 (6).jpg TS1 - 副本 (5).jpg TS1 - 副本 (9).jpg TS1.jpg
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    1

    主题

    8

    帖子

    0

    新手上路

    Rank: 1

    积分
    25
    最后登录
    2021-9-13
    发表于 2021-9-9 14:52:47 | 显示全部楼层
    stm1024 发表于 2021-9-9 14:18
    NXP的一般习惯是向那个中断对应位写入1,你可以测试一下

    试了,用的LPUART3->STAT |= LPUART_STAT_TDRE_MASK这种方式,把STAT寄存器的发送完成falg写1了,依然不行,还是会一直不断进入中断服务函数。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-2-8 09:39
  • 签到天数: 217 天

    [LV.7]常住居民III

    92

    主题

    1111

    帖子

    29

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    7576

    热心会员

    最后登录
    2024-4-17
     楼主| 发表于 2021-9-9 15:57:50 | 显示全部楼层
    有病 发表于 2021-9-9 14:52
    试了,用的LPUART3->STAT |= LPUART_STAT_TDRE_MASK这种方式,把STAT寄存器的发送完成falg写1了,依然不 ...

    估计是有标志位没有清除,可以仿真监控一下看看
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    1

    主题

    8

    帖子

    0

    新手上路

    Rank: 1

    积分
    25
    最后登录
    2021-9-13
    发表于 2021-9-9 16:02:51 | 显示全部楼层
    az158 发表于 2021-9-9 15:57
    估计是有标志位没有清除,可以仿真监控一下看看

    就是仿真看了的,使用LPUART_SendEDMA()发送数据后,程序就会跳到中断服务函数LPUART3_IRQHandler(),然后我在中断服务函数中做判断,也确实进了发送完成的那个if里面。然后我在这个if里面用的如下清除语句:
    LPUART3->STAT |= LPUART_STAT_RDRF_MASK;
    LPUART3->STAT |= LPUART_STAT_TC_MASK;
    LPUART3->STAT |= LPUART_STAT_TDRE_MASK;
    但是走完这个if退出中断服务函数后,又会进入中断函数,依然是进入发送完成的if。就这样无限循环卡死在这里。貌似是这三条语句并不能清除这个flag,有没有什么其他方法啊?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    9

    主题

    25

    帖子

    0

    注册会员

    Rank: 2

    积分
    191
    最后登录
    2023-4-12
    发表于 2022-5-7 09:49:50 | 显示全部楼层
    有病 发表于 2021-9-9 16:02
    就是仿真看了的,使用LPUART_SendEDMA()发送数据后,程序就会跳到中断服务函数LPUART3_IRQHandler() ...

    你好,你的问题解决了,我现在也遇到了这样的问题,使用LPUART_SendEDMA()这个函数后程序就会死掉
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-20 08:13 , Processed in 0.146423 second(s), 31 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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