STM32笔记_11(DMA—直接存储区访问)

DMA—直接存储区访问

DMA 简介

        DMA(Direct Memory Access)—直接存储器存取,它的主要功能是用来搬数据,但是不需要占用 CPU

        数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH

        DMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道。

        注意的是 DMA2 只存在于大容量的单片机中。

DMA 功能框图

DMA 请求

        通过 DMA 来传输数据,必须先给 DMA 控制器发送 DMA 请求,DMA 收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会启动 DMA 的传输,直到传输完毕。

        不同的 DMA 控制器的通道对应着不同的外设请求,具体见 DMA 请求映像表。

         其中 ADC3、 SDIO 和 TIM8 的 DMA 请求只在大容量产品中存在,这个在具体项目时要注意。

通道

        DMA 具有 12 个独立可编程的通道,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,每个通道对应不同的外设的 DMA 请求。

        虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。

仲裁器

        仲裁器管理 DMA 通道请求分为两个阶段。

                第一阶段属于软件阶段:有 4 个等级:非常高、高、中和低四个优先级。

                第二阶段属于硬件阶段:两个或以上的 DMA 通道请求设置的优先级一样,编号越低优先权越高,DMA1 控制器拥有高于 DMA2 控制器的优先级。

DMA 数据配置

        方向有三个:从外设到存储器,从存储器到外设,从存储器到存储器。

外设到存储器

        ADC 采集为例,DMA 外设寄存器的地址对应的就是 ADC数据寄存器的地址, DMA 存储器的地址就是我们自定义的变量(用来接收存储 AD 采集的数据)的地址。方向我们设置外设为源地址。

存储器到外设

        串口向电脑端发送数据为例,DMA 外设寄存器的地址对应的就是串口数据寄存器的地址, DMA 存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)的地址。方向我们设置外设为目标地址。

存储器到存储器

        内部 FLASH 向内部 SRAM 复制数据为例。DMA 外设寄存器的地址对应的就是内部 FLASH(我们这里把内部 FALSH 当作一个外设来看)的地址, DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部 FLASH 的数据)的地址。方向我们设置外设(即内部 FLASH)为源地址。

传输数据的单位        

        数据传输正确,源和目标地址存储的数据宽度还必须一致。

        串口向电脑发送数据为例,我们可以一次性给电脑发送很多数据,具体多少由 DMA_CNDTR配置,这是一个 32 位的寄存器,一次最多只能传输 65535 个数据。串口数据寄存器是 8 位的,所以我们定义的要发送的数据也必须是 8 位。在 DMA 控制器的控制下,还必须正确设置两边数据指针的增量模式。要发送的数据很多,每发送完一个,那么存储器的地址指针就应该加 1,而串口数据寄存器只有一个,那么外设的地址指针就固定不变。

传输完成标志

        每个 DMA 通道在 DMA 传输过半、传输完成和传输错误时都会有相应的标志位。

        传输完成还分两种模式,是一次传输还是循环传输

                一次传输:传输一次之后就停止。

                循环传输:一次传输完成之后又恢复第一次传输时的配置循环传输,不断的重复。

DMA 初始化结构体详解

typedef struct{ 
                uint32_t DMA_PeripheralBaseAddr; // 外设地址
                uint32_t DMA_MemoryBaseAddr; // 存储器地址
                uint32_t DMA_DIR; // 传输方向
                uint32_t DMA_BufferSize; // 传输数目
                uint32_t DMA_PeripheralInc; // 外设地址增量模式
                uint32_t DMA_MemoryInc; // 存储器地址增量模式
                uint32_t DMA_PeripheralDataSize; // 外设数据宽度
                uint32_t DMA_MemoryDataSize; // 存储器数据宽度
                uint32_t DMA_Mode; // 模式选择
                uint32_t DMA_Priority; // 通道优先级
                uint32_t DMA_M2M; // 存储器到存储器模式
} DMA_InitTypeDef;

1) DMA_PeripheralBaseAddr:外设地址,设定 DMA_CPAR 寄存器的值;一般设置为外设的数据寄存器地址,如果是存储器到存储器模式则设置为其中一个存储器地址。

