什么是网站建设的建议,什么人做网站,厦门自助网站建设报价,网站设计高端一、DMA#xff1a;1.简介#xff1a;DMA#xff0c;直接存储区存取DMA可以提供外设和存储器或存储器与存储器见的高速数据传输#xff0c;无需CPU干预。12个通道#xff1a;DMA1#xff08;7个通道#xff09;#xff0c;DMA2#xff08;5个通道#xff09;每个通道…一、DMA1.简介DMA直接存储区存取DMA可以提供外设和存储器或存储器与存储器见的高速数据传输无需CPU干预。12个通道DMA17个通道DMA25个通道每个通道支持软件触发和特定硬件触发每个外设有固定通道。本芯片只有DMA1。2.存储器映像3.功能图外设寄存器与Flash和SRAM存储器为两大数据存储地点。转运数据由两个结构体决定每个包含三个参数
起始地址数据宽度地址是否自增一次转运完成后指针是否挪到下个地址。
ps:这两个结构体其实是完全相同的并非外设结构体只能放外设地址等等传输计数器触发后进行数据转运的次数在传输完成后两个结构体的指针回到初始地址。自动重装器决定了是否循环传输在传输完成后传输寄存器恢复到自动重装器的值配合上面结构体指针回到初始地址可以做到对对同一块地址数据循环传输。M2M决定触发逻辑为1则软件触发为0硬件触发MtoM名称意义为存储器到存储器软件触发与前面不同的是并非由一个函数触发而是不断连续触发DMA直到将传输计数器清零完成传输即使能DMA就自动开始转运。软件触发和循环模式不能同时使用硬件触发就是外设给出信号触发开关控制给DMA使能写传输计数器时需要将DMA关闭。4.ADC与DMA前文介绍了ADC的功能ADC有一个扫描模式可以同时转换多个通道的值但在规则组中却只有一个寄存器存放结果就需要DMA在一次转换完成后就将寄存器的数据转运到存储器中这样就不会被下一个通道的结果覆盖而丢失。二、实战DMA数据转运DMA.c
#include stm32f10x.h                  // Device headeruint16_t MyDMA_Size;					//定义全局变量用于记住Init函数的Size供Transfer函数使用/*** 函    数DMA初始化* 参    数AddrA 原数组的首地址* 参    数AddrB 目的数组的首地址* 参    数Size 转运的数据大小转运次数1代表字节* 返 回 值无*/
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{MyDMA_Size  Size;					//将Size写入到全局变量记住参数Size/*开启时钟*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);						//开启DMA的时钟/*DMA初始化*/DMA_InitTypeDef DMA_InitStructure;										//定义结构体变量DMA_InitStructure.DMA_PeripheralBaseAddr  AddrA;						//外设基地址给定形参AddrADMA_InitStructure.DMA_PeripheralDataSize  DMA_PeripheralDataSize_Byte;	//外设数据宽度选择字节DMA_InitStructure.DMA_PeripheralInc  DMA_PeripheralInc_Enable;			//外设地址自增选择使能DMA_InitStructure.DMA_MemoryBaseAddr  AddrB;							//存储器基地址给定形参AddrBDMA_InitStructure.DMA_MemoryDataSize  DMA_MemoryDataSize_Byte;			//存储器数据宽度选择字节DMA_InitStructure.DMA_MemoryInc  DMA_MemoryInc_Enable;					//存储器地址自增选择使能DMA_InitStructure.DMA_DIR  DMA_DIR_PeripheralSRC;						//数据传输方向选择由外设到存储器此处名称的意思是外设作为数据源DMA_InitStructure.DMA_BufferSize  Size;								//转运的数据大小转运次数DMA_InitStructure.DMA_Mode  DMA_Mode_Normal;							//模式选择正常模式DMA_InitStructure.DMA_M2M  DMA_M2M_Enable;								//存储器到存储器选择使能DMA_InitStructure.DMA_Priority  DMA_Priority_Medium;					//优先级选择中等DMA_Init(DMA1_Channel1, DMA_InitStructure);							//将结构体变量交给DMA_Init配置DMA1的通道1软件无所谓硬件要查手册看是通道几/*DMA使能*/DMA_Cmd(DMA1_Channel1, DISABLE);	//这里先不给使能初始化后不会立刻工作等后续调用Transfer后再开始
}/*** 函    数启动DMA数据转运* 参    数无* 返 回 值无*/
void MyDMA_Transfer(void)
{DMA_Cmd(DMA1_Channel1, DISABLE);					//DMA失能在写入传输计数器之前需要DMA暂停工作DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);	//写入传输计数器指定将要转运的次数DMA_Cmd(DMA1_Channel1, ENABLE);						//DMA使能开始工作while (DMA_GetFlagStatus(DMA1_FLAG_TC1)  RESET);	//等待DMA工作完成DMA_ClearFlag(DMA1_FLAG_TC1);						//清除工作完成标志位
}
三、实战DMAAD多通道问如何访问外设寄存器答无需具体地址可通过结构体来访问如想访问ADC1的DR寄存器直接ADC1-DR即可。新AD.c
#include stm32f10x.h                  // Device headeruint16_t AD_Value[4];					//定义用于存放AD转换结果的全局数组/*** 函    数AD初始化* 参    数无* 返 回 值无*/
void AD_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);		//开启DMA1的时钟/*设置ADC时钟*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//选择时钟6分频ADCCLK  72MHz / 6  12MHz/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode  GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin  GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed  GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);					//将PA0、PA1、PA2和PA3引脚初始化为模拟输入/*规则组通道配置*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);	//规则组序列1的位置配置为通道0ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);	//规则组序列2的位置配置为通道1ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);	//规则组序列3的位置配置为通道2ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);	//规则组序列4的位置配置为通道3/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure;											//定义结构体变量ADC_InitStructure.ADC_Mode  ADC_Mode_Independent;							//模式选择独立模式即单独使用ADC1ADC_InitStructure.ADC_DataAlign  ADC_DataAlign_Right;						//数据对齐选择右对齐ADC_InitStructure.ADC_ExternalTrigConv  ADC_ExternalTrigConv_None;			//外部触发使用软件触发不需要外部触发ADC_InitStructure.ADC_ContinuousConvMode  ENABLE;							//连续转换使能每转换一次规则组序列后立刻开始下一次转换ADC_InitStructure.ADC_ScanConvMode  ENABLE;								//扫描模式使能扫描规则组的序列扫描数量由ADC_NbrOfChannel确定ADC_InitStructure.ADC_NbrOfChannel  4;										//通道数为4扫描规则组的前4个通道ADC_Init(ADC1, ADC_InitStructure);											//将结构体变量交给ADC_Init配置ADC1/*DMA初始化*/DMA_InitTypeDef DMA_InitStructure;											//定义结构体变量DMA_InitStructure.DMA_PeripheralBaseAddr  (uint32_t)ADC1-DR;				//外设基地址给定形参AddrADMA_InitStructure.DMA_PeripheralDataSize  DMA_PeripheralDataSize_HalfWord;	//外设数据宽度选择半字对应16为的ADC数据寄存器DMA_InitStructure.DMA_PeripheralInc  DMA_PeripheralInc_Disable;			//外设地址自增选择失能始终以ADC数据寄存器为源DMA_InitStructure.DMA_MemoryBaseAddr  (uint32_t)AD_Value;					//存储器基地址给定存放AD转换结果的全局数组AD_ValueDMA_InitStructure.DMA_MemoryDataSize  DMA_MemoryDataSize_HalfWord;			//存储器数据宽度选择半字与源数据宽度对应DMA_InitStructure.DMA_MemoryInc  DMA_MemoryInc_Enable;						//存储器地址自增选择使能每次转运后数组移到下一个位置DMA_InitStructure.DMA_DIR  DMA_DIR_PeripheralSRC;							//数据传输方向选择由外设到存储器ADC数据寄存器转到数组DMA_InitStructure.DMA_BufferSize  4;										//转运的数据大小转运次数与ADC通道数一致DMA_InitStructure.DMA_Mode  DMA_Mode_Circular;								//模式选择循环模式与ADC的连续转换一致DMA_InitStructure.DMA_M2M  DMA_M2M_Disable;								//存储器到存储器选择失能数据由ADC外设触发转运到存储器DMA_InitStructure.DMA_Priority  DMA_Priority_Medium;						//优先级选择中等DMA_Init(DMA1_Channel1, DMA_InitStructure);								//将结构体变量交给DMA_Init配置DMA1的通道1只能是通道1/*DMA和ADC使能*/DMA_Cmd(DMA1_Channel1, ENABLE);							//DMA1的通道1使能ADC_DMACmd(ADC1, ENABLE);								//ADC1触发DMA1的信号使能ADC_Cmd(ADC1, ENABLE);									//ADC1使能/*ADC校准*/ADC_ResetCalibration(ADC1);								//固定流程内部有电路会自动执行校准while (ADC_GetResetCalibrationStatus(ADC1)  SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1)  SET);/*ADC触发*/ADC_SoftwareStartConvCmd(ADC1, ENABLE);	//软件触发ADC开始工作由于ADC处于连续转换模式故触发一次后ADC就可以一直连续不断地工作
}