qinyunti 发表于 2022-12-15 21:33

【ST NUCLEO-U575ZI-Q 测评 】串口收发测试

<div class='showpostmsg'> 本帖最后由 qinyunti 于 2022-12-15 21:57 编辑

<p>&nbsp;</p>

<h1><b>前言</b></h1>

<p>串口作为最常用的通讯接口,我们先实现串口的收发,后面标准输入输出,但因调试等都依赖于传口。</p>

<h1><b>串口模块</b></h1>

<p>参见《58 Low-power universal asynchronous receiver transmitter (LPUART)》</p>

<h2><b>引脚</b></h2>

<p>&nbsp;</p>

<p>使用PG7-PG8 &nbsp;LPUART1-TX LPUART1-RX,对应AF8</p>

<p> &nbsp;</p>

<p> &nbsp;</p>

<p></p>

<div class="parsedown-markdown">
<p>LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOG);</p>

<p>&nbsp;&nbsp;/* PG7 TX */</p>

<p>LL_GPIO_InitTypeDef GPIO_InitStruct;</p>

<p>//LL_GPIO_StructInit(&amp;GPIO_InitStruct);</p>

<p>GPIO_InitStruct.Pin = LL_GPIO_PIN_7;</p>

<p>GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;</p>

<p>GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;</p>

<p>GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;</p>

<p>GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;</p>

<p>GPIO_InitStruct.Alternate = LL_GPIO_AF_8;</p>

<p>LL_GPIO_Init(GPIOG, &amp;GPIO_InitStruct);</p>

<p>&nbsp;&nbsp;/* PG8 RX */</p>

<p>GPIO_InitStruct.Pin = LL_GPIO_PIN_8;</p>

<p>GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;</p>

<p>GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;</p>

<p>GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;</p>

<p>GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;</p>

<p>GPIO_InitStruct.Alternate = LL_GPIO_AF_8;</p>

<p>LL_GPIO_Init(GPIOG, &amp;GPIO_InitStruct);</p>
</div>

<p>&nbsp;</p>

<p>&nbsp;</p>

<h2><b>时钟</b></h2>

<p>从时钟树可以看到LPUART1时钟可以来源于SYSCLK-&gt;AHB-&gt;APB3-&gt;PCLK3</p>

<p>也可以来源于MSIK,HSI16,LSE。我们选择PCLK3。</p>

<p> &nbsp;</p>

<p>AHB和APB3分频之前在RCC配置时设置</p>

<p>&nbsp;</p>

<div class="parsedown-markdown">
<p>RCC_ClkInitTypeDef pRCC_ClkInitStruct;</p>

<p>pRCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;</p>

<p>pRCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;</p>

<p>pRCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;</p>

<p>pRCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;</p>

<p>pRCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;</p>

<p>pRCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV2;</p>

<p>HAL_RCC_ClockConfig(&amp;pRCC_ClkInitStruct, FLASH_LATENCY_4);</p>
</div>

<p>&nbsp;</p>

<p>这里分别是分频1和2所以 LPUART的输入时钟是160MHz/2=80MHz</p>

<p>&nbsp;</p>

<p>使能时钟</p>

<p>&nbsp;</p>

<div class="parsedown-markdown">
<p>LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_LPUART1);</p>
</div>

<p>&nbsp;</p>

<p>&nbsp;</p>

<h2><b>串口配置</b></h2>

<p>&nbsp;</p>

<div class="parsedown-markdown">
<p>LL_LPUART_InitTypeDef LPUART_InitStruct;</p>

<p>LPUART_InitStruct.BaudRate = 115200;</p>

<p>LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;</p>

<p>LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;</p>

<p>LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;</p>

<p>LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;</p>

<p>LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;</p>

<p>LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;</p>

<p>LL_LPUART_Init(LPUART1, &amp;LPUART_InitStruct);</p>
</div>

<p>&nbsp;</p>

<p>&nbsp;</p>

<h2><b>中断配置</b></h2>

<p>使能接收非空中断,发送非空中断暂时不使能(否则使能后马上回进入中断,后续实现中断发送再讲)</p>

<div class="parsedown-markdown">
<p>LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);</p>

<p>//LL_LPUART_EnableIT_TXE_TXFNF(LPUART1);</p>

<p>__NVIC_EnableIRQ(LPUART1_IRQn);</p>

<p>__NVIC_SetPriority(LPUART1_IRQn, 3);</p>
</div>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>LPUART_ISR中中断标志</p>

<p>RXNE中断时读RDR清除标志</p>

<p>TXE中断时写TDR清除标志。</p>

<p> &nbsp;</p>

<h2><b>中断处理</b></h2>

<p>收到数据后原样返回</p>

<p>&nbsp;</p>

<div class="parsedown-markdown">
<p>void LPUART1_IRQHandler(void)</p>

