DMA

DMA

stm32cubemx教程之DMA的MemToMem例子,即数据从flash到sram的DMA操作

软件教程l1w1w1 回复了问题 • 6 人关注 • 4 个回复 • 7181 次浏览 • 2019-11-06 16:22 • 来自相关话题

STM32F407discovery DMA1 用CUBEMX无法配置

回复

问题困惑抵触 发起了问题 • 1 人关注 • 0 个回复 • 47 次浏览 • 2019-10-19 08:03 • 来自相关话题

怎么实现timer 触发DMA

回复

问题困惑lost_resister 发起了问题 • 1 人关注 • 0 个回复 • 112 次浏览 • 2019-09-08 10:13 • 来自相关话题

使用DMA 发送 SPI 数据发现,HAL_SPI_Transmit_DMA发送 数据给TFt240*240 的分辨率数据

回复

问题困惑V-Robot 发起了问题 • 1 人关注 • 0 个回复 • 292 次浏览 • 2019-08-13 15:16 • 来自相关话题

F4使用DMA+TIM实现指定个数脉冲,占空比可调(dshot300电调协议)

回复

问题困惑John Watson 发起了问题 • 1 人关注 • 0 个回复 • 334 次浏览 • 2019-07-31 15:43 • 来自相关话题

关于STM32F0的USART采用DMA循环模式接收的设想

回复

问题困惑public_rtos 回复了问题 • 1 人关注 • 1 个回复 • 409 次浏览 • 2019-07-30 10:03 • 来自相关话题

stm32 f7 nucleo 输入捕获 触发不了DMA ?

回复

问题困惑™✔ 发起了问题 • 1 人关注 • 0 个回复 • 432 次浏览 • 2019-03-27 19:39 • 来自相关话题

求大神帮我判断下 STM32 回调函数 HAL_ADC_ConvCpltCallback 的理解是否正确

回复

问题困惑sun0727 发起了问题 • 3 人关注 • 0 个回复 • 5159 次浏览 • 2017-09-14 23:04 • 来自相关话题

一直不理解DMA不需要耗系统时间的原因,今天做了个实验才终于理解了,O(∩_∩)O哈!

经验分享xiaohuihui 回复了问题 • 10 人关注 • 3 个回复 • 4282 次浏览 • 2016-12-17 15:22 • 来自相关话题

(转)串口可以配置成用DMA的方式接收数据,不过DMA需要定长才能产生接收中断,如何接收可变长度的数据呢?

经验分享~*静ヅ清晰._ 回复了问题 • 5 人关注 • 3 个回复 • 3787 次浏览 • 2016-05-23 13:10 • 来自相关话题

(转)与DMA的那些事 , DMA在外设与存储器之间的应用举例!

经验分享admin 发表了文章 • 0 个评论 • 2064 次浏览 • 2016-03-02 09:16 • 来自相关话题

参考手册上是这样介绍DMA的:用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。从上面我们可以看到DMA就好比是个“包邮的快递”一样,可以不收钱(不占用CPU)帮我们送快递(传递数据),有这等便宜岂能放过,我们必须要“用用用”!
1、DMA写SD卡
我最开始使用DMA是写SD卡,因为STM32的SPI在连续传递数据时字节和字节之间有很大的时间间隔,这导致了写一个扇区需要很长的时间,经过很多测试发现字节之间的间隔没法很好的被优化掉,所以就考虑用DMA写SD卡了。使用DMA写SD卡时只需设置好要写的数据,然后使能DMA传输完成中断,在中断中判断写数据是否成功。
如果使用常规的SPI写SD没有问题,那么修改为SPI的DMA模式写SD就卡就比较简单了。只需要修改下面几个函数即可。
1) 在写512字节时使用DMA传输





2) 在中断函数中进行判断即可void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
uint8_t t,s;
//扇区写完后发送校验字节
SPI2_ReadWriteByte(0xFF);
SPI2_ReadWriteByte(0xFF);
for(s = 0;s < 255;s++)
{
//接收响应
t = SPI2_ReadWriteByte(0xFF);
if((t&0x1F)==0x05)
{
SD_DMA_Write_Status = Status_OK;
break;
}
}
if(s == 0xff)
{
s = s;
}
SD_DisSelect();

}
2、DMA传输多通道ADC采集数据
这个测试使用NUCLEO-STM32F410RB,我们先初始化4个通道的ADC输出,然后用DMA将转换的数据传到数组中。
  4个通道配置如下:










