IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F303RE 四个ADC同步规则采样 -> 正文阅读

[嵌入式]STM32F303RE 四个ADC同步规则采样

STM32F303RE 芯片有4个ADC, 采样频率据说能达到5Mbsps 已经算是非常高的了.
比较适合做采样

参考文章
STM32三个ADC同步规则采样

参考上面的配置文章. 经过不断的失败和重复尝试, 最后终于搞通了.
其中遇到了好几个错误, 也许是 STM32F303RE 与其它的不一样, 也许是我用的固件库库版本不一样… 我目前用的是
STM32Cube FW_F3 V1.11.3 这个版本的 Firmware Package, 我的开发工具是 STM32CubeIDE

第一步配置ADC1
在这里插入图片描述
在这里插入图片描述
配置ADC1 的 DMA 这里一定要选择 Word, 为啥一定要是Word?
DMA配置
我也是被这个问题困扰了好久. 经过我一番好找, 查边各种文章, 最后终于搞明白了.

答案是, 在同步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]; // 这里是 uint16_t  类型的,下面用的时候是转换成 (uint32_t *) 的指针
volatile uint16_t Adc34_Values[MAX_ADC_COUNT*2]; // 这里是 uint16_t  类型的,下面用的时候是转换成 (uint32_t *) 的指针
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  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();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  //开启DMA接收命令
  //HAL_UART_Receive_DMA(&huart2, ReceiveBuffer, 10);

	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); //校准


	// 启动adc dma模式下面这几句就够了参考  https://www.stm32cube.com/article/212,
	HAL_StatusTypeDef state = HAL_OK;

	//	HAL_ADC_Start(&hadc1); //不能启动主ADC, 如果启动了, 后面的 HAL_ADCEx_MultiModeStart_DMA 就不能正常启动了.
		HAL_ADC_Start(&hadc2);
	//	HAL_ADC_Start(&hadc3); //不能启动主ADC, 如果启动了, 后面的 HAL_ADCEx_MultiModeStart_DMA 就不能正常启动了.
		HAL_ADC_Start(&hadc4);//启动ADC

	 state = HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)Adc12_Values, MAX_ADC_COUNT);//启动同步规则模式及DMA,4个ADC 
     state = HAL_ADCEx_MultiModeStart_DMA(&hadc3, (uint32_t*)Adc34_Values, MAX_ADC_COUNT);//启动同步规则模式及DMA,4个ADC 

//	 state = HAL_ADC_Start_DMA(&hadc1, (uint32_t*)Adc1_4_Values[0], MAX_ADC_COUNT);  //这个不需要, 也不行.
//	 state = HAL_ADC_Start_DMA(&hadc3, (uint32_t*)Adc1_4_Values[1], MAX_ADC_COUNT);  //这个不需要, 也不行.

// 这里调试 state 的状态可以方便知道前面的配置是否正常..如果不是HAL_OK可以调试跟踪进去,看看是哪一步代码出错了.
    if(state == HAL_OK){
			int a=0;
	}


  HAL_TIM_Base_Start(&htim4);//启动TIM2,用于触发ADC采样
 
  HAL_UARTEx_ReceiveToIdle_DMA(&huart2, ReceiveBuffer, MAX_REC_COUNT);


  while (1)
  {
             /* USER CODE END WHILE */
	        //HAL_UART_Transmit(&huart2, (uint8_t *)SendBuffer, sizeof(SendBuffer),10);
//	  	   if(DMA_Flag == 1)//AD转换完成标准
//	        {
//	             DMA_Flag = 0;
//	             HAL_TIM_Base_Stop(&htim4);
//	             HAL_ADCEx_MultiModeStop_DMA(&hadc1);
//	             HAL_ADC_Stop(&hadc1);//停止采样
//	             HAL_ADC_Stop(&hadc2);//停止采样
//	             HAL_ADC_Stop(&hadc3);//停止采样
//	             HAL_ADC_Stop(&hadc4);//停止采样
//
//				 for(uint8_t i=0;i<100;i++)
//				 {
						sprintf(str,"$,%d,%d,%d",Adc_Values[i][0],Adc_Values[i][1],Adc_Values[i][2]);
						HAL_UART_Transmit(&huart8, (uint8_t*)str,strlen(str),100);//串口发送到上位机
//				 }
				 HAL_ADC_Start(&hadc1);
//				 HAL_ADC_Start(&hadc2);
				 HAL_ADC_Start(&hadc3);
//				 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);
//
//				 HAL_TIM_Base_Start(&htim4);//重新启动采样
//			//	  ————————————————
//			//	  版权声明:本文为CSDN博主「天外飞仙CUG」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//			//	  原文链接:https://blog.csdn.net/zhang062061/article/details/113735874
//	        }

			  HAL_UART_Transmit_DMA(&huart2, (uint8_t *)SendBuffer, sizeof(SendBuffer));//DMA model
			 // HAL_UART_Transmit_DMA(&huart2, (uint8_t *)adc_vals, sizeof(SendBuffer));//DMA model

			  HAL_Delay(1000);

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

ADC时钟的配置, 需要自己根据项目需求更改合适的数值. 前面的ADC时钟源要选这个Timer… 注意Trigger Event Selection TRGO 要选择 Update Event

在这里插入图片描述

注意事项:
前面的参考文章中并未说明, HAL_ADCEx_MultiModeStart_DMA 要求, 主ADC不能先启动, 只能先启动从属ADC2和ADC4,

//				 HAL_ADC_Start(&hadc1);  // 这个不能启动, 否则下面的HAL_ADCEx_MultiModeStart_DMA(&hadc1, ..)  就不能正常启动.
				 HAL_ADC_Start(&hadc2);
//				 HAL_ADC_Start(&hadc3);  // 这个不能启动, 否则下面的HAL_ADCEx_MultiModeStart_DMA(&hadc3, ..)  就不能正常启动.
 			     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天…

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:44:29  更:2022-09-21 00:46:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:39:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码