<p>{</p>

<p>if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1) == SET)</p>

<p>{</p>

<p>LL_LPUART_TransmitData8(LPUART1,LL_LPUART_ReceiveData8(LPUART1));</p>

<p>}</p>

<p>if(LL_LPUART_IsActiveFlag_TXE_TXFNF(LPUART1))</p>

<p>{</p>

<p>}</p>

<p>}</p>
</div>

<p>&nbsp;</p>

<h2><b>串口使能</b></h2>

<p>&nbsp;</p>

<div class="parsedown-markdown">
<p>LL_LPUART_Enable(LPUART1);</p>
</div>

<p>&nbsp;</p>

<p>&nbsp;</p>

<h1><b>测试</b></h1>

<p>添加uart.c</p>

<p>&nbsp;</p>

<div class="parsedown-markdown">
<p>#include &quot;stm32u575xx.h&quot;</p>

<p >#include &quot;stm32u5xx_ll_gpio.h&quot;</p>

<p >#include &quot;stm32u5xx_ll_bus.h&quot;</p>

<p >#include &quot;stm32u5xx_ll_lpuart.h&quot;</p>

<p >&nbsp;</p>

<p >&nbsp;</p>

<p >void LPUART1_IRQHandler(void)</p>

<p >{</p>

<p >if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1) == SET)</p>

<p >{</p>

<p >LL_LPUART_TransmitData8(LPUART1,LL_LPUART_ReceiveData8(LPUART1));</p>

<p >}</p>

<p >if(LL_LPUART_IsActiveFlag_TXE_TXFNF(LPUART1))</p>

<p >{</p>

<p >&nbsp;</p>

<p >}</p>

<p >}</p>

<p >&nbsp;</p>

<p >&nbsp;</p>

<p >void uart_init(void)</p>

<p >{</p>

<p >&nbsp;</p>

<p >LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOG);</p>

<p >&nbsp;&nbsp;/* PG7 TX */</p>

<p >LL_GPIO_InitTypeDef GPIO_InitStruct;</p>

<p >//LL_GPIO_StructInit(&amp;GPIO_InitStruct);</p>

<p >GPIO_InitStruct.Pin = LL_GPIO_PIN_7;</p>

<p >GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;</p>

<p >GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;</p>

<p >GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;</p>

<p >GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;</p>

<p >GPIO_InitStruct.Alternate = LL_GPIO_AF_8;</p>

<p >LL_GPIO_Init(GPIOG, &amp;GPIO_InitStruct);</p>

<p >&nbsp;&nbsp;/* PG8 RX */</p>

<p >GPIO_InitStruct.Pin = LL_GPIO_PIN_8;</p>

<p >GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;</p>

<p >GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;</p>

<p >GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;</p>

<p >GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;</p>

<p >GPIO_InitStruct.Alternate = LL_GPIO_AF_8;</p>

<p >LL_GPIO_Init(GPIOG, &amp;GPIO_InitStruct);</p>

<p >&nbsp;</p>

<p >LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_LPUART1);</p>

<p >LL_LPUART_InitTypeDef LPUART_InitStruct;</p>

<p >LPUART_InitStruct.BaudRate = 115200;</p>

<p >LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;</p>

<p >LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;</p>

<p >LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;</p>

<p >LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;</p>

<p >LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;</p>

<p >LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;</p>

<p >LL_LPUART_Init(LPUART1, &amp;LPUART_InitStruct);</p>

<p >&nbsp;</p>

<p >LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);</p>

<p >//LL_LPUART_EnableIT_TXE_TXFNF(LPUART1);</p>

<p >__NVIC_EnableIRQ(LPUART1_IRQn);</p>

<p >__NVIC_SetPriority(LPUART1_IRQn, 3);</p>

<p >&nbsp;</p>

<p >LL_LPUART_Enable(LPUART1);</p>

<p >}</p>

<p >&nbsp;</p>
</div>

<p>uart.h</p>

<div class="parsedown-markdown">
<p>#ifndef UART_H</p>

<p >#define UART_H</p>

<p >&nbsp;</p>

<p >void uart_init(void);</p>

<p >&nbsp;</p>

<p >#endif</p>
</div>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>main.c</p>

<p>main中调用uart_init即可</p>

<p>&nbsp;</p>

<div class="parsedown-markdown">
<p>#include &quot;stm32u575xx.h&quot;<br />
#include &quot;stm32u5xx_ll_gpio.h&quot;<br />
#include &quot;stm32u5xx_ll_bus.h&quot;<br />
#include &quot;uart.h&quot;</p>

