文章目录
前言
一、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:
- 在单次转换模式下:
启动ADC1,则
1.开始转换CH0(ADC_SQR的第一通道)
2.转换完成后停止,等待ADC的下一次启动,继续从第一步开始转换
启动ADC1,则
1.开始转换CH0(ADC_SQR的第一通道)
2.转换完成后回到第一步。
在单次转换模式下:
启动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
总结