OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2621|回复: 6

程序中有DMA以后,程序的流程怎么理顺?

[复制链接]

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2018-8-31 17:57:34 | 显示全部楼层 |阅读模式
5金钱
最早接触的代码是菜鸟级别的

void main(void)

     inti();
    while(1)

     任务1();
     任务2();




高级一些的加入一些中断,比如串口、定时器。

无论多么复杂的程序,我们都可以有一个执行流程,这个是针对CPU来看的。1.从main函数开始-----》2.然后进入while,跑第一个任务,然后几个任务一直循环-----》3.某个时刻中断了,跳转到中断里面跑,置一些标志位,当前任务挂起,中断出来继续刚刚
挂起的任务跑,又在while(1)里面循环。



那么加入DMA以后,我知道MCU还在照样这样跑,但是数据的处理好像没有那种感觉了,我什么时候需要用,什么时候有数据用,我将一无所知,不像上面那样我等待某个标志即可,不停的在while(1)循环。


















最佳答案

查看完整内容[请看2#楼]

楼上正解。 DMA初始化后,你可以随时查询是否完成,也可以让它申请中断。 打个比方:大人在做饭(主程序),给小孩分配一点活:“把豆角剥一下吧(DMA)” 这可以有两种配合方式:一是中断方式,事先告诉小孩,“剥完了告诉我一声”,小孩完成后喊一声(申请中断),中断服务函数中执行炒豆角。 二是查询方式:主循环中增加一项任务,主动问小孩:“剥完了吗?(检查标志)”根据结果决定是否执行炒豆角。
自己选择的路,成家前走完。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4522
金钱
4522
注册时间
2018-5-11
在线时间
947 小时
发表于 2018-8-31 17:57:35 | 显示全部楼层
楼上正解。
DMA初始化后,你可以随时查询是否完成,也可以让它申请中断。
打个比方:大人在做饭(主程序),给小孩分配一点活:“把豆角剥一下吧(DMA)”
这可以有两种配合方式:一是中断方式,事先告诉小孩,“剥完了告诉我一声”,小孩完成后喊一声(申请中断),中断服务函数中执行炒豆角。
二是查询方式:主循环中增加一项任务,主动问小孩:“剥完了吗?(检查标志)”根据结果决定是否执行炒豆角。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

3

主题

312

帖子

0

精华

高级会员

Rank: 4

积分
907
金钱
907
注册时间
2011-10-19
在线时间
196 小时
发表于 2018-8-31 23:15:24 | 显示全部楼层
所有处理都用中断来推动——定时中断、外部中断、传输完成中断等。但中断处理函数通常只设置标志位,具体处理在main函数里实现。如果再实现些高阶功能(消息队列、软件定时器)则效果更佳!
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-8-31 23:24:52 | 显示全部楼层
DMA 的 ISR 就是让你可以检测DMA是否完成的一堆标志位
回复

使用道具 举报

3

主题

312

帖子

0

精华

高级会员

Rank: 4

积分
907
金钱
907
注册时间
2011-10-19
在线时间
196 小时
发表于 2018-9-1 08:52:30 | 显示全部楼层
本帖最后由 ufbycd 于 2018-9-1 09:01 编辑

我具体是做法是:实现消息队列及软件定时器,在中断里发送消息(携带数据),在main函数里处理消息。
[mw_shl_code=c,true]int main(int argc, char* argv[])
{
    (void)argc;
    (void)argv;

    _Init();
    Utils_Init();
    MsgQueue_Init(_MsgDeliver);
    Ctimer_Init();
    BSP_Init();
    Shell_Init(_shellCmds, ARRAY_SIZE(_shellCmds));
    Ctimer_Start(& _testTimer, 1000, _Test, 0);

    GUI_Init();
    /* Activate the use of memory device feature */
    WM_SetCreateFlags(WM_CF_MEMDEV);

    /* Start Demo */
//    GUIDEMO_Main();
    WatchDog_Init();

    while (1)
    {
        MsgQueue_Service();
        IDLE();
    }

    return -1;
}[/mw_shl_code]

[mw_shl_code=c,true]/**
* @brief 分发并处理消息
* @param msg 一条消息
*/
static void _MsgDeliver(MsgQueue_Msg_t *msg)
{

//    debug("MQ: Dealing msg id: %d\n", msg->id);

    switch(msg->id)
    {
    case MsgQueue_Id_CtimerFire:
        Ctimer_Fire(msg);
        break;

    case MsgQueue_Id_ShellLineIn:
        Shell_OnLine(msg);
        break;

    case MsgQueue_Id_SerialTest:
        Serial_OnTest(msg);
        break;

    case MsgQueue_Id_SlaveFrameIn:
//        Slave_OnFrameIn(msg);
        break;

    case MsgQueue_Id_CaptureCalc:
        Capture_Calc(msg);
        break;

    default:
        debug("Error: Unknown Message, id = %d!\n", msg->id);
        break;
    }
}
[/mw_shl_code]
回复

使用道具 举报

61

主题

160

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
270
金钱
270
注册时间
2012-1-12
在线时间
93 小时
发表于 2018-9-1 20:12:25 | 显示全部楼层
本帖最后由 47933673 于 2018-9-1 20:14 编辑

我的程序里面有采集气体压力大小的,我是用的DMA循环,不用中断,每次转换完成后自动放到一个内存里面,主程序只管调用这个内存数据就可以了,不需要管他什么时候转换完成了,因为他转换的时间比你刷新的时间要快的多,所以没有必要转换完成了来一个中断。
回复

使用道具 举报

3

主题

312

帖子

0

精华

高级会员

Rank: 4

积分
907
金钱
907
注册时间
2011-10-19
在线时间
196 小时
发表于 2018-9-1 21:54:11 | 显示全部楼层
47933673 发表于 2018-9-1 20:12
我的程序里面有采集气体压力大小的,我是用的DMA循环,不用中断,每次转换完成后自动放到一个内存里面,主 ...

如果是电池供电的产品就不能这么干了!
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 05:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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