STM32F103C8T6之用寄存器点亮LED流水灯

一、准备工作

1、什么是STM32芯片?

STM32,从字面上来理解,ST 是意法半导体,M 是 Microelectronics 的缩写,32 表示32 位,合起来理解,STM32 就是指 ST 公司开发的 32 位微控制器。在如今的 32 位控制器当中,STM32 可以说是最璀璨的新星,它受宠若娇,大受工程师和市场的青睐,无芯能出其右。

STM32 属于一个微控制器,自带了各种常用通信接口,比如 USART、I2C、SPI 等,可连接非常多的传感器,可以控制很多的设备。现实生活中,我们接触到的很多电器产品都有 STM32 的身影,比如智能手环,微型四轴飞行器,平衡车、移动 POST 机,智能电饭锅,3D 打印机等等。

STM32 有很多系列,可以满足市场的各种需求,从内核上分有 Cortex-M0、M3、M4和 M7 这几种,每个内核又大致分为主流、高性能和低功耗。

单纯从学习的角度出发,可以选择 F1和 F4,F1代表了基础型,基于 Cortex-M3内核,主频为 72MHZ,F4 代表了高性能,基于 Cortex-M4 内核,主频 180M。本文则选择的F1下的stm32f103c8t6。

2、GPIO相关的寄存器

首先需要知道的是,STM32中对于GPIO口的操作,无非就是操作下面的寄存器而已,所谓的标准库也好,HAL库也好,它们都只是对操作寄存器的过程进行了封装,目的是为了减轻你编程时的工作负担。因此对于寄存器的描述,你只要稍微了解一下,大概知道每个寄存器是干啥的,有哪些位,是如何配置的就行,除了一些你觉得需要留意的地方,其它的完全没有必要完全记住,用的时候知道在哪里查就行了。

两个32位的配置寄存器:GPIOx_CRL、GPIOx_CRH

两个32位数据寄存器:GPIOx_IDR、GPIOx_ODR

一个32位的置位/复位寄存器:GPIOx_BSRR

一个16位复位寄存器:GPIOx_BRR

一个32位锁定寄存器:GPIOx_LCKR

注:具体的寄存器描述可以参考《STM32F10x-中文参考手册》的GPIO章节的P113页。强烈建议先花几分钟先看一下这一部分的内容。

  • GPIO地址
    在这里插入图片描述

  • 时钟地址
    在这里插入图片描述

  • 初始化地址以及GPIO偏移量

在这里插入图片描述

二、GPIO输出的操作

  • A0

在这里插入图片描述

  • C15

在这里插入图片描述

  • B9

在这里插入图片描述
GPIO口有八种模式:

1.输入浮空
2.输入上拉
3.输入下拉
4.模拟输入
5.开漏输出
6.推挽式输出
7.推挽式复用功能
8.开漏复用功能

这里点亮LED灯使用推挽输出。

端口1-7为低,端口8-15为高。每个引脚由四个位控制。

1、初始化GPIO

以GPIOA和0号引脚(A0)为例,将其设置为推挽输出,并设置最大速度为10MHz,则将控制A0的四个位设置为0001。同理从上图可以得到另外两个的设置。
对于GPIOA的A0、GPIOC的C15、GPIOB的B9,初始化设置如下:

#define GPIOB_CRH (*(unsigned int *)0x40010C04)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)

// 配置 GPIO 口为推免输出
// GPIOB----最后四位为0001
GPIOB_CRH |= (1<<4);  // 最后一位变1
GPIOB_CRH &= ~(0xE<<0);  // 倒数2、3、4位变0
// GPIOC----前四位为0001
GPIOC_CRH |= (1<<28);  //  第四位变1
GPIOC_CRH &= ~(0xE0000000);  // 前三位变0
// GPIOA----最后四位为0001
GPIOA_CRL |= (1<<0);  // 最后一位变1
GPIOA_CRL &= ~(0xE<<0);  // 倒数2、3、4位变0

2、设置低电平

