实验目的
- 理解MCU上电启动过程;
- 掌握使用Cube库来编写STM32裸机程序的方法;
- 掌握使用Cube库来编写GPIO和UART程序的方法;
- 掌握使用Cube库来编写中断响应程序的方法;
- 理解前后台程序模式;
- 掌握在STM32F103上编写裸机程序并下载运行的方法。
实验器材
硬件
- STM32F103核心板板一块;
- microUSB线一根(供电);
- STLink板或USB串口板一块。
软件
- 交叉编译软件。
实验步骤
一、连接示意图
1、面包板:
在面包板上,标有A、B、C、D、E字母旁边的每竖列上有五个方孔,被其内部的一条金属簧片所接通,但竖列与竖列方孔之间是相互绝缘的。同理,标有F、G、H、I、J每竖列的五个方孔也是相通的。
面包板上下两个横行X和Y,各有二十个方孔也是相通的。
对于10组的结构,左边3组内部电气连通,中间4组内部电气连通,右边3组内部电气连通,但左边3组、中间4组以及右边3组之间是不连通的。
对于11组的结构,左边4组内部电气连通,中间3组内部电气连通,右边4组内部电气连通,但左边4组、中间3组以及右边4组之间是不连通的。若使用的时候需要连通,必须在两者之间跨接导线。
2、转usb与stm32的连接
USB | STM32 |
---|---|
3.3V | 3.3V |
GND | GND |
TXD | A10 |
RXD | A9 |
3、GND、PA9~PA12 即下图框出的引脚,其中 PA9、 PA10 连接 usb,GND、PA11 和 PA12 连接面包板
二、首先配置环境。安装STM32CubeMX等等一系列
- STM32CUBEMX
- KEIL V5(安装教程)
- 选择驱动包下载 STM32CUBEF1
- keil中的stm32设备包
密码:ftuq
三、UART图
- 选择正确的板子型号(STM32F103C8Tx)
- 在右侧芯片设置中,定义引脚,将PA12、PA11接按钮,PA10、PA9分别定为USART1_TX、USART1_RX
- 在左侧的配置中,将USART1的模式定为Half-Duplex。
- 在project setting中填写项目名字,选择MDK-ARM V5。
- 设置keil生成hex文件才能导入flymcu
四、编写Cube程序,配置UART0为9600,8n1,上电后向串口输出“Hello”,在PC上通过串口软件观察结果
1.打开main.c可以看到串口的函数已经存在。按照要求设定串口的波特率为9600,数据宽度8,停止位为1,无检验位,然后用HAL_UART_Init函数初始化。
void UART0_Init(UART_HandleTypeDef* UartHandle){
UartHandle->Instance = USART1;
UartHandle->Init.BaudRate = 9600;
UartHandle->Init.WordLength = UART_WORDLENGTH_8B;
UartHandle->Init.StopBits = UART_STOPBITS_1;
UartHandle->Init.Parity = UART_PARITY_NONE;
UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle->Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(UartHandle);
}
- 重写pirntf函数,这样可以使用printf来让串口输出‘hello’
/* USER CODE END 0 */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
在main函数中写入printf语句printf(“Hello”);
打开flymcu,进行烧程序
输出hello
2.编写Cube程序,配置PA11和PA12为内部上拉到输入模式,在main()函数循环检测PA11按钮按下,并在按钮按下时 在串口输出“Pressed”;
在main中修改GPIO的初始化函数如下,设定PA11的方式为上拉输入,PA12为下降沿中断触发,初始化两个GPIO。
在main函数中增加对PA11的按下的检测,按下时输出press和按下的次数。增加防抖动Delay防止输出很多。
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// printf("hello\r\n");
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11)==0){
HAL_Delay(100);//anti-jitter
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11)==0){
count++;
printf("press:%d\r\n",count);
}
}
}
- 重新烧录程序后,打开putty,按下按钮,可以看到输出
3. 编写Cube程序,配置PA12下降沿触发中断,程序中设置两个全局变量,一个为计数器,一个为标识。当中断触发 时,计数器加1,并设置标识。在主循环中判断标识,如果标识置位则清除标识并通过串口输出计数值
- 配置PA12为下降边沿触发,在GPIO的初始化函数中如5中所配置
- 设置中断的优先级,enable中断向量 表处理,在main函数中添加以下代码
- 出现中断的时候,STM32会调用EXTI15_10_IRQHandler这个中断服务程序进行处理,在stm32f1xx_it.c中调用HAL_GPIO_EXTI_IRQHandler函数。由于上述函数会判断中断标志位并且调用HAL_GPIO_EXTI_Callback函数,因此我们将中断处理程序放在了HAL_GPIO_EXTI_Callback函数中进行实现。
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}
- 在main.c中定影了两个全局变量flag和counter。main的主循环中判断标志flag,如果其为1,则输出counter值,并且消除标志位
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// printf("hello\r\n");
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11)==0){
HAL_Delay(100);//anti-jitter
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11)==0){
count++;
printf("press:%d\r\n",count);
}
}
if(flag==1){
printf("press12 %d\r\n",counter);
flag=0;
}
}
- 重新烧录程序,可以得到如下结果