这一期,我们接着上一期的内容,来看看ADC实验与DMA实验在实际的应用中的结合使用。就比如我们可以使用在自制遥控器的摇杆值的获取和传输上。
下面举例一个两个摇杆的遥控器的摇杆获取的代码的ADC配置部分。
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //使能扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //使能连续模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //右对齐
ADC_InitStructure.ADC_NbrOfChannel = 6; //6个ADC转换在规则序列中
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_56Cycles); //PC0
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_56Cycles); //PC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_56Cycles); //PC2
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_56Cycles); //PC3
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_56Cycles); //PC4
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_56Cycles); //PC5
ADC_DMACmd(ADC1, ENABLE); //使能ADC模块的DMA传输功能
ADC_DMALastTransferCmd(ADC1, ENABLE); //使能ADC的DMA方式并在最后一次传输结束后终止传输请求
ADC_Cmd(ADC1, ENABLE); //使能ADC1
我们在遥控的摇杆获取中需要使用到ADC1的6个通道,每3个负责一个摇杆值的获取。上面的配置大部分在上一期的ADC实验中都是讲过的,这里还有一些要讲解和强调的点以及几个新的函数要给大家介绍一下。
首先是这个扫描模式,扫描模式就是循环扫描我们使能的通道,按我们设置的顺序进行循环转换。因为我们在这里使用了6个通道来获取我们遥控的摇杆值,这6个通道是需要不断循环进行转换的,所以我们需要开启扫描模式使一个通道转换完成后自动开启下一个通道的转换。
其次是这个连续转换模式,这个大家应该都很清楚,但是还是要强调一下。连续转换模式就是和单次转换模式相对的,连续转换模式是该通道完成一次转换后接着进行下一次转换。因为我们的遥控是需要一直获取我们的摇杆值的,所以我们要使能这个连续转换模式。
还有就是两个新函数,先将ADC_DMACmd()函数。该函数用于配置 ADC 模块的 DMA 传输功能,可以将 ADC 采样结果自动传输到指定的内存区域,减少 CPU 的负担,提高系统效率。在这里就体现到 ADC 和 DMA 的联系了,通过使用这个函数使能 ADC 模块的 DMA 功能,就可以在获取采样值之后自动传输到指定的内存区域,在这期间不需要 CPU 的参与。
还有一个新的函数是ADC_DMALastTransferCmd(),这个函数是在使用 ADC 的 DMA 模式下控制 DMA 传输终止的函数。当我们使用 ADC 模块采集数据,并通过 DMA 方式将采集到的数据存储到内存中时,可以通过这个函数使 DMA 在最后一次数据传输完毕后自动停止传输请求,以减少资源占用。当启用 DMA 传输模式时,每当 ADC 转换完成后即会通过 DMA 请求传输数据。ADC_DMALastTransferCmd 函数默认情况下是禁止的,因此,在最后一次数据转换完成后,DMA 仍然会继续完成一次数据传输请求。而如果启用了 ADC_DMALastTransferCmd 函数,当最后一次转换完成后,DMA 仅会传输最后一次的转换结果,并切换到空闲状态,使得 DMA 完成传输请求,同时不会接收新的 DMA 传输请求,从而实现 DMA 在最后一次传输后自动停止传输请求的功能。这个函数在使用 STM32F1 的 ADC 和 DMA 进行数据采集时非常有用,可以避免多余的 DMA 传输请求和占用过多的系统资源,提高了系统的稳定性和效率。
介绍完ADC部分,下面我们来看看DMA部分的配置吧。DMA的部分与前面上一期DMA传输实验的相比没有新的东西,只有一些配置要根据需要进行相应的使用需求做一些改变罢了。
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR); //外设地址为ADC_DR
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_Value; //内存地址为创建的数组ADC_Value
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向为外设到存储器
DMA_InitStructure.DMA_BufferSize = 6; //与通道数一样
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_Medium; //优先级为中等
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //不使能内存到内存方向
DMA_Init(DMA_CHx, &DMA_InitStructure);
上面的配置就是遥控的摇杆值获取的ADC和DMA传输的设置了,通过这样的设置之后就可以实现获取遥控的摇杆值数据后直接进行DMA传输到我们划分出来的内存区域中,且CPU不参与数据的处理。我们剩下要做的就是对内存区域中的摇杆值数据进行处理,比如数据的转化、计算、2.4G无线通信或蓝牙通信等传输到其他设备的处理。
本期的内容到这里就结束了!同时,从下一期开始我们将进入一个非常重要的专题学习了。有的小伙伴应该猜到这个专题是什么了。没错,我们在下一期就要进入通信专题的学习了。通信专题在stm32乃至全部单片机的学习中都是至关重要的一个部分,因为以后在单片机的开发过程中将会使用到各种的通信。反正就是一句话:什么都离不开通信!!!