(请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365)
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)
(YIE001和YIE002都是我平时为了嵌入式编程所做的开发板,特征在于:方便回家或出差携带、U盘大小。《UEFI编程实践》也使用它们,作为PCIE和USB程序的实验硬件。)
在YIE002上准备了5个LED灯,除去用来显示电源的灯,其余4个都可以用来做实验。这一篇中,我准备用这4个灯实现跑马灯的效果。
1 STM32的GPIO
STM32单片机的每个IO口可以自由编程,不过要求是按32位字进行访问。包括输入和输出,它们可以配置为8种模式。在输入时,包括模拟输入、浮空输入、下拉输入和上拉输入;通用输出时,包括推挽式和开漏式;复用功能输出时,也包括推挽式和开漏式。
为控制IO端口,STM32提供了7个寄存器来进行控制。对于这些寄存器的用法,不需要深入了解也可以编程。有兴趣的话,它们的具体用法,可以查看《STM32中文参考手册_V10.pdf》。
YIE002-STM32型开发板使用的是F103C8T6,其封装类型为LQFP48。当前我使用的版本,准备了5个LED灯,除了其中一个用来表示电源接通,其他4个都可以通过GPIO来控制。
STM32对于GPIO的编程,主要包括使能相应的时钟、设置相应的工作模式、置位或清位。在Cube Library中,主要包含以下可使用的API(参考UM1850《Description of STM32F1 HAL and low-layer drivers》):
1) 初始化函数
void HAL_GPIO_Init (GPIO_TypeDef * GPIOx, GPIO_InitTypeDef * GPIO_Init) ;
void HAL_GPIO_DeInit (GPIO_TypeDef * GPIOx, uint32_t GPIO_Pin) ;
2) IO操作函数
GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
HAL_StatusTypeDef HAL_GPIO_LockPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_IRQHandler (uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin);
对于GPIO时钟的配置,一般在CubeMx图形化编程时,会自动生成代码。因此,对GPIO的操作,主要使用读、写、变换(也即上述的HAL_GPIO_ReadPin、HAL_GPIO_WritePin、HAL_GPIO_TogglePin)就可以了。
下面在YIE002-STM32型上,实现跑马灯的代码。
2 YIE002-STM32型编程
实际上,主要的工作是使用CubeMX设定各种参数,然后自动生成代码。需要手动编写的代码没几行,相对以前使用Legacy Library的方法,是简便得多了。
2.1 建立工程,配置时钟树
打开STM32CubeMx,选择芯片STM32F103C8Tx,新建工程(目前使用的版本是6.2.1)。
在Pinout&Configuration栏的System Core下,打开RCC的配置。由于YIE002中使用了无源外部晶振,可以在High Speed Clock(HSE)中选择“Crystal/Ceramic Resonator”,Low Speed Clock(LSE)保持Disable的状态即可。
对于时钟树,选择Clock Configuration栏,配置图如下:
图1 时钟树的配置
注意标红的部分,是根据开发板的实际情况进行修改的。STM32103C8T6最大的频率为72MHZ,其他所有外设的时钟的来源都是SYSCLK,经过分频器分频后给各模块使用。
2.2 GPIO配置
YIE002上控制LED灯的4个GPIO分别为PB12、PB13、PB14和PB15。直接在Pinout view视图上,将这4个脚设置为输出就可以了。配置后的结果如图2所示。
图2 GPIO配置
2.3 打开调试
CubeMX有个容易忽视的问题,会导致程序下载后,再次下载的时候无法找到ST-Link的硬件(我是用ST-Link下载的,其他下载设备类似)。
其核心的原因在于,CubeMX管脚配置中的SYS选项,默认的是 No Debug,这个选项会造成板子debug(以及下载)失效。
解决方法也很简单,把Debug打开就可以了。
在Pinout&Configuration栏的System Core下,打开SYS的配置。在其配置界面中,Debug有五种选项:“No Debug”、“Serial Wire”、“JTAG(4 pins)”、“JTAG(5 pins)”和“Trace Asynchronous Sw”。我使用的是ST-Link,改为“Serial Wire”即可。
2.4 生成代码
工程的选项和配置,可以在“Project Manager”栏下进行,本篇的配置信息如下:
图3 工程配置
图3中选择的编译器为MDK-ARM,这是我编程使用的Keil编译器,也可以根据自己的情况选择其他编译器。
需要提醒的是,为保证工程代码占用空间不要太大,最好对引用库文件进行设置。如图4所示。
图4 设置库文件
至此,所有配置设置完成。选择“GENERATE CODE”,生成需要的代码。
2.5 添加跑马灯代码
使用MDK-ARM打开工程,在main.c中的while循环中,添加如下语句:
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_12);
HAL_Delay(100);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_13);
HAL_Delay(100);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_14);
HAL_Delay(100);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_15);
HAL_Delay(100);
/* USER CODE BEGIN 3 */
就完成了跑马灯的程序了。
编译下载,即可看到实际效果了。
总体感觉,CubeMx还是比较好用的。让我回忆起很多年前学习Windows编程时,使用MFC写代码的日子。
当然,CubeMx主要是为了节省开发时间,将很多代码进行了封装。为了开发稳定而高效的代码,对其库函数的使用以及芯片本身的理解,这些功夫还是要下的。