然后在main函数中开始adc的转换:#include "main.h"

__IO uint16_t uhADCxConvertedValue[4];
int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
ADC1_Init();
ADC1_Config();
HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&uhADCxConvertedValue, 4);

while(1)
{

}
}



首先悬空4个输入引脚,从转换结果可以看到ADC的值为随机值,这也说明了可以使用悬空ADC引脚的方法来产生随机数是可行的。










将其中的2个通道接地,可以看到ADC的值接近0





3、使用DMA和串口空闲中断接收不定长数据
这个测试也使用NUCLEO-STM32F410RB。串口在接收数据时使用空闲中断和DMA接收不定长的数据,在发送时使用DMA发送。使用这个方法能够很方便的接收不定长的数据,但是也有一些限制,实际使用中如果出现问题要根据需要优化。
需要注意的是使用HAL库要自己写个回调函数如下:





在main中我们将PC端发送的数据返回到PC端:#include "main.h"

int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
while(1)
{
if(U1_Rxlen)
{
HAL_UART_Transmit_DMA(&UARTHandle,aU3RxBuff,U1_Rxlen);
U1_Rxlen = 0;
}
}
}



发送不同长度的数据,可以看到都能够正确接收:




上面只是DMA的几个最简单的使用,因为比较常用而且简单,所以并没有详细的叙述,具体可以参考代码。测试代码是使用hal写的,明白了原理很容易转换为标准库。DMA在其他的外设也有很多可以使用的场合,合理使用DMA能起到事半功倍的效果
 
文中所提到的相关代码,在本站百度网盘中[与DMA的那些事代码]中可下载
 
原帖地址:http://www.stmcu.org/module/forum/thread-605178-1-1.html
感谢creep分享 查看全部
参考手册上是这样介绍DMA的:用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。从上面我们可以看到DMA就好比是个“包邮的快递”一样,可以不收钱(不占用CPU)帮我们送快递(传递数据),有这等便宜岂能放过,我们必须要“用用用”!
1、DMA写SD卡
我最开始使用DMA是写SD卡,因为STM32的SPI在连续传递数据时字节和字节之间有很大的时间间隔,这导致了写一个扇区需要很长的时间,经过很多测试发现字节之间的间隔没法很好的被优化掉,所以就考虑用DMA写SD卡了。使用DMA写SD卡时只需设置好要写的数据,然后使能DMA传输完成中断,在中断中判断写数据是否成功。
如果使用常规的SPI写SD没有问题,那么修改为SPI的DMA模式写SD就卡就比较简单了。只需要修改下面几个函数即可。
1) 在写512字节时使用DMA传输

QQ图片20160302090653.jpg

2) 在中断函数中进行判断即可
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
uint8_t t,s;
//扇区写完后发送校验字节
SPI2_ReadWriteByte(0xFF);
SPI2_ReadWriteByte(0xFF);
for(s = 0;s < 255;s++)
{
//接收响应
t = SPI2_ReadWriteByte(0xFF);
if((t&0x1F)==0x05)
{
SD_DMA_Write_Status = Status_OK;
break;
}
}
if(s == 0xff)
{
s = s;
}
SD_DisSelect();

}

2、DMA传输多通道ADC采集数据
这个测试使用NUCLEO-STM32F410RB,我们先初始化4个通道的ADC输出,然后用DMA将转换的数据传到数组中。
  4个通道配置如下:

212624litd2fmbbyw2u6hu.jpg


212624ftpntnwmhehbmpei.jpg

然后在main函数中开始adc的转换:
#include "main.h"

__IO uint16_t uhADCxConvertedValue[4];
int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
ADC1_Init();
ADC1_Config();
HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&uhADCxConvertedValue, 4);

while(1)
{

}
}



首先悬空4个输入引脚,从转换结果可以看到ADC的值为随机值,这也说明了可以使用悬空ADC引脚的方法来产生随机数是可行的。

212625iz9q94xo44999g0v.jpg


212625ywppmbvs5sz9x5w8.jpg

将其中的2个通道接地,可以看到ADC的值接近0
213833qxtfjfn9ln44pxxn.png


3、使用DMA和串口空闲中断接收不定长数据
这个测试也使用NUCLEO-STM32F410RB。串口在接收数据时使用空闲中断和DMA接收不定长的数据,在发送时使用DMA发送。使用这个方法能够很方便的接收不定长的数据,但是也有一些限制,实际使用中如果出现问题要根据需要优化。
需要注意的是使用HAL库要自己写个回调函数如下:

