【STM32U5A5ZJ开发板】 ADC DMA测试及UART输出
[复制链接]
STM32U5A5ZJ开发板使用的芯片配置有多达3个ADC通道,分别为ADC1、ADC2、ADC4,ADC1通道的采样为14bit,使用超采样技术可以达到16bit,本次测试只使用了ADC4通道配合GPDMA进行采集,ST公司虽然配置了STM32Cube的STM32U5XXX的设置,但是却没有提供HAL库的相关设置只提供了部分较为底层的LL库设置代码。所以需要更加深入的了解芯片的相关设置。
1、芯片的时钟设置。
STM32U5A5ZJ的时钟设置对于较为基础的STM32F系列增加了很多低功耗的设置,本身ST的时钟功能就较为丰富导致设置比较复杂,增加了低功耗以后就又增加了复杂度。希望各位网友有关ST公司较为完整的全面的中文资料请告知。
本次测试使用外部晶振,所以不涉及低功耗内容。
ADC的时钟也相应的设置为HSE,设置ADC的工作时钟为16MHZ。个人经验:外部时钟似乎能够提高ADC的稳定性,没有严格验证
2、ADC通道设置
本次测试使用ADC4通道配合GPDMA采集,设置为ADC4的IN4通道引脚PC3,
ADC4通道的设置除了通道设置外还有几个较为重要的设置,
(1)采样率设置,时钟分频设置为1,ADC4通道的工作频率为HSE的16MHZ,采样时间周期为1.5个采样周期,
(2)采样精度,设置为12bit,因为ADC4最高为12bit
(3)ADC4的DMA设置需要转到GPDMA的设置。
上图为具体的设置。
3、GPDMA设置
DMA通道设置为10,模式为Linked-List,这是一种新的DMA内存模式,传统的DMA只能使用连续的内存块,所以对内存的要求较为严格,因此DMA的长度受到一定的限制。而链接表结构则可以不使用连续的内存空间。但是结构较为复杂。GPDMA的设置为两个重要部分,
(1)工作模式设置,工作模式为连续模式,端口为Port1
(2)LINKED链接表设置
除了工作模式外,还需要设置链接表,ST公司提供了链接表的设置工具。链接实际为数据结构中的队列结构。
找到LINKEDLIST项目,设置GPDMA的各项参数,主要设置:队列名称:ADCQueue,链表数据结构:GPDMA,工作模式:Circular,队列头指针:ADCNode
指针节点设置。
4、main主程序
程序主要是引入DMA队列控制初始化和ADC工作设置。
-
-
-
-
- #include "main.h"
-
-
-
-
- #include <stdio.h>
-
-
-
-
-
-
-
-
-
- #if defined(__ICCARM__)
-
- int iar_fputc(int ch);
- #define PUTCHAR_PROTOTYPE int putchar(int ch)
- #elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)
-
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #elif defined(__GNUC__)
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #endif /* __ICCARM__ */
-
-
-
-
-
- uint32_t uhADCxConvertedData_Voltage_mVolt = 0;
-
- #define ADC_CONVERTED_DATA_BUFFER_SIZE ((uint32_t) 32) /* Size of array aADCxConvertedData[] */
- uint32_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];
-
-
- ADC_HandleTypeDef hadc4;
-
- DMA_HandleTypeDef handle_GPDMA1_Channel10;
-
- UART_HandleTypeDef hlpuart1;
- UART_HandleTypeDef huart1;
-
-
-
-
-
-
- void SystemClock_Config(void);
- static void SystemPower_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_GPDMA1_Init(void);
- static void MX_ADC4_Init(void);
- static void MX_LPUART1_UART_Init(void);
- static void MX_ICACHE_Init(void);
- static void MX_USART1_UART_Init(void);
-
-
-
-
-
-
-
-
-
-
- int main(void)
- {
-
-
-
-
-
-
-
- HAL_Init();
-
-
-
-
-
-
- SystemClock_Config();
-
-
- SystemPower_Config();
-
-
-
-
-
-
- MX_GPIO_Init();
- MX_GPDMA1_Init();
- MX_ADC4_Init();
- MX_LPUART1_UART_Init();
- MX_ICACHE_Init();
- MX_USART1_UART_Init();
-
- MX_ADCQueue_Config();
- __HAL_LINKDMA(&hadc4, DMA_Handle, handle_GPDMA1_Channel10);
- if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel10, &ADCQueue) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_ADC_Start_DMA(&hadc4,
- (uint32_t *)aADCxConvertedData,
- (ADC_CONVERTED_DATA_BUFFER_SIZE)
- ) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
-
- while (1)
- {
-
- HAL_Delay(200);
- for(uint16_t i=0;i<ADC_CONVERTED_DATA_BUFFER_SIZE;i++)
- {
- uhADCxConvertedData_Voltage_mVolt += aADCxConvertedData[i];
- }
-
- printf("mVolt=%d \n",uhADCxConvertedData_Voltage_mVolt/ADC_CONVERTED_DATA_BUFFER_SIZE);
- uhADCxConvertedData_Voltage_mVolt = 0;
-
- }
-
- }
-
-
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-
-
-
- if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;
- RCC_OscInitStruct.PLL.PLLM = 1;
- RCC_OscInitStruct.PLL.PLLN = 20;
- RCC_OscInitStruct.PLL.PLLP = 2;
- RCC_OscInitStruct.PLL.PLLQ = 2;
- RCC_OscInitStruct.PLL.PLLR = 2;
- RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1;
- RCC_OscInitStruct.PLL.PLLFRACN = 0;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
- |RCC_CLOCKTYPE_PCLK3;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
-
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
-
- static void SystemPower_Config(void)
- {
-
-
-
- HAL_PWREx_DisableUCPDDeadBattery();
-
-
-
- if (HAL_PWREx_ConfigSupply(PWR_SMPS_SUPPLY) != HAL_OK)
- {
- Error_Handler();
- }
-
-
- }
-
-
- static void MX_ADC4_Init(void)
- {
-
-
-
-
-
- ADC_ChannelConfTypeDef sConfig = {0};
-
-
-
-
-
-
-
- hadc4.Instance = ADC4;
- hadc4.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
- hadc4.Init.Resolution = ADC_RESOLUTION_12B;
- hadc4.Init.DataAlign = ADC_DATAALIGN_RIGHT;
- hadc4.Init.ScanConvMode = ADC4_SCAN_DISABLE;
- hadc4.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
- hadc4.Init.LowPowerAutoPowerOff = ADC_LOW_POWER_NONE;
- hadc4.Init.LowPowerAutoWait = DISABLE;
- hadc4.Init.ContinuousConvMode = DISABLE;
- hadc4.Init.NbrOfConversion = 1;
- hadc4.Init.DiscontinuousConvMode = DISABLE;
- hadc4.Init.ExternalTrigConv = ADC_SOFTWARE_START;
- hadc4.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
- hadc4.Init.DMAContinuousRequests = DISABLE;
- hadc4.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;
- hadc4.Init.Overrun = ADC_OVR_DATA_PRESERVED;
- hadc4.Init.SamplingTimeCommon1 = ADC4_SAMPLETIME_1CYCLE_5;
- hadc4.Init.SamplingTimeCommon2 = ADC4_SAMPLETIME_1CYCLE_5;
- hadc4.Init.OversamplingMode = DISABLE;
- if (HAL_ADC_Init(&hadc4) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
- sConfig.Channel = ADC_CHANNEL_4;
- sConfig.Rank = ADC4_REGULAR_RANK_1;
- sConfig.SamplingTime = ADC4_SAMPLINGTIME_COMMON_1;
- sConfig.OffsetNumber = ADC_OFFSET_NONE;
- sConfig.Offset = 0;
- if (HAL_ADC_ConfigChannel(&hadc4, &sConfig) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
-
- }
-
-
- static void MX_GPDMA1_Init(void)
- {
-
-
-
-
-
-
- __HAL_RCC_GPDMA1_CLK_ENABLE();
-
-
-
-
- handle_GPDMA1_Channel10.Instance = GPDMA1_Channel10;
- handle_GPDMA1_Channel10.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
- handle_GPDMA1_Channel10.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
- handle_GPDMA1_Channel10.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;
- handle_GPDMA1_Channel10.InitLinkedList.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;
- handle_GPDMA1_Channel10.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
- if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel10) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel10, DMA_CHANNEL_NPRIV) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
-
- }
-
-
- static void MX_ICACHE_Init(void)
- {
-
-
-
-
-
-
-
-
-
-
-
- if (HAL_ICACHE_ConfigAssociativityMode(ICACHE_1WAY) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_ICACHE_Enable() != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
-
- }
-
-
- static void MX_LPUART1_UART_Init(void)
- {
-
-
-
-
-
-
-
-
- hlpuart1.Instance = LPUART1;
- hlpuart1.Init.BaudRate = 115200;
- hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
- hlpuart1.Init.StopBits = UART_STOPBITS_1;
- hlpuart1.Init.Parity = UART_PARITY_NONE;
- hlpuart1.Init.Mode = UART_MODE_TX_RX;
- hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- hlpuart1.FifoMode = UART_FIFOMODE_DISABLE;
- if (HAL_UART_Init(&hlpuart1) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
-
- }
-
-
- static void MX_USART1_UART_Init(void)
- {
-
-
-
-
-
-
-
-
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
- huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
-
-
-
-
- }
-
-
- static void MX_GPIO_Init(void)
- {
-
-
-
-
- __HAL_RCC_GPIOC_CLK_ENABLE();
- __HAL_RCC_GPIOH_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
-
-
-
- }
-
-
- PUTCHAR_PROTOTYPE
- {
-
-
- HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
-
- return ch;
- }
-
-
-
- void Error_Handler(void)
- {
-
-
- __disable_irq();
- while (1)
- {
- }
-
- }
-
- #ifdef USE_FULL_ASSERT
-
- void assert_failed(uint8_t *file, uint32_t line)
- {
-
-
-
-
- }
- #endif /* USE_FULL_ASSERT */
-
ADC工作设置
- __HAL_LINKDMA(&hadc4, DMA_Handle, handle_GPDMA1_Channel10);
- if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel10, &ADCQueue) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_ADC_Start_DMA(&hadc4,
- (uint32_t *)aADCxConvertedData,
- (ADC_CONVERTED_DATA_BUFFER_SIZE)
- ) != HAL_OK)
- {
- Error_Handler();
- }
首先连接DMA通道10和ADC4的句柄,__HAL_LINKDMA(&hadc4, DMA_Handle, handle_GPDMA1_Channel10);
连接后开始ADC采集,HAL_ADC_Start_DMA(&hadc4, (uint32_t *)aADCxConvertedData, (ADC_CONVERTED_DATA_BUFFER_SIZE) )
ADC为循环模式,工作开始后就可以自动的进行采集。
主程序中每个200毫秒,将采集数据平均后输出。
本次测试,可以发现测试的精度较为准确,可以达到1个mV的精度,但是这个精度是我的输出仪器的精度,不是ADC的精度。
|