【STM32Cube HAL】DMA传输(八)

  实验内容:使用的ADC多通道采集,实现输出引脚电压的采集并通过串口打印至PC 端串口调试助手。(使用DMA传输数据)

一、原理图

二、 CubeMX配置

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

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

  

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

 

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

Step5.ADC的配置

 

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

 

 

 

 

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

三、添加功能代码

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

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

//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{		
	int ch;
	HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);	
	return (ch);
}

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

//全局变量
uint16_t conv_value[6];//用于存放DMA传输的数据
float voltage[6];//计算后的电压
 //使能相关外设
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)conv_value,6);//开启ADC转换以及DMA传输,6是DMA传输的次数

//在WHILE(1)中,输出电压值
 while (1)
  {
		voltage[0]=(float)conv_value[0]*3.3/4096;//通过转化的值计算电压值
		voltage[1]=(float)conv_value[1]*3.3/4096;
		voltage[2]=(float)conv_value[2]*3.3/4096;
		voltage[3]=(float)conv_value[3]*3.3/4096;
		voltage[4]=(float)conv_value[4]*3.3/4096;
		voltage[5]=(float)conv_value[5]*3.3/4096;
		
		printf("\n\rCH0 voltage=%.2fV\n\r",voltage[0]);//输出电压值
		printf("\n\rCH1 voltage=%.2fV\n\r",voltage[1]);
		printf("\n\rCH2 voltage=%.2fV\n\r",voltage[2]);
		printf("\n\rCH3 voltage=%.2fV\n\r",voltage[3]);
		printf("\n\rCH4 voltage=%.2fV\n\r",voltage[4]);
		printf("\n\rCH5 voltage=%.2fV\n\r",voltage[5]);
		
		HAL_Delay(1000);//延时1秒	
  }

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

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倍。(暂时没理解)

  • 15
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
下面是使用STM32 HAL库进行SPI DMA配置的步骤: 1. 启用DMA时钟 首先,需要开启DMA时钟。使用以下代码: ``` __HAL_RCC_DMA1_CLK_ENABLE(); // 开启DMA1时钟 ``` 2. 配置SPI 在使用DMA之前,需要正确配置SPI。使用CubeMX或手动配置SPI寄存器。 3. 配置DMA 在配置DMA之前,需要确定使用哪个DMA通道。可以在STM32的参考手册中查找可用DMA通道的列表。 使用以下代码配置DMA: ``` /* 配置DMA */ hdma_spi.Instance = DMA1_Channel3; hdma_spi.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_spi.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi.Init.MemInc = DMA_MINC_ENABLE; hdma_spi.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_spi.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi.Init.Mode = DMA_NORMAL; hdma_spi.Init.Priority = DMA_PRIORITY_HIGH; ``` 其中,`DMA1_Channel3`是DMA通道。 `Direction`设置为“内存到外设”,因为我们要将数据从内存传输到SPI外设。`PeriphInc`设置为“禁止”,因为在SPI传输期间外设地址不应该自动增加。`MemInc`设置为“使能”,因为我们要在传输期间增加存储器地址。数据对齐设为“字节对齐”,并将优先级设置为“高”。 4. 配置DMA传输 下一步是配置DMA传输。使用以下代码: ``` /* 配置DMA传输 */ HAL_DMA_Init(&hdma_spi); __HAL_LINKDMA(hspi, hdmatx, hdma_spi); ``` 其中,`HAL_DMA_Init()`函数初始化DMA通道,将`hdma_spi`结构体作为参数传递。`__HAL_LINKDMA()`函数将DMA通道链接到SPI发送通道。 5. 启用DMA传输 最后,启用DMA传输。使用以下代码: ``` HAL_SPI_Transmit_DMA(&hspi, (uint8_t*)tx_data, len); ``` 其中,`HAL_SPI_Transmit_DMA()`函数将SPI发送通道设置为DMA模式,并将`tx_data`和`len`作为参数传递。DMA传输现在应该已启动。 请注意,以上代码仅为示例。具体实现可能因使用的STM32型号和所需的DMA通道而异。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值