你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32Cube HAL DMA传输

[复制链接]
STMCU小助手 发布时间:2022-4-7 15:34
一、原理图

L$D(E9(U2FSS881TGD2@_%Q.png

二、 CubeMX配置

Step1.打开 STM32CubeMX,点击“New Project”,选择芯片型号,STM32F103VETx。

MG$E]IKM_FJEOYN)KJYV)`Q.png

Step2.选择时钟源,并配置时钟树。选择Crystal/Ceramic Resonator,并配置系统时钟为72M。

7RXFX8MLB3`ES{@AY_Z]3.png

L9Y`A_O]RE7U~9(D(ZIM[5Q.png

Step3.配置SYS,我们这里选择的是Serial Wire。(正常情况配置不配置不影响,debug可以使用。但是你不可以把这两个引脚用于其他复用功能,如果用于其他复用功能,debug就不起作用了。)

PZ1H1IW]}IB61W7AZ6)H]1L.png

Step4.串口配置(主要为了在串口调试助手显示测试的电压),因为没有用到中断和DMA所以我们就不过多讲解。

V7TD{2XU2}$}H_6X2H7[7(Q.png

IFGW@R}Z471`ER{_EUMUO7H.png

Step5.ADC的配置

]61ZJ1Z0M1EHWND%BQO61KI.png

[K~5B[5{Y3@NDA{N11YHL9R.png

Step6.因为多个通道需要使用到DMA传输到内存,否则ADC的存放转换数据的寄存器会不断覆盖上一个转换的数据。DMA模式:循环模式,重复传输,而常规模式则是传输1次。地址自增,因为ADC外设本身就只有一个寄存器所以不存在地址自增的情况,而内存是需要地址自增来存放不同通道的转换结果,如果不自增,则会覆盖上一次的结果。数据宽度:根据传输数据决定,因为此次传输的是12位的数据,所以使用半字(2个字节)就可以了。

XP1FE3[%XMP6ECCPOX%4S.png

$M[M2WZ97C%5ZZ)GHAPS.png

6(YYA}W@(CDYAJ]%UFT`21Q.png

到这里关于ADC参数配置基本已经完成,只需要根据之前文章《STM32Cube HAL:GPIO输入/输出(一)》Step4-Step8,设置相关工程参数和生成代码。

三、添加功能代码

1、我们等会会向串口调试助手发送数据,进行实验结果的验证。 发送数据我们采用printf函数,所有需要重定向c库函数printf到串口。注意使用时需要在keil设置中勾选微库(use mircolib),同时需要添加头文件#include <stdio.h>。重定向代码如下(usart.c)

  1. //重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
  2. int fputc(int ch, FILE *f)
  3. {
  4.         /* 发送一个字节数据到串口DEBUG_USART */
  5.         HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);        
  6.         
  7.         return (ch);
  8. }

  9. //重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
  10. int fgetc(FILE *f)
  11. {               
  12.         int ch;
  13.         HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);        
  14.         return (ch);
  15. }
复制代码

   2、定义相关变量,以及使能相关ADC和处理代码(main.c)

  1. //全局变量
  2. uint16_t conv_value[6];//用于存放DMA传输的数据
  3. float voltage[6];//计算后的电压
复制代码
  1. //使能相关外设
  2. HAL_ADC_Start_DMA(&hadc1,(uint32_t*)conv_value,6);//开启ADC转换以及DMA传输,6是DMA传输的次<span style="background-color: rgb(255, 255, 255);">数</span>
复制代码
  1. //在WHILE(1)中,输出电压值
  2. while (1)
  3.   {
  4.                 voltage[0]=(float)conv_value[0]*3.3/4096;//通过转化的值计算电压值
  5.                 voltage[1]=(float)conv_value[1]*3.3/4096;
  6.                 voltage[2]=(float)conv_value[2]*3.3/4096;
  7.                 voltage[3]=(float)conv_value[3]*3.3/4096;
  8.                 voltage[4]=(float)conv_value[4]*3.3/4096;
  9.                 voltage[5]=(float)conv_value[5]*3.3/4096;
  10.                
  11.                 printf("\n\rCH0 voltage=%.2fV\n\r",voltage[0]);//输出电压值
  12.                 printf("\n\rCH1 voltage=%.2fV\n\r",voltage[1]);
  13.                 printf("\n\rCH2 voltage=%.2fV\n\r",voltage[2]);
  14.                 printf("\n\rCH3 voltage=%.2fV\n\r",voltage[3]);
  15.                 printf("\n\rCH4 voltage=%.2fV\n\r",voltage[4]);
  16.                 printf("\n\rCH5 voltage=%.2fV\n\r",voltage[5]);
  17.                
  18.                 HAL_Delay(1000);//延时1秒        
  19.   }
复制代码


在实验中主要注意的是函数

HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);

hadc:adc句柄

pData:buffer缓冲区指针

Length:传输的数目(以数据宽度为单位)

例:    1:5个通道,每个通道传输1个,一共传输5个 。那么Length=5;

           2:1个通道,每个通道传输5个,一共传输5个。那么Length=5;

关于这个函数的理解,如果有错误的地方,欢迎指出。

关于length的说法,网上有些文章是说这个Length是和传输的数据宽度有关的,如果传输的是 word的话,那么Length,有多少通道就设置多少;如果是half word,则Length,是通道数的2倍。(暂时没理解)


收藏 评论0 发布时间:2022-4-7 15:34

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版