拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:
我直接用点灯的例程来改串口例程,方便省事:
整理好的例程结构如下:
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:
我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
- int fputc(int ch , FILE *f)
- {
- while ((USART1->ISR & 0X40) == 0);
- USART1->TDR = (uint8_t)ch;
- return ch;
- }
- void UART1_Init(uint32_t baud)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
- __HAL_RCC_USART1_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
- </font> <font face="微软雅黑" size="5">
- huart1.Instance = USART1;
- huart1.Init.BaudRate = baud;
- 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;
- HAL_UART_Init(&huart1);
- }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:
- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
- DMA_NodeTypeDef Node_GPDMA1_Channel0;
- DMA_QListTypeDef List_GPDMA1_Channel0;
- DMA_HandleTypeDef handle_GPDMA1_Channel0;
- void LPUART1_Init(uint32_t baud)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
- DMA_NodeConfTypeDef NodeConfig;
- __HAL_RCC_LPUART1_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPDMA1_CLK_ENABLE();
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
- PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- </font> <font face="微软雅黑" size="5">
- GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
- GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
- </font> <font face="微软雅黑" size="5">
- hlpuart1.Instance = LPUART1;
- hlpuart1.Init.BaudRate = baud;
- 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.OverSampling = UART_OVERSAMPLING_16;
- hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
- hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- HAL_UART_Init(&hlpuart1);
- </font> <font face="微软雅黑" size="5">
- __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
- HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
- HAL_NVIC_EnableIRQ(LPUART1_IRQn);
- </font> <font face="微软雅黑" size="5">
- NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
- NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
- NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
- NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
- NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
- NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
- NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
- NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
- NodeConfig.Init.SrcBurstLength = 1;
- NodeConfig.Init.DestBurstLength = 1;
- NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
- NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
- NodeConfig.Init.Mode = DMA_NORMAL;
- NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
- NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
- NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
- HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);
- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);
- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
- handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
- handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
- handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
- handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
- HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);
- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
- </font> <font face="微软雅黑" size="5">
- HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
- }
- void LPUART1_Send_Char(uint8_t ch)
- {
- while ((LPUART1->ISR & 0X40) == 0);
- LPUART1->TDR = (uint8_t)ch;
- }
- void LPUART1_Send_String(uint8_t * s)
- {
- uint32_t i;
- for(i = 0 ; s != '\0' ; i++)
- LPUART1_Send_Char(s);
- }
- void GPDMA1_Channel0_IRQHandler(void)
- {
- HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
- }
- uint8_t aRxBuffer[RXBUFFERSIZE];
- void LPUART1_IRQHandler(void)
- {
- // int temp;
- if(LPUART1->ISR & UART_FLAG_IDLE)
- {
- __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
- printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
- </font> <font face="微软雅黑" size="5">
- HAL_UART_DMAStop(&hlpuart1);
- HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
- // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
- // uart1_recv_end_flag = 1;
- }
- }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?
没看懂你的表述是什么意思
就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?
[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄
使用的是全功能的Type-c线吗?
没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用