(89)void expModuleDriverInit(void)*扩展模块驱动初始化*【AD初始化 && DMA初始化】

it2025-10-05  3

 

 

文章目录

 


前言

 



一、void expModuleDriverInit(void)

void expModuleDriverInit(void) /*扩展模块驱动初始化*/ { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; //GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能PORTB时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //使能DMA时钟 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; //PB1 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模拟输入 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //不上拉、下拉 GPIO_Init(GPIOB,&GPIO_InitStructure); // 初始化PB1 /*DMA2_Stream0 channel0 ÅäÖÃ*/ DMA_DeInit(DMA2_Stream0); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&adcValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = ADC_SAMPLE_NUM; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE);//ʹÄÜDMA2_Stream0 /*ADC1 ÅäÖÃ*/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//¶ÀÁ¢Ä£Ê½ ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//Á½¸ö²ÉÑù½×¶ÎÖ®¼äµÄÑÓ³Ù5¸öʱÖÓ ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //¶à¸öADCģʽDMAʧÄÜ ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//Ô¤·ÖƵ4·ÖƵ¡£ADCCLK=PCLK2/4=100/4=25Mhz,ADCʱÖÓ×îºÃ²»Òª³¬¹ý36Mhz ADC_CommonInit(&ADC_CommonInitStructure);//³õʼ»¯ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12λģʽ ADC_InitStructure.ADC_ScanConvMode = DISABLE;//·ÇɨÃèģʽ ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//Á¬Ðø×ª»» ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//½ûÖ¹´¥·¢¼ì²â£¬Ê¹ÓÃÈí¼þ´¥·¢ ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ÓÒ¶ÔÆë ADC_InitStructure.ADC_NbrOfConversion = 1;//1¸öת»»ÔÚ¹æÔòÐòÁÐÖÐ Ò²¾ÍÊÇֻת»»¹æÔòÐòÁÐ1 ADC_Init(ADC1, &ADC_InitStructure);//ADC³õʼ»¯ ADC_RegularChannelConfig(ADC1, ADC_Channel_9,1,ADC_SampleTime_480Cycles);//ÅäÖÃPB1¹æÔòͨµÀ9 ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE);//ʹÄÜDMA ADC_Cmd(ADC1, ENABLE);//ʹÄÜADת»»Æ÷ ADC_SoftwareStartConv(ADC1);//¿ªÆôת»» }

二、DMA配置(对应F1开发指南 二十七章节)

    2.1 DMA简介 (Diriect Memory Access)

DMA传输数据从一个地址空间复制到另外一个地址空间。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件直接传输数据,大幅提高CPU的效率。

STM32最多有2个DMA控制器,DMA1有7个通道,通道的作用是通过硬件触发或者软件触发读取外设对存储器访问的请求,每个通道同时只能相应一个DMA请求 。有一个寄存器协调各请求的优先权。

每个通道都有3个事件标志,DMA半传输,DMA传输完成和DMA传输出错,通过事件标志逻辑或运算得到中断请求。

2.2DMA寄存器

2.2.1 DMA中断状态寄存器(ISR)

2.2.2 DMA中断标志清除寄存器(IFCR)

2.2.3 DNA通道x配置寄存器(DMA_CCRx)

 

2.3 DMA配置及初始化

  1)使能DMA时钟

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟

  2)初始化DMA 通道 4  参数

void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,DMA_InitTypeDef* DMA_InitStruct)

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;

 

 

DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = &USART1->DR; //DMA 外设 ADC 基地址 DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //从内存读取发送到外设 DMA_InitStructure.DMA_BufferSize = 64; //DMA 通道的 DMA 缓存的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //8 位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8 位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA 通道 x 拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输 DMA_Init(DMA_CHx, &DMA_InitStructure); //根据指定的参数初始化

  3)使能串口 DMA 发 送

USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);

  4)使能 DMA1 通道 4 ,启动传输

DMA_Cmd(DMA_CHx, ENABLE);

  5)查询 DMA 传输状态

在 DMA 传输过程中,我们要查询 DMA 传输通道的状态,使用的函数是: FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG) 比如我们要查询 DMA 通道 4 传输是否完成,方法是: DMA_GetFlagStatus(DMA2_FLAG_TC4); 这里还有一个比较重要的函数就是获取当前剩余数据量大小的函数: uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx) 比如我们要获取 DMA 通道 4 还有多少个数据没有传输,方法是: DMA_GetCurrDataCounter(DMA1_Channel4); DMA 相关的库函数我们就讲解到这里,大家可以查看固件库中文手册详细了解。