214207ajqgjgxabaq4dge1.jpg

在main中我们将PC端发送的数据返回到PC端:
#include "main.h"

int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
while(1)
{
if(U1_Rxlen)
{
HAL_UART_Transmit_DMA(&UARTHandle,aU3RxBuff,U1_Rxlen);
U1_Rxlen = 0;
}
}
}



发送不同长度的数据,可以看到都能够正确接收:
214358hv9zr89q8qmkrg5r.jpg

上面只是DMA的几个最简单的使用,因为比较常用而且简单,所以并没有详细的叙述,具体可以参考代码。测试代码是使用hal写的,明白了原理很容易转换为标准库。DMA在其他的外设也有很多可以使用的场合,合理使用DMA能起到事半功倍的效果
 
文中所提到的相关代码,在本站百度网盘中[与DMA的那些事代码]中可下载
 
原帖地址:http://www.stmcu.org/module/forum/thread-605178-1-1.html
感谢creep分享

STM32F207 CUBE 串口 DMA变长接收小结

经验分享自由泳 发表了文章 • 13 个评论 • 5477 次浏览 • 2015-03-25 07:54 • 来自相关话题

感谢【叫兽】担/xin的耐心指导,把我的做法发来请大家指正:
DMA变长接收,采取串口接受中断和空闲中断结合的办法。接手前先开串口接收中断、关空闲中断
一、当收到第一个字符时,关接收中断、开空闲中断,调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收。
二、当串口没有数据接收时,进入空闲中断,此时调用HAL_DMA_Abort(&hdma_usart3_rx);停掉DMA接收,读取接收的内容;
三、读取完接收内容后,再打开接收中断、关闭空闲中断,再次调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收,如此往复。

注意:cubemx中设置DMA接收为Normal,开DMA全局中断和串口全局中断

核心代码如下:


void USART3_IRQHandler(void)
{
/[i] USER CODE BEGIN USART3_IRQn 0 [/i]/

#if 1
uint32_t tmp1 = 0, tmp2 = 0,i,rx_len;

/[i] UART RXNE interrupt occurred ------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_RXNE);
if((tmp1 != RESET) && (tmp2 != RESET))
{

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_DISABLE_IT(&huart3, UART_IT_RXNE);//close rx int
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);//open idel int
}

/[i] UAR TIDLE interrupt occurred -------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_IDLE);
if((tmp1 != RESET) && (tmp2 != RESET))
{
HAL_DMA_Abort(&hdma_usart3_rx);

rx_len = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);

if(rx_len < UART_RX_MAXLEN)
{
printf("\r\nUart3 DMA recv len = %d",UART_RX_MAXLEN-rx_len);

for(i=0;i<UART_RX_MAXLEN-rx_len;i++)
{
if(i == 0) printf("\r\n");

printf(" %3x",uart3_RX_data[i]);
}
}

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);//open rx int
__HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE);//close idel int

}

#endif


/[i] USER CODE END USART3_IRQn 0 [/i]/
HAL_UART_IRQHandler(&huart3);
/[i] USER CODE BEGIN USART3_IRQn 1 [/i]/

/[i] USER CODE END USART3_IRQn 1 [/i]/
}


经简单测试,不知道是否有隐含问题,请指点!
再次感谢叫兽】担/xin的耐心指导!!!

总觉得这种方法没有 DMA循环接收好,哪位大侠指点一下循环方式! 查看全部
感谢【叫兽】担/xin的耐心指导,把我的做法发来请大家指正:
DMA变长接收,采取串口接受中断和空闲中断结合的办法。接手前先开串口接收中断、关空闲中断
一、当收到第一个字符时,关接收中断、开空闲中断,调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收。
二、当串口没有数据接收时,进入空闲中断,此时调用HAL_DMA_Abort(&hdma_usart3_rx);停掉DMA接收,读取接收的内容;
三、读取完接收内容后,再打开接收中断、关闭空闲中断,再次调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收,如此往复。

注意:cubemx中设置DMA接收为Normal,开DMA全局中断和串口全局中断

核心代码如下:


void USART3_IRQHandler(void)
{
/[i] USER CODE BEGIN USART3_IRQn 0 [/i]/

#if 1
uint32_t tmp1 = 0, tmp2 = 0,i,rx_len;

/[i] UART RXNE interrupt occurred ------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_RXNE);
if((tmp1 != RESET) && (tmp2 != RESET))
{

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_DISABLE_IT(&huart3, UART_IT_RXNE);//close rx int
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);//open idel int
}

/[i] UAR TIDLE interrupt occurred -------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_IDLE);
if((tmp1 != RESET) && (tmp2 != RESET))
{
HAL_DMA_Abort(&hdma_usart3_rx);

rx_len = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);

if(rx_len < UART_RX_MAXLEN)
{
printf("\r\nUart3 DMA recv len = %d",UART_RX_MAXLEN-rx_len);

for(i=0;i<UART_RX_MAXLEN-rx_len;i++)
{
if(i == 0) printf("\r\n");

printf(" %3x",uart3_RX_data[i]);
}
}

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);//open rx int
__HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE);//close idel int

}

#endif


/[i] USER CODE END USART3_IRQn 0 [/i]/
HAL_UART_IRQHandler(&huart3);
/[i] USER CODE BEGIN USART3_IRQn 1 [/i]/

/[i] USER CODE END USART3_IRQn 1 [/i]/
}


经简单测试,不知道是否有隐含问题,请指点!
再次感谢叫兽】担/xin的耐心指导!!!

总觉得这种方法没有 DMA循环接收好,哪位大侠指点一下循环方式!

记录stm32cubemx中I2C的DMA板卡之间的传输设置

软件教程admin 发表了文章 • 3 个评论 • 5491 次浏览 • 2014-11-07 09:23 • 来自相关话题

I2c板卡之间连接示意图





先上图,后面解释..




















2楼注释 查看全部
I2c板卡之间连接示意图

5.png

先上图,后面解释..

1.png


2.png


3.png


4.png

2楼注释

stm32cube中文教程:AD用TIM8定时采集,uart3输出

软件教程admin 发表了文章 • 15 个评论 • 5140 次浏览 • 2014-10-13 23:45 • 来自相关话题

stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/ 查看全部
stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

stm32cubemx教程之DMA的MemToMem例子,即数据从flash到sram的DMA操作

回复

软件教程l1w1w1 回复了问题 • 6 人关注 • 4 个回复 • 7181 次浏览 • 2019-11-06 16:22 • 来自相关话题

STM32F407discovery DMA1 用CUBEMX无法配置

回复

问题困惑抵触 发起了问题 • 1 人关注 • 0 个回复 • 47 次浏览 • 2019-10-19 08:03 • 来自相关话题

怎么实现timer 触发DMA

回复

问题困惑lost_resister 发起了问题 • 1 人关注 • 0 个回复 • 112 次浏览 • 2019-09-08 10:13 • 来自相关话题

使用DMA 发送 SPI 数据发现,HAL_SPI_Transmit_DMA发送 数据给TFt240*240 的分辨率数据

回复

问题困惑V-Robot 发起了问题 • 1 人关注 • 0 个回复 • 292 次浏览 • 2019-08-13 15:16 • 来自相关话题

F4使用DMA+TIM实现指定个数脉冲,占空比可调(dshot300电调协议)

回复

问题困惑John Watson 发起了问题 • 1 人关注 • 0 个回复 • 334 次浏览 • 2019-07-31 15:43 • 来自相关话题

关于STM32F0的USART采用DMA循环模式接收的设想

回复

问题困惑public_rtos 回复了问题 • 1 人关注 • 1 个回复 • 409 次浏览 • 2019-07-30 10:03 • 来自相关话题

stm32 f7 nucleo 输入捕获 触发不了DMA ?

回复

问题困惑™✔ 发起了问题 • 1 人关注 • 0 个回复 • 432 次浏览 • 2019-03-27 19:39 • 来自相关话题

求大神帮我判断下 STM32 回调函数 HAL_ADC_ConvCpltCallback 的理解是否正确

回复

问题困惑sun0727 发起了问题 • 3 人关注 • 0 个回复 • 5159 次浏览 • 2017-09-14 23:04 • 来自相关话题

一直不理解DMA不需要耗系统时间的原因,今天做了个实验才终于理解了,O(∩_∩)O哈!

回复

经验分享xiaohuihui 回复了问题 • 10 人关注 • 3 个回复 • 4282 次浏览 • 2016-12-17 15:22 • 来自相关话题