2) DMA_Memory0BaseAddr:存储器地址,一般设置为我们自定义存储区的首地址。

3) DMA_DIR:传输方向选择,可选外设到存储器、存储器到外设。这里并没有存储器到存储器的方向选择,当使用存储器到存储器时,只需要把其中一个存储器当作外设使用即可。

4) DMA_BufferSize:设定待传输数据数目。

5) DMA_PeripheralInc:如果配置为 DMA_PeripheralInc_Enable,使能外设地址自动递增功能,一般外设都是只有一个数据寄存器,所以一般不会使能该位。

6) DMA_MemoryInc:如果配置为 DMA_MemoryInc_Enable,使能存储器地址自动递增功能,,我们自定义的存储区一般都是存放多个数据的,所以要使能存储器地址自动递增功能。

7) DMA_PeripheralDataSize:外设数据宽度,可选字节 (8 位)、半字 (16 位) 和字 (32 位)。

8) DMA_MemoryDataSize:存储器数据宽度,可选字节 (8 位)、半字 (16 位) 和字 (32 位),当外设和存储器之间传数据时,两边的数据宽度应该设置为一致大小。

9) DMA_Mode: DMA 传输模式选择,可选一次传输或者循环传输,ADC 采集是持续循环进行的,所以使用循环传输模式。

10) DMA_Priority:软件设置通道的优先级,有 4 个可选优先级分别为非常高、高、中和低, DMA 通道优先级只有在多个 DMA 通道同时使用时才有意义,如果是单个通道,优先级可以随便设置。

11) DMA_M2M:存储器到存储器模式,使用存储器到存储器时用到,可启动存储器到存储器模式。

DMA 存储器到存储器模式实验

编程要点

        1) 使能 DMA 时钟;

        2) 配置 DMA 数据参数;

        3) 使能 DMA,进行传输;

        4) 等待传输完成,并对源数据和目标地址数据进行比较。

 dma.c

#include "./dma/dma.h"

//定Source_Data组作为DMA传输数据源
//const关键字将Source_Data组变量定义为常量类型,表示数据存储在内部的FLASH中
const uint32_t Source_Data[BUFFER_SIZE]= {
                                    0x1,0x2,0x3,0x4,
                                    0x5,0x6,0x7,0x8,
                                    0x9,0xA,0xB,0xC,
                                    0xD,0xE,0xF,0x10,
                                    0x20,0x30,0x40,0x50,
                                    0x60,0x70,0x80,0x90,
                                    0xA0,0xB0,0xC0,0xD0,
                                    0xE0,0xF0,0x100,0x200};

//定义DMA传输目标存储器
//存储在内部的SRAM中
uint32_t Distination_Data[BUFFER_SIZE];

void DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStruct;
	// 开启DMA时钟
	RCC_AHBPeriphClockCmd(DMA_CLOCK,ENABLE);
	// 源数据地址
	DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)Source_Data; 
	// 目标地址
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Distination_Data;
	// 方向:外设到存储器(这里的外设是内部的FLASH)	
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
	// 传输大小	
	DMA_InitStruct.DMA_BufferSize = BUFFER_SIZE;
	// 外设(内部的FLASH)地址递增	    
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
	// 内存地址递增
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
	// 外设数据单位	
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
	// 内存数据单位
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
	// DMA模式,一次或者循环模式
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; 
	// 优先级:高	
	DMA_InitStruct.DMA_Priority = DMA_Priority_High;
	// 使能内存到内存的传输
	DMA_InitStruct.DMA_M2M = DMA_M2M_Enable;
	// 配置DMA通道		   
	DMA_Init(DMA_CHANNEL,&DMA_InitStruct);
	//清除DMA数据流传输完成标志位
	DMA_ClearFlag(DMA_FLAG_TC);
	// 使能DMA
	DMA_Cmd(DMA_CHANNEL,ENABLE);
}

//判断两个数据是否相等
uint8_t DataCmp(const uint32_t *pData1,uint32_t *pData2,uint16_t DataLen)
{
	while(DataLen--)
	{
		if(*pData1 != *pData2)
		{
			return 0;
		}
		pData1++;
		pData2++;
	}
	return 1;
}
	


