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

沧州企业做网站网站排名靠前的方法

沧州企业做网站,网站排名靠前的方法,巴南城乡建设网站,襄阳市做网站 优帮云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/433805.html

相关文章:

  • 北京网站搭建公司电话微信软文推广怎么做
  • 网站空间如何搬家大连网站建设
  • 装饰网站建设专家免费找客源软件
  • 做网站 郑州公司有哪些搜狗seo查询
  • 网站后台 批量上传深圳外包网络推广
  • 如何用java语言做网站色盲测试图片60张
  • 安微省建设厅田网站品牌宣传策略
  • 新手学做网站 电子书网站域名综合查询
  • 网站建设价目百度seo推广软件
  • 化工网站源码如何让网站快速收录
  • 无忧网站建设多少钱培训机构最新消息
  • 西安做网站找哪家公司好网页怎么做出来的
  • iosapp做网站济南seo网站排名关键词优化
  • 北辰做网站公司湖南关键词优化品牌价格
  • 法制建设网站短视频培训学校
  • 计算机web是什么意思哈尔滨企业网站seo
  • 怎样做网站的排名seo日常优化内容是什么
  • 为什么手机进网站乱码磁力狗最佳搜索引擎
  • 内蒙古自治区建设厅网站设计素材网站
  • 购物分享网站流量排名天津网络关键词排名
  • 中高风险地区最新名单seo工资水平
  • 外国网站域名在哪查seo 360
  • 网络运营商是干嘛的网站点击排名优化
  • 宁波雪窦山名山建设委员会网站线上推广是什么工作
  • 湖南响应式网站建设价位网站查询网
  • 怎么策划一个网站网络营销策划书步骤
  • 济南企业建站怎么样百度百家官网入口
  • 如何用asp.net做网站网络推广精准营销推广
  • 云南网站建设快速排名seo实战教程
  • 作词做曲网站windows优化大师值得买吗