(转)串口可以配置成用DMA的方式接收数据,不过DMA需要定长才能产生接收中断,如何接收可变长度的数据呢?

回复

经验分享~*静ヅ清晰._ 回复了问题 • 5 人关注 • 3 个回复 • 3787 次浏览 • 2016-05-23 13:10 • 来自相关话题

(转)与DMA的那些事 , DMA在外设与存储器之间的应用举例!

经验分享admin 发表了文章 • 0 个评论 • 2064 次浏览 • 2016-03-02 09:16 • 来自相关话题

参考手册上是这样介绍DMA的:用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。从上面我们可以看到DMA就好比是个“包邮的快递”一样,可以不收钱(不占用CPU)帮我们送快递(传递数据),有这等便宜岂能放过,我们必须要“用用用”!
1、DMA写SD卡
我最开始使用DMA是写SD卡,因为STM32的SPI在连续传递数据时字节和字节之间有很大的时间间隔,这导致了写一个扇区需要很长的时间,经过很多测试发现字节之间的间隔没法很好的被优化掉,所以就考虑用DMA写SD卡了。使用DMA写SD卡时只需设置好要写的数据,然后使能DMA传输完成中断,在中断中判断写数据是否成功。
如果使用常规的SPI写SD没有问题,那么修改为SPI的DMA模式写SD就卡就比较简单了。只需要修改下面几个函数即可。
1) 在写512字节时使用DMA传输





2) 在中断函数中进行判断即可void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
uint8_t t,s;
//扇区写完后发送校验字节
SPI2_ReadWriteByte(0xFF);
SPI2_ReadWriteByte(0xFF);
for(s = 0;s < 255;s++)
{
//接收响应
t = SPI2_ReadWriteByte(0xFF);
if((t&0x1F)==0x05)
{
SD_DMA_Write_Status = Status_OK;
break;
}
}
if(s == 0xff)
{
s = s;
}
SD_DisSelect();

}
2、DMA传输多通道ADC采集数据
这个测试使用NUCLEO-STM32F410RB,我们先初始化4个通道的ADC输出,然后用DMA将转换的数据传到数组中。
  4个通道配置如下:










然后在main函数中开始adc的转换:#include "main.h"

__IO uint16_t uhADCxConvertedValue[4];
int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
ADC1_Init();
ADC1_Config();
HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&uhADCxConvertedValue, 4);

while(1)
{

}
}



首先悬空4个输入引脚,从转换结果可以看到ADC的值为随机值,这也说明了可以使用悬空ADC引脚的方法来产生随机数是可行的。










将其中的2个通道接地,可以看到ADC的值接近0





3、使用DMA和串口空闲中断接收不定长数据
这个测试也使用NUCLEO-STM32F410RB。串口在接收数据时使用空闲中断和DMA接收不定长的数据,在发送时使用DMA发送。使用这个方法能够很方便的接收不定长的数据,但是也有一些限制,实际使用中如果出现问题要根据需要优化。
需要注意的是使用HAL库要自己写个回调函数如下:





在main中我们将PC端发送的数据返回到PC端:#include "main.h"

int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
while(1)
{
if(U1_Rxlen)
{
HAL_UART_Transmit_DMA(&UARTHandle,aU3RxBuff,U1_Rxlen);
U1_Rxlen = 0;
}
}
}



发送不同长度的数据,可以看到都能够正确接收:




上面只是DMA的几个最简单的使用,因为比较常用而且简单,所以并没有详细的叙述,具体可以参考代码。测试代码是使用hal写的,明白了原理很容易转换为标准库。DMA在其他的外设也有很多可以使用的场合,合理使用DMA能起到事半功倍的效果
 
文中所提到的相关代码,在本站百度网盘中[与DMA的那些事代码]中可下载
 
原帖地址:http://www.stmcu.org/module/forum/thread-605178-1-1.html
感谢creep分享 查看全部
参考手册上是这样介绍DMA的:用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。从上面我们可以看到DMA就好比是个“包邮的快递”一样,可以不收钱(不占用CPU)帮我们送快递(传递数据),有这等便宜岂能放过,我们必须要“用用用”!
1、DMA写SD卡
我最开始使用DMA是写SD卡,因为STM32的SPI在连续传递数据时字节和字节之间有很大的时间间隔,这导致了写一个扇区需要很长的时间,经过很多测试发现字节之间的间隔没法很好的被优化掉,所以就考虑用DMA写SD卡了。使用DMA写SD卡时只需设置好要写的数据,然后使能DMA传输完成中断,在中断中判断写数据是否成功。
如果使用常规的SPI写SD没有问题,那么修改为SPI的DMA模式写SD就卡就比较简单了。只需要修改下面几个函数即可。
1) 在写512字节时使用DMA传输

