本帖最后由 lugl4313820 于 2023-12-18 22:35 编辑
【实验硬件】
- STM32U599J-DK开发板。
- 数据电源
- FLUKE 45万用表
【软件环境】
- STM32CubeIDE 1.14
- TouchGFX Designer 4.23
【实验步骤】
- 使用touchGFX创建一个基于STM32U599J-DK的空白工程。
- 创建一个文本框用于显示电压值:
- 生成工程后用stm32CubeIDE打开工程。
- ADC的配置:
- 从原理图上,找到CN9的ADC引脚图,我这里选用PA4即ADC1、2、4的通道9。
- 打开stm32CubeMAX将PA4选中并配置为通道9
- 配置他的参数为
- 接着去配置DMA
【注意】DMA一定要选12通道以上,我按照别人的设置为通道10,运行时始终报错,经过半天的调试才找到,DMA有个断言,需要在12通道上以上才能成功,他的判断在stm32u5a9xx.h中有说明:
- 打开中断:
到此DMA与ADC就配置好了,接下来是配置DMA接收的队列,这个也是耽误了我好长时间的一个难题,最后找到stm32U575的ADC_DMA的例程才发现需要配置这个。
- 配置ADCQueue:
具体的参数太多了,翻了好久的数据手册,结合stm32U575的例程才配置好。有空时再来研究。
到这里,stm32CubeMAX的配置告一段落。
- 生成代码后需要要添加ADCQueue的配置函数,我直接复制了stm32U575的例程的linked_list.c/h 到工程中。主要的代码如下:
HAL_StatusTypeDef MX_ADCQueue_Config(void)
{
HAL_StatusTypeDef ret = HAL_OK;
/* DMA node configuration declaration */
DMA_NodeConfTypeDef pNodeConfig;
/* Set node configuration ################################################*/
pNodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
pNodeConfig.Init.Request = GPDMA1_REQUEST_ADC4;
pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
pNodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
pNodeConfig.Init.SrcInc = DMA_SINC_FIXED;
pNodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
pNodeConfig.Init.SrcBurstLength = 1;
pNodeConfig.Init.DestBurstLength = 1;
pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
pNodeConfig.SrcAddress = 0;
pNodeConfig.DstAddress = 0;
pNodeConfig.DataSize = 0;
/* Build ADCNode Node */
ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &ADCNode);
/* Insert ADCNode to Queue */
ret |= HAL_DMAEx_List_InsertNode_Tail(&ADCQueue, &ADCNode);
ret |= HAL_DMAEx_List_SetCircularMode(&ADCQueue);
return ret;
}
- 在freertos.c中我们初始化adc、dma,并让他一直在转换,把数据放到队例数据中。
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN defaultTask */
MX_ADCQueue_Config(); //配置队列
__HAL_LINKDMA(&hadc4, DMA_Handle, handle_GPDMA1_Channel12); //链接dma到adc4到GDMA通道12
if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel12, &ADCQueue) != HAL_OK)
{
Error_Handler();
}
//开启DMA转换
if (HAL_ADC_Start_DMA(&hadc4,
(uint32_t *)aADCxConvertedData,
(ADC_CONVERTED_DATA_BUFFER_SIZE)
) != HAL_OK)
{
Error_Handler();
}
/* Infinite loop */
for(;;)
{
osDelay(1000);
}
/* USER CODE END defaultTask */
}
- 在touchGFX的screen1View.hpp中增加handleTickEvent函数,并在screen1View.cpp中实现:
void Screen1View::handleTickEvent()
{
tick ++;
float value;
if(tick == 60)
{
for(int i=0; i<8;i++)
{
value += aADCxConvertedData;
}
value = value*1.78/8/4095;
Unicode::snprintfFloat(textAreaADCValueBuffer, TEXTAREAADCVALUE_SIZE, "%2.4f", value);
textAreaADCValue.invalidate();
value = 0;
tick = 0;
}
}
代码的主要逻辑是把8个获取到的数据,做简单的平均,然后更新到屏的文本框上面。
【实现效果】
从检测的结果来看,精度还是非常不错的。
【讨论】
Stm32U599这款芯片的例程不是很丰富,很多要从stm32U575等来借鉴。出现问题调试也是非常需要时间。弄好这个例程花了我两天的时间,这里记录下来,一来方便以后查阅,二来给大家引个路。
GDMA与传统的DMA的配置流程与方法不尽相同,这是大家如果使用这款开发板需要注意的。
当然也许还有其他的人有很好的方法,或者我的一些操作也可能有误,希望各位大佬们指点我一下。