2.4 MiniFly  DMA初始化

    DMA_InitTypeDef           DMA_InitStructure;     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);    //使能DMA时钟     /*DMA2_Stream0 channel0配置*/     DMA_DeInit(DMA2_Stream0);//以DMA2 BASE地址定义了一个结构体     DMA_InitStructure.DMA_Channel = DMA_Channel_0;  //DMA2 通道0     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//外设地址     DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&adcValue;//自己定义的一个数据数组     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//发送方向定义     DMA_InitStructure.DMA_BufferSize = ADC_SAMPLE_NUM;//采集次数为10     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//地址加一?     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//地址加一?     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_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; /*以下的还未了解 要到中文手册去了解各个寄存器的作用*/     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;//((uint32_t)0x00000001)      DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//0x00000000     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//0x00000000     DMA_Init(DMA2_Stream0, &DMA_InitStructure);     DMA_Cmd(DMA2_Stream0, ENABLE);//ʹÄÜDMA2_Stream0

三、ADC配置(对应F1开发指南 二十二章节)

3.1 ADC简介

STM32具有12位逐次逼近型的模拟数字转换器,它有18个通道,可测量16个外部和2个内部信号源。STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正 常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你 的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之 后,规则通道才得以继续转换。 意思就是说避免切换时重新配置通道。

用ADC1 规则通道的顺序为CH0,CH1,CH2,CH3:

(一)不启动SCAN模式 

在单次转换模式下:

启动ADC1,则 1.开始转换CH0(ADC_SQR的第一通道) 2.转换完成后停止,等待ADC的下一次启动,继续从第一步开始转换

在连续转换模式下:

启动ADC1,则 1.开始转换CH0(ADC_SQR的第一通道) 2.转换完成后回到第一步。

(二)启动SCAN模式下

在单次转换模式下: 启动ADC1,则 1.开始转换CH0、 2.转换完成后自动开始转换CH1 3.转换完成后自动开始转换CH2 4.转换完成后自动开始转换CH3 5.转换完成后停止,等待ADC的下一次启动下一次ADC启动后从第一步开始转换

在连续转换模式下: 启动ADC1,则 1.开始转换CH0、 2.转换完成后自动开始转换CH1 3.转换完成后自动开始转换CH2 4.转换完成后自动开始转换CH3 5.转换完成后返回第一步

3.2MiniFly  ADC配置理解

    ADC_InitTypeDef          ADC_InitStructure;     ADC_CommonInitTypeDef     ADC_CommonInitStructure;     GPIO_InitTypeDef          GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);    //ʹÄÜPORTBʱÖÓ     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);      //ʹÄÜADC1ʱÖÓ

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;                    //PB1     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;                //Ä£ÄâÊäÈë     GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;            //²»ÉÏÀ­¡¢ÏÂÀ­     GPIO_Init(GPIOB,&GPIO_InitStructure);                      //³õʼ»¯PB1

     /*ADC1配置*/

    //看了下 这部分应该是一个寄存器 分别是 12位 3位 4 位 所以最后或到一起赋值了     ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式     ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//Á½¸ö²ÉÑù½×¶ÎÖ®¼äµÄÑÓ³Ù5¸öʱÖÓ     ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //¶à¸öADCģʽDMAʧÄÜ     ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//Ô¤·ÖƵ4·ÖƵ¡£ADCCLK=PCLK2/4=100/4=25Mhz,ADCʱÖÓ×îºÃ²»Òª³¬¹ý36Mhz      ADC_CommonInit(&ADC_CommonInitStructure);//³õʼ»¯

//这里是设置常规模式

    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//     ADC_InitStructure.ADC_ScanConvMode = DISABLE;//     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//     ADC_InitStructure.ADC_NbrOfConversion = 1;//     ADC_Init(ADC1, &ADC_InitStructure);//          ADC_RegularChannelConfig(ADC1, ADC_Channel_9,1,ADC_SampleTime_480Cycles);//     ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);     ADC_DMACmd(ADC1, ENABLE);//     ADC_Cmd(ADC1, ENABLE);//     ADC_SoftwareStartConv(ADC1);//

    ADC_RegularChannelConfig(ADC1, ADC_Channel_9,1,ADC_SampleTime_480Cycles);//     ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);     ADC_DMACmd(ADC1, ENABLE);//     ADC_Cmd(ADC1, ENABLE);//     ADC_SoftwareStartConv(ADC1);//

 

/*看不动了  眼睛酸痛  暂时先了解ADC 扫描 连续转换等概念 后续用到再看*/

 

                                                                                                                                      16:30    科学园

                                                                                                                                       October 22, 2020


 

总结

 

最新回复(0)