dma.h

#ifndef _DMA_H
#define _DMA_H

#include "stm32f10x.h"

// 当使用存储器到存储器模式时候,通道可以随便选,没有硬性的规定
#define DMA_CHANNEL     DMA1_Channel1
#define DMA_CLOCK       RCC_AHBPeriph_DMA1

// 传输完成标志
#define DMA_FLAG_TC     DMA1_FLAG_TC1

// 要发送的数据大小
#define BUFFER_SIZE     32

void DMA_Config(void);
uint8_t DataCmp(const uint32_t *pData1,uint32_t *pData2,uint16_t DataLen);

#endif

main.c

#include "stm32f10x.h"
#include "led.h"
#include "dma/dma.h"
#include "delay/delay.h"

extern const uint32_t Source_Data[BUFFER_SIZE];
extern uint32_t Distination_Data[BUFFER_SIZE];

int main(void)
{
	uint8_t transferstate; //传输状态
	LED_Init(); //LED初始化
	DMA_Config(); //DMA初始化
	LED_Config(LED_B,ON);
	Delay_ms(1000);
	LED_Config(LED_B,OFF);
	while(DMA_GetFlagStatus(DMA_FLAG_TC) == RESET); //等待DMA传输完成
	transferstate = DataCmp(Source_Data,Distination_Data,32); //比较源数据和传输完成的目的数据
	if(transferstate == 1)
		LED_Config(LED_G,ON); 
	else
		LED_Config(LED_R,ON);
	while(1)
	{

	}
}

DMA 存储器到外设模式实验

编程要点

        1) 配置 USART 通信功能;
        2) 设置串口 DMA 工作参数;
        3) 使能 DMA;
        4) DMA 传输同时 CPU 可以运行其他任务。

dam.c

#include "./dma/dma.h"

//定Source_Data组作为DMA传输数据源
uint8_t Source_Data[BUFFER_SIZE];

void DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStruct;
	// 开启DMA时钟
	RCC_AHBPeriphClockCmd(DMA_CLOCK,ENABLE);
	// 源数据地址
	DMA_InitStruct.DMA_PeripheralBaseAddr = USART_DR_ADDRESS; 
	// 目标地址
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Source_Data;
	// 方向:外设到存储器(这里的外设是内部的FLASH)	
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
	// 传输大小	
	DMA_InitStruct.DMA_BufferSize = BUFFER_SIZE;
	// 外设(内部的FLASH)地址递增	    
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	// 内存地址递增
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
	// 外设数据单位	
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	// 内存数据单位
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	// DMA模式,一次或者循环模式
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; 
	// 优先级:高	
	DMA_InitStruct.DMA_Priority = DMA_Priority_High;
	// 使能内存到内存的传输
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
	// 配置DMA通道		   
	DMA_Init(DMA_CHANNEL,&DMA_InitStruct);
	//清除DMA数据流传输完成标志位
	DMA_ClearFlag(DMA_FLAG_TC);
	// 使能DMA
	DMA_Cmd(DMA_CHANNEL,ENABLE);
}

//串口初始化
void usart_init(void)
{
	//GPIO及USART结构体
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	
	//使能GPIO时钟和USART时钟
	USART_GPIO_APBxClkCmd(USART_GPIO_CLK,ENABLE);
	USART_APBxClkCmd(USART_CLK,ENABLE);
	
	//GPIO结构体配置及初始化
	//TX的GPIO
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin = USART_TX_GPIO_PIN;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(USART_TX_GPIO_PORT,&GPIO_InitStruct);
	
	//USART结构体配置
	USART_InitStruct.USART_BaudRate = USART_BAUDRATE;
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode = USART_Mode_Tx;
	USART_InitStruct.USART_Parity = USART_Parity_No;
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	//初始化USART
	USART_Init(USARTx,&USART_InitStruct);
	//使能USART
	USART_Cmd(USARTx,ENABLE);
	
	 /* USART1 向 DMA发出TX请求 */
	USART_DMACmd(USARTx, USART_DMAReq_Tx, ENABLE);
}

