STM32CubeMX
一、配置定时器为PWM产生

二、配置时钟树

三、定时器配置

四、配置完生成程序后,主程序里还要进行启动PWM就可以了
MX_TIM3_Init(); HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//启动。置1 CCER的输出使能位bit4 HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//CCER的bit0
然后可以改变占空比了。
**特别注意:**占空比不能大于自动重载寄存器ARR的值,不然输出的都是高电平。这个问题整了一天。
五、程序分析

/* TIM3 init function */
static void MX_TIM3_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; //------------------实际是调用TIM_Base_SetConfig配置定时器,上一篇分析过-- htim3.Instance = TIM3; htim3.Init.Prescaler = 71; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 99; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_PWM_Init(&htim3) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } //---------------------这个是默认的,不管------------------------------- sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } //----------------配置输出比较部分-- 上图5部分------------------------------- sConfigOC.OCMode = TIM_OCMODE_PWM1;//输出模式PWM1 sConfigOC.Pulse = 80;//占空比 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;//高电平极性 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } //---------------------------------------------------------------------------------- sConfigOC.Pulse = 50; if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } HAL_TIM_MspPostInit(&htim3);//初始化引脚IO }
初始化PWM通道HAL_TIM_PWM_ConfigChannel------>调用
case TIM_CHANNEL_1: { assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); /* Configure the Channel 1 in PWM mode */ TIM_OC1_SetConfig(htim->Instance, sConfig); /* Set the Preload enable bit for channel1 */ htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE;//比较模式寄存器CCMR1的bit3位OC1PE置1,写入到CCR1的值在事件更新时,才会传到影子寄存器。清0则写入CCR1的值会马上起作用 /* Configure the Output Fast mode */ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE;//配置CCMR1的bit2位,输出比较快速使能 htim->Instance->CCMR1 |= sConfig->OCFastMode; } break; //-------------------------------------------------------------------------------- void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) { uint32_t tmpccmrx = 0U; uint32_t tmpccer = 0U; uint32_t tmpcr2 = 0U; /* Disable the Channel 1: Reset the CC1E Bit */ TIMx->CCER &= ~TIM_CCER_CC1E;//关通道 CCER bit0清0 /* 读出三个寄存器的值 */ tmpccer = TIMx->CCER; tmpcr2 = TIMx->CR2; tmpccmrx = TIMx->CCMR1; /* Reset the Output Compare Mode Bits */ tmpccmrx &= ~TIM_CCMR1_OC1M;//复位CCMR1的bit6:4 tmpccmrx &= ~TIM_CCMR1_CC1S;//复制CCMR1的bit1:0 /* Select the Output Compare Mode */ tmpccmrx |= OC_Config->OCMode;//配置OC1M为 110 PWM1模式 /* Reset the Output Polarity level */ tmpccer &= ~TIM_CCER_CC1P;//配置输出极性 CCER的 CC1P位 tmpccer |= OC_Config->OCPolarity; if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))//如果是定时器1的123通道,还要设置互补输出 { assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); /* Reset the Output N Polarity level */ tmpccer &= ~TIM_CCER_CC1NP; /* Set the Output N Polarity */ tmpccer |= OC_Config->OCNPolarity; /* Reset the Output N State */ tmpccer &= ~TIM_CCER_CC1NE; } if(IS_TIM_BREAK_INSTANCE(TIMx))//如果是定时器1,还要设置CR2的bit8 bit9 死区控制 { /* Check parameters */ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); /* Reset the Output Compare and Output Compare N IDLE State */ tmpcr2 &= ~TIM_CR2_OIS1; tmpcr2 &= ~TIM_CR2_OIS1N; /* Set the Output Idle state */ tmpcr2 |= OC_Config->OCIdleState; /* Set the Output N Idle state */ tmpcr2 |= OC_Config->OCNIdleState; } /* 把设置好的值写入这4个寄存器 */ TIMx->CR2 = tmpcr2; TIMx->CCMR1 = tmpccmrx; TIMx->CCR1 = OC_Config->Pulse;//占空比 TIMx->CCER = tmpccer; }
流程图如下:

需要改变占空比的,直接调用
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,dutycycle);
改变寄存器CCR1,改变的值是立即生效还是下一个周期生效取决于CCMR1的OC1PE位
while (1) { while(dutycycle<100) { dutycycle+=10; __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,dutycycle); HAL_Delay(1); } while(dutycycle) { dutycycle-=10; __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,dutycycle); HAL_Delay(1); } }
版权声明:本文为CSDN博主 - D.luffy 的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/liangbin414/article/details/88707340





