11、DMA
1、DMA介绍
直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。
2、DMA主要特征
● 12个独立的可配置的通道(请求):DMA1有7个通道,DMA2有5个通道
● 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
● 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推) 。
● 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
● 支持循环的缓冲器管理
● 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。
● 存储器和存储器间的传输
● 外设和存储器、存储器和外设之间的传输
● 闪存、SRAM、外设的SRAM、APB1 、APB2和AHB外设均可作为访问的源和目标。
● 可编程的数据传输数目:最大为65535
3、DMA1请求映像
从外设(TIMx[x=1、2 、3、4] 、ADC1 、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])产生的7个请求,通过逻辑或输入到DMA1控制器,这意味着同时只能有一个请求有效。
4、DMA2请求映像
从外设(TIMx[5、6 、7 、8] 、ADC3 、SPI/I2S3 、UART4、DAC通道1、2和SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,这意味着同时只能有一个请求有效。
5、DMA操作
(1)数据传输的目的地和来源
(2)定义DMA通道的DMA缓存的大小
(3)外设地址寄存器递增与否
(4).内存地址寄存器递增与否
(5)设定了外设数据宽度
(6).设定了内存数据宽度
(7)设置了DMA的工作模式
(8)DMA通道的软件优先级
(9).使能DMA通道的内存到内存传输
6、例程代码:
1 /************************************************************************************************************************************* 2 * 3 * 文件名称:main.c 4 * 文件功能:主函数文件 5 * 6 ***************************************************************************************************************************************/ 7 8 #include "pbdata.h"//调用自定义公共函数库 9 10 11 /********************************************************************************* 12 * 13 * 全局变量声明 14 * 15 *********************************************************************************/ 16 17 u16 ADCData[50]; 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 /********************************************************************************* 33 * 34 * 初始化操作 35 * 36 *********************************************************************************/ 37 void RCC_Configuration(void);//系统时钟初始化函数声明 38 void GPIO_Configuration(void);//GPIO初始化函数声明 39 void NVIC_Configuration(void);//中断优先级配置函数声明 40 void USART_Configuration(void);//串口配置函数声明 41 void ADC_Configuration(void);//ADC配置函数声明 42 void DMA_Configuration(void);//DMA配置函数声明 43 44 45 46 /******************************************************************************** 47 * 48 * 函数名称:main(void) 49 * 函数功能:主函数 50 * 函数说明:不能用void定义主函数 51 * 52 ********************************************************************************/ 53 int main(void)//void不能void定义主函数 54 { 55 56 u32 ad=0;//取50次转换平均值 57 u8 i=0;//循环50次 58 59 RCC_Configuration(); //系统时钟初始化 60 61 GPIO_Configuration();//端口初始化 62 63 USART_Configuration();//串口配置 64 65 NVIC_Configuration(); 66 67 ADC_DMACmd(ADC1,ENABLE);//将AD和DMA绑定在一起 68 69 ADC_Configuration();//ADC配置 70 71 72 while(1) 73 { 74 ad=0; 75 for(i=0;i<50;i++) 76 { 77 ad=ad+ADCData[i];//循环取50次,放入数组中,最后取平均值 78 } 79 80 ad=ad/50; 81 printf("AD=%.3f\n",ad*3.3/4095); 82 83 delay_ms(1000); 84 delay_ms(1000); 85 delay_ms(1000); 86 delay_ms(1000); 87 delay_ms(1000); 88 89 } 90 91 } 92 93 94 95 96 /******************************************************************************** 97 * 98 * 函数名称:RCC_Configuration(void) 99 * 函数功能:系统时钟高初始化函数 100 * 101 ********************************************************************************/ 102 void RCC_Configuration(void)//系统时钟高初始化函数 103 { 104 105 SystemInit();//系统初始化 106 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//串口对应GPIO时钟使能 107 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口时钟使能 108 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//引脚复用 109 110 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//adc对应GPIO时钟使能 111 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//ADC1时钟使能 112 RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC频率不超过14M,所以对它分频,72/6=12 113 114 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//DMA时钟使能 115 116 } 117 118 119 120 /******************************************************************************* 121 * 122 * 函数名称:GPIO_Configuration(void) 123 * 函数功能:GPIO初始化函数 124 * 125 ********************************************************************************/ 126 127 void GPIO_Configuration(void)//GPIO初始化函数 128 { 129 130 131 /*串口引脚配置*/ 132 GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量 133 134 /*输出引脚配置*/ 135 /*结构体变量赋值*/ 136 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;////引脚配置TX 137 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置频率 138 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//发送要配置成复用推挽输出 139 /*对应的GPIO初始化*/ 140 GPIO_Init(GPIOA,&GPIO_InitStructure); 141 142 143 /*输入引脚配置*/ 144 /*结构体变量赋值*/ 145 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;////引脚配置RX 146 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//接收引脚配置成浮空输入 147 /*对应的GPIO初始化*/ 148 GPIO_Init(GPIOA,&GPIO_InitStructure); 149 150 /*ADC输入引脚配置*/ 151 /*结构体变量赋值*/ 152 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;////引脚配置adc 153 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入 154 /*对应的GPIO初始化*/ 155 GPIO_Init(GPIOC,&GPIO_InitStructure); 156 157 158 159 160 } 161 162 163 /******************************************************************************** 164 * 165 * 函数名称:NVIC_Configuration(void) 166 * 函数功能:配置中断优先级 167 * 168 ********************************************************************************/ 169 170 void NVIC_Configuration(void) 171 { 172 NVIC_InitTypeDef NVIC_InitStructure; //定义一个优先级配置结构体变量 173 174 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//分组 175 176 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 177 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢断优先级 178 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级 179 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能 180 181 NVIC_Init(&NVIC_InitStructure);//初始化 182 } 183 184 185 /********************************************************************************* 186 * 187 * 函数名称:USART_Configuration(void) 188 * 函数功能:串口配置函数 189 * 190 *********************************************************************************/ 191 void USART_Configuration(void) 192 { 193 /*定义串口配置结构体变量*/ 194 USART_InitTypeDef USART_InitStructure;//定义一个串口配置结构体变量 195 196 197 /*结构体变量赋值*/ 198 USART_InitStructure.USART_BaudRate = 9600;//波特率9600 199 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//位宽,8位 200 USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位1 201 USART_InitStructure.USART_Parity = USART_Parity_No;//不奇偶校验 202 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//流控禁止 203 USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//发送使能 204 205 206 /*发送串口配置初始化*/ 207 USART_Init(USART1, &USART_InitStructure); 208 209 210 /*打开串口接收中断*/ 211 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//当接收到数据时,会产生中断 212 213 214 /*打开串口*/ 215 USART_Cmd(USART1,ENABLE);//串口使能,打开 216 217 /*清空中断标志位*/ 218 USART_ClearFlag(USART1,USART_FLAG_TC); 219 } 220 221 222 223 /********************************************************************************* 224 * 225 * 函数名称:ADC_Configuration(void) 226 * 函数功能:串口配置函数 227 * 228 *********************************************************************************/ 229 void ADC_Configuration(void) 230 { 231 232 /*定义一个ADC配置结构体变量*/ 233 ADC_InitTypeDef ADC_InitStructure; 234 235 236 /*对结构体变量赋值*/ 237 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式 238 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单通道模式 239 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//循环采集 240 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发 241 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对其 242 ADC_InitStructure.ADC_NbrOfChannel = 1;//转换的通道,只取1个通道 243 244 /*ADC初始化*/ 245 ADC_Init(ADC1, &ADC_InitStructure); 246 247 248 /*规则组*/ 249 ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1,ADC_SampleTime_239Cycles5); //,选择ADC1,通道10,通道数1,采样时间239.5 250 251 252 /*使能ADC*/ 253 ADC_Cmd(ADC1, ENABLE); 254 255 256 /*校准ADC*/ 257 ADC_ResetCalibration(ADC1);//对应ADC复位 258 while(ADC_GetResetCalibrationStatus(ADC1));//获取状态,等待复位完成 259 ADC_StartCalibration(ADC1);//开始指定ADC校准状态 260 while(ADC_GetCalibrationStatus(ADC1));//获取校准状态,等待完成 261 262 263 /*启动ADC*/ 264 ADC_SoftwareStartConvCmd(ADC1,ENABLE); 265 266 267 } 268 269 270 /********************************************************************************* 271 * 272 * 函数名称:DMA_Configuration(void) 273 * 函数功能:串口配置函数 274 * 275 *********************************************************************************/ 276 void DMA_Configuration(void) 277 { 278 DMA_InitTypeDef DMA_InitStructure; 279 280 DMA_DeInit(DMA1_Channel1);//DMA1通道1初始化 281 282 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//AD存放数的地址 283 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCData;//存放的地址,设一个数组存放 284 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设是数据的来源 285 DMA_InitStructure.DMA_BufferSize = 50;//缓冲区大小,也就是数组大小 286 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//AD地址不变 287 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//数组地址递增 288 DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord;//外设数据宽度,16位 289 DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord;//DMA数据宽度,16位 290 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//工作模式,循环 291 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA优先级,高 292 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// 293 294 DMA_Init(DMA1_Channel1,&DMA_InitStructure);//DMA初始化 295 296 DMA_Cmd(DMA1_Channel1,ENABLE);//DMA使能 297 298 } 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
1 /**************************************************************************************************************** 2 * 3 * 文件名称:pbdata.c 4 * 文件功能:自定义函数或者全局变量的初始化 5 * 6 ****************************************************************************************************************/ 7 8 /*头文件声明*/ 9 #include "pbdata.h" 10 11 12 13 14 /******************************************************************************************** 15 * 16 * 自定义全局变量 17 * 18 ********************************************************************************************/ 19 u8 dt=0; 20 21 22 23 24 25 /****************************************************************************************** 26 * 27 * 自定义函数 28 * 29 ******************************************************************************************/ 30 31 32 33 /************************************************** 34 * 35 * 函数名称:delay_us(u32 nus) 36 * 函数功能:微秒延时函数 37 * 输入参数:输入值为延时us 38 * 39 ***************************************************/ 40 void delay_us(u32 nus) 41 { 42 u32 temp; 43 SysTick->LOAD = 9*nus;//载入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是执行9次 44 SysTick->VAL=0X00;//清空计数器,清空后,就自动设置自己设定的计数器的值 45 SysTick->CTRL=0X01;//使能,减到零动作(不发生中断),采用外部时钟 46 47 do 48 { 49 temp=SysTick->CTRL;//标志位,等到一直减到0 50 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达 51 52 SysTick->CTRL=0x00; //关闭计数器 53 SysTick->VAL =0X00; //清空计数器 54 } 55 56 57 58 59 60 61 62 /*************************************************** 63 * 64 * 函数名称:delay_ms(u16 nms) 65 * 函数功能:毫秒级延时 66 * 输入参数:输入值位延时ms 67 * 68 ****************************************************/ 69 void delay_ms(u16 nms) 70 { 71 u32 temp; 72 SysTick->LOAD = 9000*nms;//载入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是执行9000次 73 SysTick->VAL=0X00;//清空计数器,清空后,就自动设置自己设定的计数器的值 74 SysTick->CTRL=0X01;//使能,减到零动作(不发生中断),采用外部时钟 75 76 do 77 { 78 temp=SysTick->CTRL;//标志位,等到一直减到0 79 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达 80 81 SysTick->CTRL=0x00; //关闭计数器 82 SysTick->VAL =0X00; //清空计数器 83 } 84 85 86 87 /**************************************************** 88 * 89 * 重定义printf函数部分 90 * 91 ****************************************************/ 92 int fputc(int ch,FILE *F) 93 { 94 95 USART_SendData(USART1,(u8)ch); 96 97 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待发送完成,判断标志位 98 99 return ch; 100 }
1 /*pbdata.h*/ 2 /*************************************************************************************************** 3 * 4 * 文件名称:pbdata.h 5 * 文件功能:自定义的函数和全局变量的声明头文件 6 * 7 ***************************************************************************************************/ 8 9 #ifndef _pbdata_H 10 #define _pbdata_H 11 12 13 14 15 16 /******************************************************************** 17 * 18 * 调用的头文件放在这里 19 * 20 ********************************************************************/ 21 #include "stm32f10x.h" 22 23 24 #include "misc.h" 25 #include "stm32f10x_exti.h" 26 #include "stm32f10x_tim.h" 27 #include "stm32f10x_usart.h" 28 #include "stm32f10x_adc.h" 29 #include "stm32f10x_dma.h" 30 31 #include "stdio.h" 32 33 34 35 36 /******************************************************************** 37 * 38 * 自定义全局变量声明 39 * 40 ********************************************************************/ 41 extern u8 dt; 42 43 44 45 46 47 /******************************************************************** 48 * 49 * 自定义全函数声明 50 * 51 ********************************************************************/ 52 void delay(u32 nCount); 53 void delay_us(u32 nus); 54 void delay_ms(u16 nms); 55 int fputc(int ch,FILE *F); 56 57 58 59 #endif
7、例程下载:
http://download.csdn.net/detail/a1181803348/8752375