在这里插入图片描述
输出高电平则为1,低电平则为0。

对于GPIOB的B9、GPIOC的C15、GPIOA的A0,设置如下:

#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)

GPIOB_ODR &= ~(1<<9);  //最后一位变为0
GPIOC_ODR &= ~(1<<15); //倒数16位变为0
GPIOA_ODR &= ~(1<<0);  //最后一位变为

三、创建项目

1、新建项目

点击Project下的New uVision Project,并输入文件名LED:

在这里插入图片描述
选择芯片(这里我用的是STM32F103C8T6):
在这里插入图片描述
添加文件main.c
在这里插入图片描述
将启动文件从下载的代码包中粘贴到该工程目录下:
(下载地址:野火资料下载中心
在这里插入图片描述
在这里插入图片描述
将启动文件导入:
在这里插入图片描述
点击魔法棒设置生成HEX文件(后面烧录需要!):
在这里插入图片描述

2、编写代码

代码:


//--------------APB2使能时钟寄存器------------------------
#define RCC_AP2ENR	*((unsigned volatile int*)0x40021018)
	//----------------GPIOA配置寄存器 ------------------------
#define GPIOA_CRL	*((unsigned volatile int*)0x40010800)
#define	GPIOA_ORD	*((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 ------------------------
#define GPIOB_CRH	*((unsigned volatile int*)0x40010C04)
#define	GPIOB_ORD	*((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH	*((unsigned volatile int*)0x40011004)
#define	GPIOC_ORD	*((unsigned volatile int*)0x4001100C)
//-------------------简单的延时函数-----------------------
void SystemInit(void);
void Delay_ms(volatile  unsigned  int);
void A_LED_LIGHT(void);
void B_LED_LIGHT(void);
void C_LED_LIGHT(void);
void  Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}
void A_LED_LIGHT(){
	GPIOA_ORD=0x0<<0;		//PA0低电平
	GPIOB_ORD=0x1<<9;		//PB9高电平
	GPIOC_ORD=0x1<<15;		//PC15高电平
}
void B_LED_LIGHT(){
	GPIOA_ORD=0x1<<0;		//PA0高电平
	GPIOB_ORD=0x0<<9;		//PB9低电平
	GPIOC_ORD=0x1<<15;		//PC15高电平
}
void C_LED_LIGHT(){
	GPIOA_ORD=0x1<<0;		//PA0高电平
	GPIOB_ORD=0x1<<9;		//PB9高电平
	GPIOC_ORD=0x0<<15;		//PC15低电平	
}
//------------------------主函数--------------------------
int main()
{
	int j=100;
	RCC_AP2ENR|=1<<2;			//APB2-GPIOA外设时钟使能
	RCC_AP2ENR|=1<<3;			//APB2-GPIOB外设时钟使能	
	RCC_AP2ENR|=1<<4;			//APB2-GPIOC外设时钟使能
	//这两行代码可以合为 RCC_APB2ENR|=1<<3|1<<4;
	GPIOA_CRL&=0xFFFFFFF0;		//设置位 清零	
	GPIOA_CRL|=0x00000002;		//PA0推挽输出
	GPIOA_ORD|=1<<0;			//设置PA0初始灯为灭
	
	GPIOB_CRH&=0xFFFFFF0F;		//设置位 清零	
	GPIOB_CRH|=0x00000020;		//PB9推挽输出
	GPIOB_ORD|=1<<9;			//设置初始灯为灭
	
	GPIOC_CRH&=0x0FFFFFFF;		//设置位 清零
	GPIOC_CRH|=0x30000000;   	//PC15推挽输出
	GPIOC_ORD|=0x1<<15;			//设置初始灯为灭	
	while(j)
	{	
		A_LED_LIGHT();	
		Delay_ms(1000000);
		B_LED_LIGHT();
		Delay_ms(1000000);
		C_LED_LIGHT();
		Delay_ms(1000000);
	}
}




void SystemInit(){
	
}




将代码写到main.c文件中之后,build一下生成hex文件
在这里插入图片描述

