当前位置: 首页 > wzjs >正文

仿小米论坛的wordpress主题seo咨询推广找推推蛙

仿小米论坛的wordpress主题,seo咨询推广找推推蛙,哪里有app项目开发,网站logo怎么替换DMA 直接存储器访问,通过硬件自动在外设与存储器之间进行数据的传输,不需要CPU的介入,减少了CPU的数据传递这种简单工作的消耗。 例如上次的ADC多通道,我们需要在主函数循环里面不断判断ADC的状态再读取ADC转换结束的值&#xff…

 DMA 直接存储器访问,通过硬件自动在外设与存储器之间进行数据的传输,不需要CPU的介入,减少了CPU的数据传递这种简单工作的消耗。

例如上次的ADC多通道,我们需要在主函数循环里面不断判断ADC的状态再读取ADC转换结束的值,但是如果我们通过DMA数据转运,把ADC转换完成的数据,存放到一个数组内,就不需要我们在主函数里面对ADC进行任何操作,直接在指定数组里面读取我们需要的数据即可。

减轻了CPU的负担,提高程序的速度。

DMA的相关hal库函数

DMA初始化结构体

typedef struct
{uint32_t Direction;                 /*传输方向*/uint32_t PeriphInc;                 /*外设自增与否*/uint32_t MemInc;                    /*存储器自增与否*/uint32_t PeriphDataAlignment;       /*外设数据对齐方式*/uint32_t MemDataAlignment;          /*存储器数据对齐方式 */uint32_t Mode;                      /*DMA转运模式*/uint32_t Priority;                  /*DMA转运优先级供DMA仲裁使用 */
} DMA_InitTypeDef;

DMA句柄 

typedef struct __DMA_HandleTypeDef
{DMA_Channel_TypeDef        *Instance; /*我们选择的DMA外设地址*/DMA_InitTypeDef            Init;  /*DMA初始化结构体*/HAL_LockTypeDef            Lock; /*DMA句柄锁*/__IO HAL_DMA_StateTypeDef  State; /*DMA传输状态*/void                       *Parent;/*用于存储一个指向父对象的指针,便于对象间的层级关联 */void                       (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma);     /*DMA转运完成回调函数 */void                       (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*DMA转运过半回调函数 */void                       (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma);    /*DMA转运出错回调函数 */void                       (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma);    /*DMA转运传输被异常终止回调函数*/__IO uint32_t              ErrorCode; /*DMA错误类型*/DMA_TypeDef                *DmaBaseAddress; /*DMA的基地址*/uint32_t                   ChannelIndex; /*DMA通道索引*/} DMA_HandleTypeDef;    

DMA初始化相关函数 

HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef HAL_DMA_DeInit (DMA_HandleTypeDef *hdma);

DMA运行函数,前面两个是开启DMA传输函数,之间两个是DMA中断函数,最后一个DMA轮询函数,询问DMA的传输状态。 

HAL_StatusTypeDef HAL_DMA_Start (DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout);

DMA状态获取函数,错误获取函数。 

HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma);
uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma);

 DMA数据转运

DMA的设置就这么点,和标准库相比,他把原地址和目标地址,传输长度放到了开始函数里面,更加方便我们的数据传输,以及DMA通道的重复利用。

使用memtomem模式,DMA1的通道1,优先级为中断,模式为普通模式,原地址自增,目标地址自增,传输的数据大小都为字节大小。

江科大的DMA初始化函数里面,首先就是失能了DMA,这样一开始初始化的时候就不会直接开始数据传递,容纳后在传输的函数里面,再次失能DMA,在写入传输次数,才开始使能DMA,DMA使能后就开始传输,等待传输完成,清除传输完成标志位。

HAL_DMA_Start() 在循环中重复调用却只执行一次,这是因为 STM32 HAL 库的 DMA 设计机制导致的,按照江科大的写入传输计数器,指定将要转运的次数,本质就是修改CNDTR寄存器,我们对hal库进行修改CNDTR寄存器操作就能正常实现江科大的功能,但是HAL_DMA_Start在正常模式下只能调用一次,按照豆包的说法,就是正常模式调用一次后,硬件自动禁用通道(CCR 的 EN 位清零),但 HAL 库内部状态可能仍标记为 “忙碌”,从而在start函数里面对DMA通道状态的判断的时候出错,导致不能正常开启转运。

if(HAL_DMA_Start(&hdma_memtomem_dma1_channel1, (uint32_t)DataA, (uint32_t)DataB, 4)==HAL_BUSY) DataA[0]+=10;

通过这个判断句,我们可以清晰的看出确实如此,多次调用DMA_Start的时候一直显示的就是DMA在忙碌状态,任何解决这个忙碌状态才是更需要思考的部分。

而直接修改传输次数,在传输完成的时候,CNDTR为0,我们修改了传输次数,DMA就继续传输,而不会对DMA的状态进行判断,跳过了DMA的状态判断,进而能够完成数据的传输。

初始化的校准部分我们通过

HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc)

来完成,这是在ADC_Ex里面。 

void MyDMA_Transfer(void)
{   __HAL_DMA_DISABLE(&hdma_memtomem_dma1_channel1);// 启动 DMA 传输hdma_memtomem_dma1_channel1.Instance->CNDTR = 4;//if(HAL_DMA_Start(&hdma_memtomem_dma1_channel1, (uint32_t)DataA, (uint32_t)DataB, 4)==HAL_BUSY) DataA[0]+=10;__HAL_DMA_ENABLE(&hdma_memtomem_dma1_channel1);while(__HAL_DMA_GET_FLAG(&hdma_memtomem_dma1_channel1, DMA_FLAG_TC1) == RESET)// 清除完成标志__HAL_DMA_CLEAR_FLAG(&hdma_memtomem_dma1_channel1, DMA_FLAG_TC1);
}

在主函数前进行一次DMA的Start,然后在循环里面不断设置传输次数

HAL_DMA_Start(&hdma_memtomem_dma1_channel1, (uint32_t)DataA, (uint32_t)DataB, 4);

把转换函数改成这个hal库的函数即可,其余的不需要我们的操作。

DMA+AD多通道

DMA+AD多通道就是DMA在外设与寄存器中间进行数据传输的最好例子,也是DMA帮助外设传递数据不需要CPU干预的最好验证。

因为我们模式是连续转换模式,扫描模式,所以配置ADC的时候就得把转换通道修改成我们所用到的四个通道,并对通道的序号进行排序扫描。他就会按照通道0,1,2,3,这样的顺序进行扫描,再回到0123不断进行,再扫描结束后会把转换结果发送到ADC规则组存储器,DMA在这个时候取走数据然后传输到我们指定的位置即可,所以对于原地址,不需要自增,目标地址就需要不断自增,没转换完成一次,就自增一次,然后全部转换完成又重新从头开始转换,DMA转运的地址也重新从头开始传输。

DMA的配置 ,这边数据的长度变成了半字(16位),且外设地址不自增,存储器地址自增,模式也改成了循环模式。

二配置完成后,我们先在主函数前面校准一次ADC,再开启一次ADC_DMA转换,就能自己一直连续转换了,我们只需要在循环里面不断读取我们存放转移数据的数组内容即可。

但是这边就会发现问题,就是OLED屏幕是全黑的,或者说OLED上面的数据变化缓慢且有明显的滞后性。我网上找了B站UP主野生绿波电龙看他的视频他也出现了这个问题,他说是DMA中断自动开启了,导致中断频繁主程序不能正常运行,我按照他视频内的方法:

把Force DMA channels Interrupts关闭,再把DMA的全局中断使能关掉。

这样下来程序就能正常运行了,这也给我们一个BUG的寻找方法,我们不仅要对代码进行差错,还得对代码的逻辑性进行查询错误,比如说中断的频繁触发导致主程序不能正常运行,这个点我们也得记下来,以后说不定就会遇到这类型的BUG。

HAL_ADCEx_Calibration_Start(&hadc1);//校准ADC
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)AD_Value,4);

 再主函数前面校准ADC后启动一次ADC_DMA传输即可自动连续扫描传输。

配置无误且关掉了DMA中断就能正常显示了。

http://www.dtcms.com/wzjs/468687.html

相关文章:

  • 个人网站推广 公司seo主要做哪些工作
  • 微信网站建设收费标准win10优化工具
  • 设计制作我的汽车网站seo培训
  • 玩具网站建设策划书网站托管维护
  • 网站布局类型百度新闻发布平台
  • 专门做悬疑推理小说的阅读网站成都业务网络推广平台
  • 口碑营销平台企业seo关键字优化
  • 郑州网站排名优化公司seo实战培训教程
  • 新网 网站空间今天今日头条新闻
  • 网站优化软件排名优化公司搜索seo
  • 香港做网站找谁淘客推广怎么做
  • 模拟网站建设软件域名注册需要多少钱?
  • wordpress+4.5seo查询站长工具
  • 网站编辑是什么工作东莞营销外包公司
  • 电子商务网站建设优势如何在百度发布广告信息
  • jquery 手机网站开发免费国外ddos网站
  • 大连做网站哪家好一点百度竞价排名又叫
  • vs平台做网站seo软件工具
  • 做网站 绑定域名今日国际新闻摘抄十条
  • 大余县网站深圳排名seo公司
  • 化妆品网站建设站长之家查询网
  • 网站开发制作阶段的说课稿搜索引擎是网站吗
  • 做网站的参考文献有哪些seo如何快速排名百度首页
  • 专业集团门户网站建设服务商株洲seo推广
  • 搜狗竞价绑定网站要求知名品牌营销策划案例
  • 怎么创建网站 优帮云电商培训基地
  • 济南网站制作*推搜点无锡百度竞价
  • 招牌做的好的网站保定百度首页优化
  • WordPress会员密码查看做百度seo
  • 旅游网站设计思路seo关键词优化费用