//发送一个字节数据
void usart_sendbyte(USART_TypeDef* pUSARTx, uint8_t data)
{
	//发送一个字节数据
	USART_SendData(pUSARTx,data);
	//等待发送数据寄存器为空
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET);
}

//发送一个数组数据
void usart_sendarr(USART_TypeDef* pUSARTx, uint8_t *arr, uint8_t len)
{
	uint8_t i;
	for(i = 0; i < len; i++)
	{
		//发送一个字节数据
		usart_sendbyte(pUSARTx,*arr++);
	}
	//等待发送完成
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);
}

//发送字符串数据
void usart_sendstr(USART_TypeDef* pUSARTx, char *str)
{
	do
	{
		//发送一个字节数据
		usart_sendbyte(pUSARTx,*str++);
	}while((*str) != '\0');
	//等待发送完成
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);
}

//重定向c库函数printf到串口,重定向后可使用printf、putchar函数
int fputc(int ch, FILE *f)
{
	//发送一个字节数据
	USART_SendData(USARTx,(uint8_t)ch);
	//等待发送数据寄存器为空
	while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE) == RESET);
	return ch;
}

//重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
	//等待接受数据寄存器为空
	while(USART_GetFlagStatus(USARTx,USART_FLAG_RXNE) == RESET);
	return USART_ReceiveData(USARTx);
}

dma.h

#ifndef _DMA_H
#define _DMA_H

#include "stm32f10x.h"
#include <stdio.h>

#define  USARTx                   USART1
#define  USART_CLK                RCC_APB2Periph_USART1
#define  USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  USART_TX_GPIO_PORT       GPIOA
#define  USART_TX_GPIO_PIN        GPIO_Pin_10

// 当使用存储器到存储器模式时候,通道可以随便选,没有硬性的规定
#define DMA_CHANNEL     DMA1_Channel4
#define DMA_CLOCK       RCC_AHBPeriph_DMA1

// 传输完成标志
#define DMA_FLAG_TC     DMA1_FLAG_TC4

// 要发送的数据大小
#define BUFFER_SIZE     5000

 外设寄存器地址
#define USART_DR_ADDRESS	(USART1_BASE+0x04)

void DMA_Config(void);
void usart_init(void);

#endif

main.c

#include "stm32f10x.h"
#include "led.h"
#include "dma/dma.h"
#include "delay/delay.h"

extern uint8_t Source_Data[BUFFER_SIZE];

int main(void)
{
	uint16_t i;
	
	LED_Init();
	usart_init();
	DMA_Config();
	
	//初始化要发送的数据
	for(i=0; i<BUFFER_SIZE; i++)
	{
		Source_Data[i] = 'x';
	}
	
	while(1)
	{
		//DMA串口传输数据的同时灯在闪烁
		LED_Toggle(LED_G);
		Delay_ms(1000);
	}
}

DMA 外设到存储器模式实验

编程要点

        1) 配置 ADC功能;
        2) 设置ADC的DMA 工作参数;
        3) 使能 DMA;
        4) DMA 传输同时 CPU 可以运行其他任务。

dma.c

#include "./dma/dma.h"

__IO uint16_t ADC_ConvertedValue;

//ADC的DAM模式初始化
void ADCx_DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStruct;
	
	//打开DMA时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	//复位DMA控制器
	DMA_DeInit(ADC_DMA_CHANNEL);
	//ADC_DAM结构体配置
	//外设及地址:ADC数据寄存器地址
	DMA_InitStruct.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADC_x->DR ) );
	//存储器地址,实际上就是一个内部SRAM的变量
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;
	//数据传输方向(数据源来自外设)
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
	//缓冲区的大小为1(数据传输的数目),缓冲区的大小应该改等于存储器大小()
	DMA_InitStruct.DMA_BufferSize = 1;
	//外设寄存器只有一个,所以地址不用自增
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	//存储器地址固定,所以也不用自增
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable;
	//外设数据大小为半字,即两个字节
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	//存储器数据大小也为半字节,跟外设数据的大小一样
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	//循环传输模式
	DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
	//DAM传输通道优先级为高,当使用一个DMA通道是,优先级没有影响
	DMA_InitStruct.DMA_Priority = DMA_Priority_High;
	//外设存储器(即禁止存储器到存储器)
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
	//初始化DMA
	DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStruct);
	//使能DMA通道
	DMA_Cmd(ADC_DMA_CHANNEL,ENABLE);
}