四、连接电路

对于USB转TTL模块和STM32F103C8T6连接:

  • GND — GND
  • 3v3 — 3v3
  • TXD — A10
  • RXD — A9

在这里插入图片描述
在这里插入图片描述
连接到电脑,打开FlyMcu,上传HEX文件到STM32F103C8T6上:

在这里插入图片描述

  • 信号波形图
    在这里插入图片描述

  • 烧录到单片机后得到如下效果:

STM32F103C8T6用C语言实现LED流水灯点亮

五、汇编实现

代码:

Stack_Size EQU  0x00000400;????
	
                AREA    STACK, NOINIT, READWRITE, ALIGN=3 ;NOINIT: = NO Init,?????READWRITE : ??,???ALIGN =3 : 2^3 ??,?8?????
Stack_Mem       SPACE   Stack_Size
__initial_sp




                AREA    RESET, DATA, READONLY

__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                    
                    
                AREA    |.text|, CODE, READONLY
                    
                THUMB
                REQUIRE8
                PRESERVE8
                    
                ENTRY
Reset_Handler 
				bl LED_Init;bl:??????????????????,????(PC)?????LR???
MainLoop		BL LED_ON_B
                BL Delay
                BL LED_OFF_B
                BL Delay        
				BL LED_ON_C
                BL Delay
                BL LED_OFF_C
                BL Delay
				BL LED_ON_A
                BL Delay
                BL LED_OFF_A
                BL Delay

                
                B MainLoop;B:??????
LED_Init;LED???
                PUSH {R0,R1, LR};R0,R1,LR???????
                ;????
                LDR R0,=0x40021018;LDR???????????(??R0)?
                ORR R0,R0,#0x1c
                LDR R1,=0x40021018
                STR R0,[R1]
				
				
                ;???GPIOA_CRL
                LDR R0,=0x40010800
                BIC R0,R0,#0x0fffffff;BIC ???????,????
                LDR R1,=0x40010800
                STR R0,[R1]
				
                LDR R0,=0x40010800
                ORR R0,#0x00000001
                LDR R1,=0x40010800
                STR R0,[R1]
                ;?PA0?1
                MOV R0,#0x01
                LDR R1,=0x4001080C
                STR R0,[R1]
				
				
                ;???GPIOB_CRL
                LDR R0,=0x40010C04
                BIC R0,R0,#0xffffff0f;BIC ???????,????
                LDR R1,=0x40010C04
                STR R0,[R1]
				
                LDR R0,=0x40010C04
                ORR R0,#0x00000020
                LDR R1,=0x40010C04
                STR R0,[R1]
                ;?PB0?1
                MOV R0,#0x200
                LDR R1,=0x40010C0C
                STR R0,[R1]
				
				
				 ;???GPIOC
                LDR R0,=0x40011004
                BIC R0,R0,#0x0fffffff
                LDR R1,=0x40011004
                STR R0,[R1]
				
                LDR R0,=0x40011004
                ORR R0,#0x20000000
                LDR R1,=0x40011004
                STR R0,[R1]
                ;?PC15?1
                MOV R0,#0x8000
                LDR R1,=0x4001100C
                STR R0,[R1]
             
                POP {R0,R1,PC};???????R0,R1,LR?????R0,R1,PC
LED_ON_A
                PUSH {R0,R1, LR}    
                
                MOV R0,#0x00
                LDR R1,=0x4001080C
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED_OFF_A
                PUSH {R0,R1, LR}    
                
                MOV R0,#0x01
                LDR R1,=0x4001080C
                STR R0,[R1]
             
                POP {R0,R1,PC}  
LED_ON_B;??
                PUSH {R0,R1, LR}    
                
                MOV R0,#0x000
                LDR R1,=0x40010C0C
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED_OFF_B;??
                PUSH {R0,R1, LR}    
                
                MOV R0,#0x200
                LDR R1,=0x40010C0C
                STR R0,[R1]
             
                POP {R0,R1,PC}  