<p>void SysTick_Handler(void)<br />
{<br />
&nbsp;&nbsp; &nbsp;static volatile uint32_t num = 0;<br />
&nbsp;&nbsp; &nbsp;if(num++ &gt;= 1000)<br />
&nbsp;&nbsp; &nbsp;{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;LL_GPIO_TogglePin(GPIOB, 1u&lt;&lt;7);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;LL_GPIO_TogglePin(GPIOG, 1u&lt;&lt;2);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;LL_GPIO_TogglePin(GPIOC, 1u&lt;&lt;7);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;num=0;<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;HAL_IncTick();<br />
}</p>

<p><br />
void delay(uint32_t t)<br />
{<br />
&nbsp;&nbsp; &nbsp;volatile uint32_t timeout = t;<br />
&nbsp;&nbsp; &nbsp;while(t--);<br />
}</p>

<p>int main(void)<br />
{<br />
&nbsp;&nbsp; &nbsp;HAL_Init();<br />
&nbsp;&nbsp; &nbsp;LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PWR);<br />
&nbsp;&nbsp; &nbsp;HAL_PWREx_EnableVddIO2();<br />
&nbsp;&nbsp; &nbsp;HAL_PWREx_ConfigSupply(PWR_SMPS_SUPPLY);<br />
#if 1<br />
&nbsp;&nbsp; &nbsp;LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PWR);<br />
&nbsp;&nbsp; &nbsp;HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;RCC_OscInitTypeDef pRCC_OscInitStruct;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.HSIState = RCC_HSI_ON;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLM = 1;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLN = 20;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLP = 1;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLQ = 1;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLR = 2;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_0;<br />
&nbsp;&nbsp; &nbsp;pRCC_OscInitStruct.PLL.PLLFRACN = 0; &nbsp;/* */<br />
&nbsp;&nbsp; &nbsp;HAL_RCC_OscConfig(&amp;pRCC_OscInitStruct);<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;RCC_ClkInitTypeDef pRCC_ClkInitStruct;<br />
&nbsp;&nbsp; &nbsp;pRCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;<br />
&nbsp;&nbsp; &nbsp;pRCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;<br />
&nbsp;&nbsp; &nbsp;pRCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;<br />
&nbsp;&nbsp; &nbsp;pRCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;<br />
&nbsp;&nbsp; &nbsp;pRCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;<br />
&nbsp;&nbsp; &nbsp;pRCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV2;<br />
&nbsp;&nbsp; &nbsp;HAL_RCC_ClockConfig(&amp;pRCC_ClkInitStruct, FLASH_LATENCY_4);<br />
#endif</p>

<p>&nbsp;&nbsp; &nbsp;LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);<br />
&nbsp;&nbsp; &nbsp;LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOG);<br />
&nbsp;&nbsp; &nbsp;LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;LL_GPIO_InitTypeDef GPIO_InitStruct;<br />
&nbsp;&nbsp; &nbsp;//LL_GPIO_StructInit(&amp;GPIO_InitStruct);<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Pin = LL_GPIO_PIN_7;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Alternate = LL_GPIO_AF_0;<br />
&nbsp;&nbsp; &nbsp;LL_GPIO_Init(GPIOB, &amp;GPIO_InitStruct);<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Pin = LL_GPIO_PIN_2;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Alternate = LL_GPIO_AF_0;<br />
&nbsp;&nbsp; &nbsp;LL_GPIO_Init(GPIOG, &amp;GPIO_InitStruct);<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Pin = LL_GPIO_PIN_7;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;<br />
&nbsp;&nbsp; &nbsp;GPIO_InitStruct.Alternate = LL_GPIO_AF_0;<br />
&nbsp;&nbsp; &nbsp;LL_GPIO_Init(GPIOC, &amp;GPIO_InitStruct);<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;uart_init();<br />
&nbsp;&nbsp; &nbsp;while(1)<br />
&nbsp;&nbsp; &nbsp;{<br />
<br />
&nbsp;&nbsp; &nbsp;}&nbsp;&nbsp; &nbsp;<br />
}</p>
</div>

<p>&nbsp;</p>

<p>串口调试助手发送数据,原样收到说明测试OK。</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p>可以在中断服务函数中打断点调试 &nbsp;</p>

<p>也可以查看外设寄存器</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<h1><b>总结</b></h1>

<p>使用库进行外设操作比较简单,一般外设操作就是时钟,引脚,外设参数,中断,使能等几个步骤,得益于完善的库操作起来都比较简单。不过也需要了解外设的基本操作逻辑,有问题查看手册,最需要注意的是,先要使能相应时钟,先清标志最后使能中断,使能模块等。</p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

freebsder 发表于 2022-12-27 14:17

<p>U系列主打安全?</p>

okhxyyo 发表于 2023-1-12 09:42

<p>测评汇总:免费申请|ST NUCLEO-U575ZI-Q https://bbs.eeworld.com.cn/thread-1228653-1-1.html</p>
页: [1]
查看完整版本: 【ST NUCLEO-U575ZI-Q 测评 】串口收发测试