使用意法半导体最新版的STM32CubeMX配置工具创建STM32 微控制器(MCU)项目,将会更直观,更高效。STM32CubeMX v.5.0的最新设计的多面板GUI界面在不改变屏幕视图的情况下,能够让用户查看更多参数,完成更多任务,从而让优化MCU配置参数变得更加轻松自如,得心应手。
STM32CubeMX帮助用户从800多款STM32产品中选择最适合的产品,配置基本硬件功能,自动生成MCU初始化代码,开启嵌入式项目开发之旅。
用户可以利用功能强大的器件配置实用工具配置微控制器参数,包括可解决冲突的引脚选择器和时钟树设置的辅助,以及能够在早期准确评估能耗需求和节能机会的功耗计算器,还有用于配置外围设备和中间件堆栈的工具,例如,TCP / IP或USB协议栈,并支持参数约束动态验证。
配置完成后,STM32CubeMX会自动生成初始化代码,支持许多常用开发环境,包括适用于IAR-EWARM、Keil MDK-ARM、AC6-SystemWorkbench STM32系列或独立的GCC(GNU编译器集合)工具链项目。
STM32CubeMX是既可在主要PC操作系统上运行,也可通过Eclipse插件运行的独立软件。用户可以从 www.st.com/stm32cubemx 页面免费下载,还可以一起下载STM32Cube其它软件,包括专用硬件抽象层(HAL)中间件和代码示例。
在16年ST就推出了STM32F769I-DISCO开发板,功能搭配可算得上眼前为之一亮,无论是POE、SPDIF输入输出、MEMS麦克风、音频编解码器、还是TFT电容触摸LCD显示屏,各种器件与STM32F769NI这块芯片恰到好处搭配。这块开发板的厚重底蕴难以形容,搭配恰如其分,相得益彰,完美地与STM32F769NI这可主控芯片融合。
本章介绍STM32CubeMX的相关配置,实现使用STM32CubeMX建立基于STM32F769I-DISCO的工程。
1)选择Graphic Choice:

2)选择Graphic Choice对应参数
显示分辨率:800x480;
显示接口:DSI Command;
帧缓冲格式:24bpp-RGB888;
GFX RAM:External SDRAM32-Bit
GFX FLASH: External QuadSPI DDR FCPU/3
3)选择产品系列、产品线、封装
系列:SIM32F7
产品线:STM32F7x9
封装:TFBGA216
4)在MCU List中选择STM32F769NI
选择芯片后,点击上方的"Start Project"开始工程,在等待系统初始化后进入后边的步骤
5)在Pinout\SYS中配置Debug方式:
Debug:配置Serial Wire,分别接PA13、PA14
6)在Pinout\RTC中配置时钟源:激活RTC时钟源
7)在Pinout\RCC中配置HSE、LSE:

参考原理图,HSE:配置外部晶振;LSE:配置外部晶振。
8)在Clock Configuration配置系统时钟
时钟树上分别选择HSE、LSE,在HCLK处输入216MHz(最大频率)

9)配置LCD-TFT控制器、DSI主机及对应时钟树
LTDC显示模式配置最高的RTB888–DSI模式。根据原理图所示DSIHOST模式选择带TEPin的适配器模式:

并设置DSI_RESET所占用的PJ15

DSI的时钟树频率:TFT的最大频率值为62.5MHz。

LCD=TFT时钟树频率:计算方式 DSI通道速率*通道数/位每像素,
500Mbs*2/24=41.6666,约等于41.7MHz。
10)配置GUI所需的扩展内存(FMC方式,STemWin需要)

根据SDRAM选型和原图引脚配置,配置FMC的相关参数为如下:
SDCKE0+SDNE0(SDCKE1+SDNE1被其他功能占用,这里只能选KE0、NE0);
4M = 12bit 地址线;
BA0、BA1 均连接到SDRAM上,共4 *BANKS
32bits 数据位宽寻址;
启用32位访问方式。

11)配置GRAPHICS
第三方插件STemWin要用到CRC,先使能CRC;
使能STemWin,并选择显示接口方式LTDC-DSIHOST
12)工程小结及项目预览
完成以上配置后,一个基本图形环境搭建完成,TFBGA216引脚占用图如下,还是有很大的功能扩展空间;

功能参数配置,只选用了最基础的LTDC、DSI-Host、FMC、GPIO、NVIC功能,配置界面如下图:

经过简单的配置后,几乎不修改代码即可生成STemWin开发环境,以下为Hello World验证图,要到下图的效果还需要在STM32CubeMX上配置一些TFT屏幕控制器、DIS、内存、STemWin等设备相关参数。

原文作者是STM32中文社区用户:wolfgang2015
转自:STM32单片机











前言
在这篇文章中,我将介绍如何从零开始建立一个以太网工程。
ST 推出的 Nucleo-144 板子上集成了以太网接口,所以在本文中,将以 STM32F746-Nucelo 板为例,通过CubeMXv4.18 来新建一个 TCPEchoserver 的程序。
用 CubeMX 建立基于 STM32F746-Nucleo 的工程
用 CubeMX 进行初始化配置
这回我们直接选择 STM32F746-Nucleo 板上对应的芯片 STM32F746ZGT6U,而不是选择 STM32F746-Nucleo 板。
1. 新建一个 Project,在向导中选择 STM32F746ZGT6U。

这个时候我们看到的还是一个空的工程。如下图:

2.外设使能,引脚配置
2.1 以太网外设引脚配置
Nucleo-144 板上用的 PHY LAN8742A,RMII 接口。在 Cubemx 中使能 ETH 外设,选择 RMII 接口。Cubemx 会自动配置对应的以太网接口。如下图:

STM32 的很多引脚都有复用功能,同一个功能也可以 remap 到不同的引脚。所以这里要记得将 CubeMX 自动配置的引脚和实际电路中使用的引脚进行对比,保证是一致的。
从 UM1974 中可以找到 Nucleo-144 板上以太网引脚分配表。对比这张表格和 CubeMX 的默认配置,会发现 PB11,PB12 引脚在 STM32F746-Nucleo 板中没有用做以太网的接口,而是用作其他用途了。
STM32F746-Nucleo 上的引脚分配:

CubeMX 的默认分配:

在 Cubemx 中修改引脚配置:
修改方法见下图,用同样的方法配置 PG11 和 PG13。配置 PG11 和 PG13 后,对应 PB11 和 PB12 会自动清除之前的配置,以免冲突。

到现在位置,已经将所有的 GPIO 口都配置好了。
在 Configuration 页面中,还可以看到所有配置的 GPIO。并可以做进一步的配置,这里就先用默认的设置。

2.2 使能 LwIP 协议栈
在这个工程内,我们会用到 LwIP 协议栈,所以还需要在这一页的 Middlewares 部分将 LWIP 勾选上。之后就可以在Configuration 页面对 LWIP 协议栈进行配置了。

3.时钟配置
接下来进行时钟配置。CubeMX 默认系统时钟 16MHz,但以太网外设需要至少 25MHz 的系统时钟,所以这里会看到 Clock Configuration 页面显示"X"
打开 Clock Configuration 页面会自动跳出一个提示框,可以选择让 CubeMX 来帮你自动调整时钟配置,也可以自己手动进行调整。这里,我选择让 CubeMX 自动配置,CubeMX 会自动将时钟配成 216MHz。

4. 配置以太网参数

在 Parameter Settings 页面,可以配置 MAC 地址,PHY 的地址,是否进行自动协商等。
这里,我们设置了 MAC 地址为本地地址 02 :00 :0 :00 :00 :00。LAN8742a 的 PHY 地址由上电时 PHYAD0 的状态决定。根据STM32F746-Nucleo 板的原理图,设置 PHY 地址为 0。

接收数据的模式有轮询和中断两种方式,中断方式需要和操作系统一起使用,这里我们没有使用任何操作系统,所以在 RX Mode 这一项只能选择 Polling Mode。
最后一项是”TX IP Header Checksum Computation”,STM32 的 MAC 控制器可以在发送数据时自动添加 IP 数据报的 checksum,如果需要这项功能,就将这一项设置为“By hardware”
在 Advanced Parameters 页,可以根据所用的 PHY 修改寄存器的地址和一些 MASK 的设置。因为 STM32F746 的两款开发板上用的都是 PHY LAN8742A,所以 CubeMX 中默认的配置是以 LAN8742A 为例进行设置的。所以这里,我们不需要做任何修改就可以直接用。但如果是其他的 PHY,可以在 PHY 这一项选择“user PHY”,然后根据所用 PHY 的数据手册,配置下面的参数,对于部分无法通过 CubeMX 进行配置的参数,需要手动的修改代码。将有冲突的地方删除,或者添加某个功能。
Advanced Parameters 页分为三个部分:
• External PHY Configuration 。复位延时,读/写超时的参数设置
• Common :External PHY Configuration。PHY 的基础寄存器配置,这部分寄存器对于大部分 PHY 都是相同或类似的。
• Extended :External PHY Configuration。 PHY 的扩展寄存器配置,这部分对于每个 PHY 都是不一样的。如果是使用非 CubeMX 默认的 PHY,这部分内容需要特别注意。

