本帖最后由 cruelfox 于 2017-3-29 22:21 编辑
Nucleo开发板连上电脑之后,系统会提示检测到新硬件。如果以前没有安装过 ST-Link 的驱动,需要下载驱动软件安装。如果是使用Keil, IAR之类的开发环境,安装时可能已经顺带安装了ST-Link的驱动,自动安装就可以了。安装ST的“ST toolset"工具集(给STM8开发的),或者 STM32 ST-Link Utility 软件也是会安装上驱动程序的。 如果安装驱动成功,在设备管理器里可以看到添加了3个设备,以本人的WinXP为例:
这三个设备分别是 ST-Link 调试器、虚拟串口和MBED虚拟磁盘。最重要的是 ST-Link 调试器,SWD调试全靠它。MBED虚拟盘据说可以用来把HEX文件拖进去就实现烧写,我没有试过。
CubeMX 是 ST 官方的STM32软件工程生成器,可以直接在 ST 网站下载,最新的版本自然是支持STM32F722的。CubeMX 运行需要 Java 的RunTime (JRE),如果系统没有带的话需要先装一下,才能成功安装 CubeMX. CubeMX 和 CubeF7 软件包是搭配使用的(开发其它系列需要类似的 CubeF4, CubeF0 ... 等),它会从CubeF7中提取程序文件。CubeF7 包含了一大堆的程序库,还有现成的例子工程,它的软件是基于 HAL 库的,即“硬件抽象层",给不同MCU提供一套统一的软件接口。有了 CubeMX 这个图形化的配置工具以后软件编写确实上手容易,不用一边查手册看有哪些硬件模块可以用,不用查每个引脚的功能分配,降低了使用门槛。
启动 CubeMx 主界面
选择"New Project"新建一个工程,然后将出现一个对话框,选择MCU型号。
找到Nucleo-F722ZE上的对应型号:STM32F722ZETx,然后确定。
现在就来到工程的主界面了,首先是片上外设的启用。在窗口左边的树状选择区里面可以设置哪些设备要用到,以及作初始配置的设定。右边显示MCU封装外形的区域将显示引脚的使用状态。
查阅手册发现,在Nucleo-144开发板上,USB虚拟串口是连接到 MCU 的 USART3 的。所以在这个demo中为了从USB虚拟串口打印输出信息,要把USART3启用,并选择对应的引脚。
在 CubeMX 中开启 USART3, 选择异步模式,就是最基本的串行口。在窗口的右边,相关的两个引脚变成绿色,出现文字说明。鼠标滚轮可以缩放显示,按下左键可以拖动显示区域。
因为 STM32 的引脚复用功能通常不只一个,而且一个设备的某个功能可能可以映射到多个引脚上(这样电路板设计方便,利用效率提高),所以 CubeMX 默认给出的复用功能引脚分配未必是唯一的。在这里,USART3的TX, RX默认给出是 PB10, PB11. 但是Nucleo板子上连接的是PD8和PD9,需要手动改一下。有一个办法可以看某个功能的引脚是否还有其它选择:按Ctrl键,再用鼠标点击绿色的引脚。如果这个复用功能可以映射到其它引脚,则那些引脚会变成浅蓝色显示,如下图。
如上面,CubeMX 提示: PC11和PD9都可以用作为 USART3_RX. 这里需要选择用 PD9, 在PD9那个地方,点以下鼠标,然后选择 USART3_RX的功能。
同样的操作,把PD8选为 USART3_TX. 这时候 USART3 的引脚就配置好了。
注意,如果选择了引脚的复用功能,但是对应的设备没有启用的话,这个引脚不会显示为绿色,而是深黄色,表示配置有问题。如果是配置为普通输入或者输出的 GPIO 口,则立即就给分配了,显示为绿色。Nucleo-144板子上有三个用户LED,分别受PB0, PB7, PB14控制,所以把这三个引脚都设成 "GPIO_Output". 此外,因为可用的引脚已被全部占用而影响设备使用时,窗口左边部分受到冲突的设备会显示出黄色或红色的禁止提示,如下图。
本次Demo还需要用到的设备是RNG(随机数发生器)和定时器,在设备选择中把 RNG 和 RTC 开启,另外把调试口也打开,使用SWD. 在Nucleo-F722板子上默认没有焊接HSE晶振,而是从ST-Link MCO输出了一个8MHz的外部时钟过来。本Demo还用到RTC的晶振,所以在硬件设备 RCC 部分把 HSE 和 LSE 都开启,HSE要设为 BYPASS 模式。
下面就到了配置各种时钟频率的时候了。在主窗口上的第二个页面是“Clock Configuration"即时钟配置,这是一个强大的工具。不仅把复杂的寄存器设置代劳了,设置结果一目了然,依赖关系也显示清晰,而且可以根据需要的频率推算参数,不合理的设置给出警告。在图的最左边,是外部输入时钟包括晶振频率设定。注意必须在RCC里面启用了外部时钟输入,这些输入框才会变成蓝色。
本次Demo使用PLL产生60MHz的主时钟,和48MHz的时钟给RNG. 手动设置PLL的各种系数是可以的,不过 CubeMX 可以自动推算,只需要在蓝色框里填写,然后确定就是了。(如果输入的频率找不到合适的解,CubeMX 会忙活半天然后报错)
剩下的,APB1和APB2都配置成30MHz, 这个随意。 接下来再做一些软件库的详细配置。这部分大都用默认值就可以了,有需要的就改一下。
比如,USART3的字长改为8-bit更符合习惯。
配置完成就可以导出工程,创建出模板代码了。选择主菜单"Project"--->"Generate Code",出现设置对话框
主要是选择使用的开发工具,工程目录的位置,还有 CubeF7 所在的目录。填好点击确认就搞定了。
然后启动集成开发环境,比如MDK,从菜单上选择打开工程,找到刚才导出的目录。以MDK为例,打开成功后在左边浏览区可以看到创建的模板.c文件(在代码树中Src子目录下面)。CubeMX只是给搭了个框架,把初始化工作完成了,main()函数也有了,内容当然该自己添加啦。
添加demo代码之后的主函数如下
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* Enable I-Cache-------------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache-------------------------------------------------------------*/
SCB_EnableDCache();
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_RNG_Init();
MX_RTC_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_GPIO_TogglePin(GPIOB, 1<<14);
while (1)
{
static RTC_TimeTypeDef tm;
static int count=0;
RTC_DateTypeDef date;
char str[128];
uint32_t x;
RTC_TimeTypeDef tm1;
HAL_RTC_GetTime(&hrtc, &tm1, RTC_FORMAT_BCD);
HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BCD);
if(tm1.Seconds != tm.Seconds)
{
memcpy(&tm, &tm1, sizeof(RTC_TimeTypeDef));
HAL_GPIO_TogglePin(GPIOB, 1<<0);
HAL_RNG_GenerateRandomNumber(&hrng, &x);
itoa(x,str);
HAL_UART_Transmit(&huart3, "\nRNG ", 5, 1000);
HAL_UART_Transmit(&huart3, str, strlen(str), 1000);
HAL_UART_Transmit(&huart3, " uptime ", 8, 1000);
str[0]=(tm.Hours>>4)+'0';
str[1]=(tm.Hours&15)+'0';
str[2]=':';
str[3]=(tm.Minutes>>4)+'0';
str[4]=(tm.Minutes&15)+'0';
str[5]=':';
str[6]=(tm.Seconds>>4)+'0';
str[7]=(tm.Seconds&15)+'0';
HAL_UART_Transmit(&huart3, str, 8, 1000);
itoa(count, str);
HAL_UART_Transmit(&huart3, " c=", 3, 1000);
HAL_UART_Transmit(&huart3, str, strlen(str), 1000);
count=0;
}
__WFI();
count++;
/* USER CODE END WHILE */
}
/* USER CODE END 3 */
}
上面的demo程序中,循环读取RTC的时间,若发现秒数和上一次不同(意味着时间过了1秒了),就读一次RNG的数,从串口显示输出。接着显示RTC的时间,小时:分:秒(就是系统运行的时间了,我发现只要不掉电,板子复位了RTC的时间也不复位)。再打印一秒种的间隔内CPU从Sleep状态被中断唤醒的次数。串口打印结果之后使用WFI指令进行休眠。 绿色的LED以亮1秒灭1秒的间歇交替。
写完程序后编译全部文件(当然写错了要排查),改正错误后可以看到链接生成的程序大小。因为我没有安装STM32F7的pack, 不能用keil的下载和调试功能,需要生成HEX文件,然后用ST的工具来烧写。
最后一步:烧写Flash测试结果。启动ST-Link utility, 先Connect连上开发板,然后选"Program & Verify", 选择生成的HEX文件,出现对话框。
点"Start"按钮之后就会烧写编译生成的HEX. MCU复位,运行新的程序。从PC上用串口终端可以看到程序输出的内容:
我发现了一秒种内有大约1000次中断唤醒了CPU. 考虑串口输出占用的时间,这个数应该就是1000. 我没有写代码开启什么中断,这应该是HAL库自己使用的,估计是1ms的系统定时器。HAL隐藏了太多东西,我就不去研究它的代码了。
|
|