QQ图片20160302090653.jpg

2) 在中断函数中进行判断即可
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
uint8_t t,s;
//扇区写完后发送校验字节
SPI2_ReadWriteByte(0xFF);
SPI2_ReadWriteByte(0xFF);
for(s = 0;s < 255;s++)
{
//接收响应
t = SPI2_ReadWriteByte(0xFF);
if((t&0x1F)==0x05)
{
SD_DMA_Write_Status = Status_OK;
break;
}
}
if(s == 0xff)
{
s = s;
}
SD_DisSelect();

}

2、DMA传输多通道ADC采集数据
这个测试使用NUCLEO-STM32F410RB,我们先初始化4个通道的ADC输出,然后用DMA将转换的数据传到数组中。
  4个通道配置如下:

212624litd2fmbbyw2u6hu.jpg


212624ftpntnwmhehbmpei.jpg

然后在main函数中开始adc的转换:
#include "main.h"

__IO uint16_t uhADCxConvertedValue[4];
int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
ADC1_Init();
ADC1_Config();
HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&uhADCxConvertedValue, 4);

while(1)
{

}
}



首先悬空4个输入引脚,从转换结果可以看到ADC的值为随机值,这也说明了可以使用悬空ADC引脚的方法来产生随机数是可行的。

212625iz9q94xo44999g0v.jpg


212625ywppmbvs5sz9x5w8.jpg

将其中的2个通道接地,可以看到ADC的值接近0
213833qxtfjfn9ln44pxxn.png


3、使用DMA和串口空闲中断接收不定长数据
这个测试也使用NUCLEO-STM32F410RB。串口在接收数据时使用空闲中断和DMA接收不定长的数据,在发送时使用DMA发送。使用这个方法能够很方便的接收不定长的数据,但是也有一些限制,实际使用中如果出现问题要根据需要优化。
需要注意的是使用HAL库要自己写个回调函数如下:

214207ajqgjgxabaq4dge1.jpg

在main中我们将PC端发送的数据返回到PC端:
#include "main.h"

int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
USART2_Init();
while(1)
{
if(U1_Rxlen)
{
HAL_UART_Transmit_DMA(&UARTHandle,aU3RxBuff,U1_Rxlen);
U1_Rxlen = 0;
}
}
}



发送不同长度的数据,可以看到都能够正确接收:
214358hv9zr89q8qmkrg5r.jpg

上面只是DMA的几个最简单的使用,因为比较常用而且简单,所以并没有详细的叙述,具体可以参考代码。测试代码是使用hal写的,明白了原理很容易转换为标准库。DMA在其他的外设也有很多可以使用的场合,合理使用DMA能起到事半功倍的效果
 
文中所提到的相关代码,在本站百度网盘中[与DMA的那些事代码]中可下载
 
原帖地址:http://www.stmcu.org/module/forum/thread-605178-1-1.html
感谢creep分享

STM32F207 CUBE 串口 DMA变长接收小结

经验分享自由泳 发表了文章 • 13 个评论 • 5477 次浏览 • 2015-03-25 07:54 • 来自相关话题

感谢【叫兽】担/xin的耐心指导,把我的做法发来请大家指正:
DMA变长接收,采取串口接受中断和空闲中断结合的办法。接手前先开串口接收中断、关空闲中断
一、当收到第一个字符时,关接收中断、开空闲中断,调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收。
二、当串口没有数据接收时,进入空闲中断,此时调用HAL_DMA_Abort(&hdma_usart3_rx);停掉DMA接收,读取接收的内容;
三、读取完接收内容后,再打开接收中断、关闭空闲中断,再次调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收,如此往复。

注意:cubemx中设置DMA接收为Normal,开DMA全局中断和串口全局中断

核心代码如下:


void USART3_IRQHandler(void)
{
/[i] USER CODE BEGIN USART3_IRQn 0 [/i]/

#if 1
uint32_t tmp1 = 0, tmp2 = 0,i,rx_len;

/[i] UART RXNE interrupt occurred ------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_RXNE);
if((tmp1 != RESET) && (tmp2 != RESET))
{

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_DISABLE_IT(&huart3, UART_IT_RXNE);//close rx int
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);//open idel int
}