LED_ON_C;??
                PUSH {R0,R1, LR}    
                
                MOV R0,#0x0000
                LDR R1,=0x4001100C
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED_OFF_C;??
                PUSH {R0,R1, LR}    
                
                MOV R0,#0x8000
                LDR R1,=0x4001100C
                STR R0,[R1]
             
                POP {R0,R1,PC}        
             
Delay
                PUSH {R0,R1, LR}
                
                MOVS R0,#0
                MOVS R1,#0
                MOVS R2,#0
                
DelayLoop0        
                ADDS R0,R0,#1

                CMP R0,#330
                BCC DelayLoop0
                
                MOVS R0,#0
                ADDS R1,R1,#1
                CMP R1,#330
                BCC DelayLoop0

                MOVS R0,#0
                MOVS R1,#0
                ADDS R2,R2,#1
                CMP R2,#15
                BCC DelayLoop0
                
                
                POP {R0,R1,PC}    
                NOP
				END

建立工程步骤与C语言一致,只是新建文件的时候需要选择.s类型。

  • 注意:
    这里还需要一个操作,右键点击启动文件选择带魔法棒的选项
    在这里插入图片描述
    取消这两个选项的勾选,否则会出错
    在这里插入图片描述
    然后重复操作就可以得到一样的运行结果了。

六、总结

本次实验点亮LED流水灯就像每个编程语言的入门程序HELLO WORLD一般,是嵌入式编程最基础的东西。通过本次实验了解到了关于GPIO寄存器的相关操作,相信本次实验会对接下来的实验奠定很重要的基础。

七、参考资料

STM32 F103之点亮LED流水灯 (STM32入门学习)
二、STM32的GPIO输出操作
【STM32】GPIO的相关配置寄存器、库函数、位操作(实例:STM32控制跑马灯)
野火产品资料下载中心

### Spring Boot 整合 MyBatis 时找不到数据库的原因分析 在 Spring Boot 中整合 MyBatis 并配置数据库连接时,如果遇到无法找到数据库的情况,可能是由于以下几个原因引起的: #### 1. **数据源配置错误** 如果 `application.properties` 或 `application.yml` 文件中的数据源配置项填写错误,则可能导致程序无法正确连接到目标数据库。常见的错误包括但不限于: - 数据库 URL 错误(例如拼写错误或端口号不对)[^2]。 - 用户名或密码错误。 正确的数据源配置应类似于以下形式: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` #### 2. **依赖版本冲突** 如果项目中引入的 MyBatis 和 Spring Boot 的版本不兼容,可能会导致初始化失败或者无法正常加载数据库资源。建议检查项目的 `pom.xml` 文件,确保使用的依赖版本匹配。例如: ```xml <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.3.0</version> </dependency> ``` #### 3. **未启用 Mapper 接口扫描** 如果没有正确配置 `@MapperScan` 注解来指定 Mapper 接口所在的包路径,MyBatis 将无法识别这些接口,从而引发异常。可以通过以下方式解决此问题[^3]: ```java @SpringBootApplication @MapperScan("com.example.mapper") // 替换为实际的 mapper 路径 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` #### 4. **数据库服务不可用** 当本地开发环境下的 MySQL 或其他数据库服务未启动时,也会报出类似的 “找不到数据库” 错误。可以尝试通过命令行或其他工具手动测试数据库连通性,确认其状态是否正常运行。 #### 5. **IDEA 缺乏 SQL 提示支持** 若开发者希望获得更友好的编码体验,在 IDEA 上完成相应设置后能够享受智能补全功能带来的便利。具体做法可参照文档说明调整插件选项以便增强用户体验效果[^4]。 --- ### 解决方案总结 针对上述可能存在的各类状况逐一排查即可定位根本所在;同时注意保持各组件间良好的协作关系以减少不必要的麻烦发生几率。 ```java // 示例代码片段展示如何定义一个简单的 DAO 层类 public interface UserMapper extends BaseMapper<UserEntity> {} ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值