//ADC的GPIO初始化
void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	//打开GPIO时钟
	ADC_GPIO_APBxClock_FUN(ADC_GPIO_CLK,ENABLE);
	//GPIO结构体配置
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStruct.GPIO_Pin = ADC_PIN;
	//初始化GPIO
	GPIO_Init(ADC_PORT,&GPIO_InitStruct);
}

//ADC模式初始化
void ADCx_MODE_Config(void)
{
	ADC_InitTypeDef ADC_InitStruct;
	
	//打开 ADC 时钟
	ADC_APBxClock_FUN(ADC_CLK,ENABLE);
	
	// ADC 模式配置
	// 只使用一个ADC,属于独立模式
	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
	// 禁止扫描模式,多通道才要,单通道不需要
	ADC_InitStruct.ADC_ScanConvMode = DISABLE;
	// 连续转换模式
	ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
	// 不用外部触发转换,软件开启即可
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	// 转换结果右对齐
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
	// 转换通道1个
	ADC_InitStruct.ADC_NbrOfChannel = 1;
	// 初始化ADC
	ADC_Init(ADC_x,&ADC_InitStruct);
	
	// 配置ADC时钟为PCLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	
	// 配置 ADC 通道转换顺序和采样时间
	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	
	//ADC_DAM初始化
	ADCx_DMA_Config();
	
	//使能ADC的DAM请求
	ADC_DMACmd(ADC_x,ENABLE);
	
	// 开启ADC ,并开始转换
	ADC_Cmd(ADC_x,ENABLE);
	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADC_x);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADC_x));
	// ADC开始校准
	ADC_StartCalibration(ADC_x);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADC_x));
	// 由于没有采用外部触发,所以使用软件触发ADC转换 
	ADC_SoftwareStartConvCmd(ADC_x,ENABLE);
}

//ADC初始化
void ADCx_Init(void)
{
	ADCx_GPIO_Config();
	ADCx_MODE_Config();
}

dma.h

#ifndef _ADC_H
#define _ADC_H

#include "stm32f10x.h"

// ADC 编号选择	使用ADC2
#define    ADC_APBxClock_FUN         RCC_APB2PeriphClockCmd    
#define    ADC_x                     ADC1     
#define    ADC_CLK                   RCC_APB2Periph_ADC1    

// ADC GPIO宏定义
// 注意:用作ADC采集的IO必须没有复用,否则采集电压会有影响
#define    ADC_GPIO_APBxClock_FUN   RCC_APB2PeriphClockCmd     
#define    ADC_GPIO_CLK             RCC_APB2Periph_GPIOC     
#define    ADC_PORT                 GPIOC     
#define    ADC_PIN                  GPIO_Pin_1     

// ADC 通道宏定义
#define    ADC_CHANNEL              ADC_Channel_11    
#define	   ADC_DMA_CHANNEL			DMA1_Channel1  

void ADCx_Init(void);

#endif

main.c

#include "stm32f10x.h"
#include "led.h"
#include "./usart/usart.h"
#include "./dma/dma.h"
#include "./delay/delay.h"

extern __IO uint16_t ADC_ConvertedValue;

//采集到的真时电压
float ADC_ConvertedValue_Reality; 

int main(void)
{
	usart_init();
	ADCx_Init();
	
	printf("这是一个adc采集电压的实验(DMA通道读取)!!!");
	
	while(1)
	{
		//计算采集的真实电压
		ADC_ConvertedValue_Reality = (float)ADC_ConvertedValue/4096*3.3;
		printf("ADC采集到的值ADC_ConvertedValue:%d\r\n",ADC_ConvertedValue);
		printf("ADC采集到的实际电压值ADC_ConvertedValue_Reality:%.2fV\r\n",ADC_ConvertedValue_Reality);	
		Delay_ms(500);
	}
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

small陀螺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值