/[i] UAR TIDLE interrupt occurred -------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_IDLE);
if((tmp1 != RESET) && (tmp2 != RESET))
{
HAL_DMA_Abort(&hdma_usart3_rx);

rx_len = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);

if(rx_len < UART_RX_MAXLEN)
{
printf("\r\nUart3 DMA recv len = %d",UART_RX_MAXLEN-rx_len);

for(i=0;i<UART_RX_MAXLEN-rx_len;i++)
{
if(i == 0) printf("\r\n");

printf(" %3x",uart3_RX_data[i]);
}
}

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);//open rx int
__HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE);//close idel int

}

#endif


/[i] USER CODE END USART3_IRQn 0 [/i]/
HAL_UART_IRQHandler(&huart3);
/[i] USER CODE BEGIN USART3_IRQn 1 [/i]/

/[i] USER CODE END USART3_IRQn 1 [/i]/
}


经简单测试,不知道是否有隐含问题,请指点!
再次感谢叫兽】担/xin的耐心指导!!!

总觉得这种方法没有 DMA循环接收好,哪位大侠指点一下循环方式! 查看全部
感谢【叫兽】担/xin的耐心指导,把我的做法发来请大家指正:
DMA变长接收,采取串口接受中断和空闲中断结合的办法。接手前先开串口接收中断、关空闲中断
一、当收到第一个字符时,关接收中断、开空闲中断,调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收。
二、当串口没有数据接收时,进入空闲中断,此时调用HAL_DMA_Abort(&hdma_usart3_rx);停掉DMA接收,读取接收的内容;
三、读取完接收内容后,再打开接收中断、关闭空闲中断,再次调用HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);开始接收,如此往复。

注意:cubemx中设置DMA接收为Normal,开DMA全局中断和串口全局中断

核心代码如下:


void USART3_IRQHandler(void)
{
/[i] USER CODE BEGIN USART3_IRQn 0 [/i]/

#if 1
uint32_t tmp1 = 0, tmp2 = 0,i,rx_len;

/[i] UART RXNE interrupt occurred ------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_RXNE);
if((tmp1 != RESET) && (tmp2 != RESET))
{

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_DISABLE_IT(&huart3, UART_IT_RXNE);//close rx int
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);//open idel int
}

/[i] UAR TIDLE interrupt occurred -------------------------------------[/i]/
tmp1 = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE);
tmp2 = __HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_IDLE);
if((tmp1 != RESET) && (tmp2 != RESET))
{
HAL_DMA_Abort(&hdma_usart3_rx);

rx_len = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);

if(rx_len < UART_RX_MAXLEN)
{
printf("\r\nUart3 DMA recv len = %d",UART_RX_MAXLEN-rx_len);

for(i=0;i<UART_RX_MAXLEN-rx_len;i++)
{
if(i == 0) printf("\r\n");

printf(" %3x",uart3_RX_data[i]);
}
}

HAL_UART_Receive_DMA(&huart3, uart3_RX_data, UART_RX_MAXLEN);

__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);//open rx int
__HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE);//close idel int

}

#endif


/[i] USER CODE END USART3_IRQn 0 [/i]/
HAL_UART_IRQHandler(&huart3);
/[i] USER CODE BEGIN USART3_IRQn 1 [/i]/

/[i] USER CODE END USART3_IRQn 1 [/i]/
}


经简单测试,不知道是否有隐含问题,请指点!
再次感谢叫兽】担/xin的耐心指导!!!

总觉得这种方法没有 DMA循环接收好,哪位大侠指点一下循环方式!

记录stm32cubemx中I2C的DMA板卡之间的传输设置

软件教程admin 发表了文章 • 3 个评论 • 5491 次浏览 • 2014-11-07 09:23 • 来自相关话题

I2c板卡之间连接示意图





先上图,后面解释..




















2楼注释 查看全部
I2c板卡之间连接示意图

5.png

先上图,后面解释..

1.png


2.png


3.png


4.png

2楼注释

stm32cube中文教程:AD用TIM8定时采集,uart3输出

软件教程admin 发表了文章 • 15 个评论 • 5140 次浏览 • 2014-10-13 23:45 • 来自相关话题

stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/ 查看全部
stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/