发现ADC(DMA模式)实验 啊,DMA 那里地方,讲解不是太详细。按照野火教程上,USART 的DMA 方式实验,没有讲。 所以还有些模糊,今天对照野火的ADC 程序,然后对照库函数,做了个详细的备注.这里只注释adc.c 函数的内容。 新手上路,喜欢搞得详细一些,分享给 和我一样的新手。 哈哈。。。- /********************************************************************************
- ADC使用DMA 功能描述:
- 启动AD转换后,AD 每次转换完成后,由DMA 控制器把转换值从ADC数据寄存器(ADC_DR)
- 中转移到变量ADC_ConvertedValue,当DMA完成后,在main中使用的,就是ADC 转换的结果。
- ********************************************************************************/
- #include"adc.h"
- #define ADC1_DR_Address ((u32)0x40012400+0x4c) //宏定义 ADC1 转换后保存数据的地址
- //具体见 STM32参考手册 P178 0x4c 的意思就是ADC1_DR 的具体地址
- //0x40012400 是ADC 的寄存器首地址 STM32参考手册 P28
- __IO uint16_t ADC_ConvertedValue; //定义一个数据
- /********************************************************************************************
- 分析上面这个定义数据的意思:
- core_cm3.h 定义了 __IO:
- #define __IO volatile !< defines 'read / write' permissions
- volatile 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.
- stdint.h定义了 uint16_t :
- typedef unsigned short int uint16_t;
- ADC_ConvertedValue 变量名
- ********************************************************************************************/
- void ADC1_Init(void)
- {
- ADC1_GPIO_Config(); //ADC1 GPIO 设置
- ADC1_Mode_Config(); //ADC1 工作方式设置
- }
- /*
- * 函数名:ADC1_GPIO_Config
- * 描述 :使能ADC1和DMA1的时钟,初始化PC.01
- * 输入 : 无
- * 输出 :无
- * 调用 :内部调用
- */
- static void ADC1_GPIO_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
- // 结构体内容在stm32f10x_gpio.h 101行 // 见库函数 P125页
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);
- //打开时钟
- /* Enable DMA clock */ //打开DMA 时钟
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //注意它的时钟树
- //初始化GPIO 见库函数 P125页
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; //要设置的PIN
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 设置IO 为 模拟输入
- // GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输入 不用设置速度
- GPIO_Init(GPIOC,&GPIO_InitStructure); //配置 IO
- }
- /* 函数名:ADC1_Mode_Config
- * 描述 :配置ADC1的工作模式为MDA模式
- * 输入 : 无
- * 输出 :无
- * 调用 :内部调用
- */
- static void ADC1_Mode_Config(void)
- {
- ADC_InitTypeDef ADC_InitStructure; //定义 ADC 结构体
- DMA_InitTypeDef DMA_InitStructure; //定义 DMA 结构体
- //DMA 初始化 函数使用 见库函数 P89页
- /* DMA channel1 configuration */
- DMA_DeInit(DMA1_Channel1); //将DMA 通道1寄存器 复位 ADC DMA 对应 通道1
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA外设基地址 即ADC地址
- DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&ADC_ConvertedValue;//DMA内存基地址 即要存放数据的地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作为数据传输的来源
- DMA_InitStructure.DMA_BufferSize = 1; //DMA 缓存大小
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //内存地址不变
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度16位
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存数据宽度
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
- DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设定DMA通道X 的优先级
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA 通道X 没有设置 内存到内存传输
- DMA_Init(DMA1_Channel1, &DMA_InitStructure); //配置DMA 通道1 参数
- /* Enable DMA channel1 */
- DMA_Cmd(DMA1_Channel1, ENABLE);
-
- //ADC 初始化 函数使用 见库函数 P42页
- /* ADC1 configuration */
- ADC_InitStructure.ADC_Mode=ADC_Mode_Independent; //独立ADC模式
- ADC_InitStructure.ADC_ScanConvMode = DISABLE ; //禁止扫描模式,扫描模式用于多通道采集
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式,即不停地进行ADC转换
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不使用外部触发启动
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐
- ADC_InitStructure.ADC_NbrOfChannel = 1; //要转换的通道数目1
- ADC_Init(ADC1,&ADC_InitStructure); //配置设定好的工作方式
- /*配置ADC时钟,为PCLK2的8分频,即9MHz*/
- RCC_ADCCLKConfig(RCC_PCLK2_Div8);
-
- /*配置ADC1的通道11为55. 5个采样周期,采样顺序为1 */ //见 库函数P49
- ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);
- /* Enable ADC1 DMA */
- ADC_DMACmd(ADC1, ENABLE); //使能ADC1 的DMA 请求 见库函数 P45
-
- /* Enable ADC1 */
- ADC_Cmd(ADC1, ENABLE); //使能ADC1 见库函数 P44 注意:函数ADC_Cmd 只能在其他ADC函数设置后被调用
- //在开启AD 转换前 启动AD 自校准
- /*复位校准寄存器 */
- ADC_ResetCalibration(ADC1); //库函数 P46 页
- /*等待校准寄存器复位完成 */
- while(ADC_GetResetCalibrationStatus(ADC1));
- /* 开启 ADC校准 */
- ADC_StartCalibration(ADC1);
- /* 等待校准完成*/
- while(ADC_GetCalibrationStatus(ADC1));
- /* 由于没有采用外部触发,所以使用软件触发ADC转换 */
- ADC_SoftwareStartConvCmd(ADC1, ENABLE); ////库函数 P47 页
-
- }
|