STM32F103寄存器方式点亮LED流水灯

本文详细介绍了使用STM32F103C8T6通过串口烧录程序的方法,包括硬件准备、软件配置、编程思想、编译设置、软件调试和硬件调试过程。在编程中,通过直接操作GPIO寄存器实现LED灯的控制,并强调了`volatile`关键字在延时函数中的重要性。最后,文章讨论了寄存器方式与库函数开发的优缺点。
摘要由CSDN通过智能技术生成

一. 硬软件准备

1. 硬件

此次实验使用串口下载的方式。

  • STM32最小系统核心板(STM32F103C8T6)

  • USB转TTL模块 CH340

  • 面包板

  • LED灯

  • 若干杜邦线(公对公、公对母、母对母)

2. 软件

  • keil5 MDK
  • mcuisp 烧录软件
  • CH340驱动

二. 编程思想

1. 创建工程

打开Keil,新建工程。选择设备 STM32F10C8

image-20211022124920119

使用寄存器方式开发无需在线添加库文件,直接跳过。

image-20211022125033256

2. 添加文件

在新建工程目录下添加三个文件

  1. startup_stm32f10x_md.s

启动文件,系统上电后第一个运行的程序,由汇编编写。从固件库里面拷贝而来,由官方提供。

官方固件库下载:STSW-STM32054 - STM32F10x标准外设库 - STMicroelectronics

文件目录:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\start up\arm\startup_stm32f10x_hd.s

  1. stm32f10x.h

用户手动新建,用于存放寄存器映射的代码,暂时为空

  1. main.c

用户手动新建,用于存放 main 函数,暂时为空

3. 编写代码

此次实验选用 GPIOA、GPIOB、GPIOC 三个端口

  • 编写 stm32f10x.h
#ifndef _STM32F10X_H_
#define _STM32F10X_H_

 /*片上外设基地址 */
#define PERIPH_BASE ((unsigned int)0x40000000)
/*总线基地址,GPIO 都挂载到 APB2 上 */
#define APB1PERIPH_BASE PERIPH_BASE               //APB1总线基地址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)   //APB2总线基地址
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)    //AHB 总线基地址

/*GPIOA 外设基地址*/
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
/* GPIOA 寄存器地址,强制转换成指针 */
#define GPIOA_CRL *(unsigned int*)(GPIOA_BASE+0x00) //端口配置低寄存器
#define GPIOA_ODR *(unsigned int*)(GPIOA_BASE+0x0C) //端口输出数据寄存器
	
/*GPIOB 外设基地址*/
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
/* GPIOB 寄存器地址,强制转换成指针 */
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE+0x00) //端口配置低寄存器
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0C) //端口输出数据寄存器
	
/*GPIOC 外设基地址*/
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
/* GPIOC 寄存器地址,强制转换成指针 */
#define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04) //端口配置高寄存器
#define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C) //端口输出数据寄存器

/*RCC 外设基地址*/
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
/*RCC 的 AHB1 时钟使能寄存器地址,强制转换成指针*/
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)
	
#endif
  • 编写main.c

选用 A0、B0、C13端口

#include "stm32f10x.h"


void SystemInit(void);
void delay(volatile unsigned int nCount);   // volatile 必须要

int main(void)
{
	// 开启端口时钟
	RCC_APB2ENR |= (1<<2); //GPIOA
	RCC_APB2ENR |= (1<<3); //GPIOB
	RCC_APB2ENR |= (1<<4); //GPIOC
	
	//清空控制 PA0 的端口位
	GPIOA_CRL &= ~(unsigned int)( 0x0F<< (4*0));
	//清空控制 PB0 的端口位
	GPIOB_CRL &= ~(unsigned int)( 0x0F<< (4*0));
	//清空控制 PC13 的端口位
	GPIOC_CRH &= ~(unsigned int)( 0x0F<< (4*5));
	// 配置 PA0 为通用推挽输出,速度为 10M
	GPIOA_CRL |= (1<<4*0);
	// 配置 PB0 为通用推挽输出,速度为 10M
	GPIOB_CRL |= (1<<4*0);
	// 配置 PC13 为通用推挽输出,速度为 10M
	GPIOC_CRH |= (1<<4*5);
	
	
	while (1)
	{

		GPIOA_BSRR=0x00000001;   //置1
		delay(0xFFFFF);
		GPIOA_BRR=0x00000001;    //清0
		
		GPIOB_BSRR=0x00000001;
		delay(0xFFFFF);
		GPIOB_BRR=0x00000001;
		
		GPIOC_BSRR=0x00008000;
		delay(0xFFFFF);
		GPIOC_BRR=0x00008000;
	}
}

// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
}
//延时函数
void delay(volatile unsigned int nCount)  // volatile 必须要
{
	for (; nCount != 0; nCount--);
}

延时函数中,volatile 必须加上,否则无效

volatile 的作用就是指示编译器不要因优化而省略此指令,必须每次都直接读写其值。

4. 编译设置

  1. 点击方框内的魔法棒

路径有中文的这种习惯一定要改。这里有中文是因为课程实验原因,用中文方便分类。

image-20211022131957993

  1. 点击Output,勾选 hex文件。此文件就是用来烧进芯片内的。

image-20211022132236244

  1. 勾选Use Simulator 使用软件调试。更改 Dialog DLL 以及 Parameter

Dialog DLL 设置为 DARMSTM.DLL 和 TARMSTM.DLL

Parameter 都设置为 -pSTM32F103C8

image-20211022132414595

现在就可以编译了

编译无误

image-20211022133105345

三. 软件调试

  1. 点击方框内,开始调试

image-20211022133307434

  1. 打开 logic analyzer窗口,进行波形分析

image-20211022133413362

  1. 点击 Setup 选项

image-20211022133604285

  1. 点击方框 新建

我使用了A0、B0、C13 端口

新建三个并分别填写三个端口:GPIOA_ODR.0 GPIOB_ODR.0 GPIOC_ODR.13

image-20211022133812329

  1. 类型都设置为比特流。并可以选择设置各个波形颜色。

设置完就可以点击下方 Close 退出了

image-20211022134253137

  1. 点击方框内 run开始

image-20211022134624387

  1. 查看波形

image-20211024120621633

四. 硬件调试

  1. 安装 CH340 驱动

蓝奏云链接:https://diyugreat.lanzouw.com/iYEvFvmh1xe 密码:3oib

若安装失败,自行去寻找答案

  1. 下载mcuisp烧录软件。无需安装,直接使用。

蓝奏云链接:https://diyugreat.lanzouw.com/ita3nvmh1yf 密码:e1d2

  1. stm32核心板与usb转TTL模块的接线

image-20211022140034284

  1. boot0接1,boot1接0。因为要用串口烧录程序

image-20211024121236637

  1. 总体接线

image-20211024121602172

五. 最终效果

如果延时函数没有加上 volatile 那么效果就是如图所示。

image-20211024121700227

是不是看到全亮,对,你没看错。这是我用别人核心板烧录的程序,因为我自己的核心板后面被我玩坏了,进入锁死状态了,因此用了别人的。最终的效果就是如此,三个灯常亮。与调试的波形的完全不同。

加上 volatile,成功

六. 总结

寄存器方式操控,容易出问题,且出了问题不好找,寄存器方式还是少用吧,还是使用标准库或者抽象库开发更好。

抽象库开发可以查看我的另一篇博客:
STM32F103 + STM32CubeMX实现流水灯闪烁_diyu-CSDN博客

七. 参考资料

  • 《零死角玩转STM32—F103指南者》pdf版

  • c8t6 datasheet.pdf(芯片手册)

  • STM32F10x参考手册.pdf(中文版)

  • STM32固件库使用手册的中文翻译版.pdf

资料蓝奏云链接:

https://diyugreat.lanzouw.com/b026lt8na 密码:7exb

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值