STM32F303RE 芯片有4个ADC, 采样频率据说能达到5Mbsps 已经算是非常高的了. 比较适合做采样
参考文章 STM32三个ADC同步规则采样
参考上面的配置文章. 经过不断的失败和重复尝试, 最后终于搞通了. 其中遇到了好几个错误, 也许是 STM32F303RE 与其它的不一样, 也许是我用的固件库库版本不一样… 我目前用的是 STM32Cube FW_F3 V1.11.3 这个版本的 Firmware Package, 我的开发工具是 STM32CubeIDE
第一步配置ADC1 配置ADC1 的 DMA 这里一定要选择 Word, 为啥一定要是Word? 我也是被这个问题困扰了好久. 经过我一番好找, 查边各种文章, 最后终于搞明白了.
答案是, 在同步ADC模式中, ADC1是主ADC, ADC2是从ADC, 当模式为 [同步规则模式] 时 数据是存放在 ADC1_2 的 CDR 寄存器中的. 我是怎么知道的? 这是花了好长时间从寄存器参考手册中查到的.
Dual ADC modes In devices with two ADCs or more, dual ADC modes can be used (see Figure 97): ? ADC1 and ADC2 can be used together in dual mode (ADC1 is master) ? ADC3 and ADC4 can be used together in dual mode (ADC3 is master)
译文如下: 双ADC模式 在有两个或多个ADC的设备中,可以使用双ADC模式(见图97): ?ADC1和ADC2双模式同时使用(ADC1为主) ?ADC3和ADC4双模式同时使用(ADC3为主)
In dual ADC mode, the converted data of the master and slave ADC can be read in parallel, by reading the ADC common data register (ADCx_CDR). The status bits can be also read in parallel by reading the dual-mode status register (ADCx_CSR).
译文如下 在双ADC模式下,通过读取ADC公共数据寄存器(ADCx_CDR),可以并行读取主、从ADC的转换数据。状态位也可以通过读取双模式状态寄存器(ADCx_CSR)来并行读取。
这里额外插一句, 我觉得 , 学习STM32 需要掌握的知识除了c语言之外,还需要手边放一个 [寄存器级别的 参考手册], 这个参考手册是芯片设计人员写给程序开发人员看的, 里面非常非常详细的介绍了每个寄存器的作用, 甚至还写了使用的注意事项和方法. 能看懂这个手册基本上就会用stm32了… 看起来也不是很难. stm32 参考手册好像还有中文版. 看参考手册要注意芯片型号要对应, 别看了半天最后发现型号都不一样的. 这个手册是可以从http://www.st.com 官方下载的. 怎么下载就不展开讲了.
另外这里要分享一个好东西, STM32CubeIDE 有寄存器查看窗口, 好像Kiel 也有. 能够查看寄存器的当前值, 基本上再根据寄存器的参考手册就知道当前的机器内部运行情况 . 而不是瞎猜了. 回到正题. 配置ADC2, 基本上跟ADC1一致,有几个选型因为ADC1选好之后ADC2就不能选了, 有些已经默认选好了. 选好通道, 再添加DMA
下面就是主代码
#define MAX_REC_COUNT 100
#define MAX_ADC_COUNT 2000
volatile uint16_t Adc12_Values[MAX_ADC_COUNT*2];
volatile uint16_t Adc34_Values[MAX_ADC_COUNT*2];
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_ADC3_Init();
MX_ADC4_Init();
MX_TIM4_Init();
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc3, ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc4, ADC_SINGLE_ENDED);
HAL_StatusTypeDef state = HAL_OK;
HAL_ADC_Start(&hadc2);
HAL_ADC_Start(&hadc4);
state = HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)Adc12_Values, MAX_ADC_COUNT);
state = HAL_ADCEx_MultiModeStart_DMA(&hadc3, (uint32_t*)Adc34_Values, MAX_ADC_COUNT);
if(state == HAL_OK){
int a=0;
}
HAL_TIM_Base_Start(&htim4);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, ReceiveBuffer, MAX_REC_COUNT);
while (1)
{
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)SendBuffer, sizeof(SendBuffer));
HAL_Delay(1000);
}
}
ADC时钟的配置, 需要自己根据项目需求更改合适的数值. 前面的ADC时钟源要选这个Timer… 注意Trigger Event Selection TRGO 要选择 Update Event
注意事项: 前面的参考文章中并未说明, HAL_ADCEx_MultiModeStart_DMA 要求, 主ADC不能先启动, 只能先启动从属ADC2和ADC4,
HAL_ADC_Start(&hadc2);
HAL_ADC_Start(&hadc4);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)Adc12_Values, MAX_REC_COUNT/2);
HAL_ADCEx_MultiModeStart_DMA(&hadc3, (uint32_t*)Adc34_Values, MAX_REC_COUNT/2);
我操这点功能搞了2天…
|