4. 修改 LWIP 的参数
配置好以太网的参数后,点击 OK,回到 CubeMX 的配置界面。选择 LWIP 继续进行参数配置。

首先是 GeneralSettings 页面,在这里我们可以看到 LWIP 的版本号。配置 IP 地址信息,可以选择通过 DHCP 的方式动态分配 IP,也可以分配一个静态的 IP 地址。这里,我们选择配置静态的 IP 地址 192.168.0.10,子网掩码 255.255.255.0,网关192.168.0.1。ICMP 协议打开,因为我们用的是 TCP 协议,所以把 UDP 协议关掉。
不用担心不知道每项参数是做什么用的,选择每一项参数后都会在窗口的底部显示该项参数的解释

在 Key Options 这一页里,有更多的参数可以配置。关于接收/发送内存的配置也是在这里。选择右上方的“Show Advanced Parameters”后,还有更多的参数配置项。这里,我们也可以不做修改,使用默认值。CubeMX 中每个参数项的名称和代码中的名称相同,这样也方便了在代码中进行查找。

到此为止,我们在 CubeMX 中需要做的配置就全部完成了。选择 Project——>Generate Code,生成初始的工程。

添加用户代码
用 IAR 打开前面已经生成好的工程。我们还需要两步就可以完成一个简单的 TCP EchoServer 程序了。
1.新建 tcp_echoserver.c 文件,在 tcp_echoserver.c 里要做下面这几件事情:
1)新建一个 tcp_echoserver_pcb(调用 tcp_new 函数);
2)将新建的 tcp_echoserver_pcb 与要监听的端口绑定(调用 tcp_bind 函数)
3)转成监听状态(调用 tcp_listen 函数)
4)注册回调函数 tcp_echoserver_accept,当有新连接建立后会调用该函数(调用 tcp_accept 函数)
5)注册回调函数 tcp_echoserver_recv,当该连接接收到数据后会调用该函数(调用 tcp_recv 函数)
6)完成 tcp_echoserver_recv 函数,在该函数内,将收到的数据再发出去。
需要注意,本文的目的是示例如何用 CubeMX 建立一个简单的 TCP EchoServer 程序,所以考虑的都是最基本简单的情况。
比如,在回发数据部分,我们假设 Client 发来的数据都在一个 Pbuf 的大小以内。
完成 tcp_echoserver.c 后,将其加入到工程项目中。
#include "stats.h" #include "tcp.h" void tcp_echoserver_init(void); static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb,err_t err); static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p,err_t err); static struct tcp_pcb *tcp_echoserver_pcb; void tcp_echoserver_init(void) { err_t err; tcp_echoserver_pcb = tcp_new(); if(tcp_echoserver_pcb !=NULL) { err = tcp_bind(tcp_echoserver_pcb,IP_ADDR_ANY,7); if(err == ERR_OK) { tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb); tcp_accept(tcp_echoserver_pcb,tcp_echoserver_accept); } else { memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb); } } } static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb,err_t err) { /* initialize lwip tcp_recv callback function for newpcb */ tcp_recv(newpcb, tcp_echoserver_recv); return ERR_OK; } static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p,err_t err) { tcp_write(tpcb,p->payload,p->len,1); pbuf_free(p); return ERR_OK; }
2. 在 main 函数中添加 tcp_echoserver_init(),在 while(1)中添加 MX_LWIP_Process()查询接收数据。记得要将代码加在/*USER CODE BEGIN*/和/*USER CODE END*/之间,这样才不会在下次用 CubeMX 生成代码时被覆盖掉。
extern void tcp_echoserver_init(void); int main(void) { MX_LWIP_Init(); /* USER CODE BEGIN 2 */ tcp_echoserver_init(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ MX_LWIP_Process(); } /* USER CODE END 3 */ }
一个简单的 TCP Echoserver 程序就完成了。
测试结果
我们来看一看 ping 测试和 TCP 测试工具的结果
1. 通过电脑(192.168.0.11)ping STM32F746-Nucleo 板(192.168.0.10)

2.通过 TCP 测试工具模拟客户端,向 STM32F746-Nucleo 板发一串数据。

测试结果说明我们刚刚建立的 TCP EchoServer 程序已经能正常工作了。
来源: eefocus


















页面
