【STM32-野火】---学习笔记---二.新建工程模板——寄存器版、使用寄存器点亮LED

1 新建工程模板——寄存器版

1.1 头文件中<>与""的区别

#include <ste3210x.h> // 头文件不在当前目录下,在软件的安装(根)目录下

#include "stm32f10x.h" // 头文件在当前目录下,如果找不到再去软件的安装(根)目录下找

1.2 .axf文件与.hex文件

  • .axf文件是可以通过编译器DownLoad(F8)下载的可执行文件。
  • .hex文件是可以通过串口下载的可执行文件。

1.3 新建工程

  • 一.新建工程:打开KEIL5,点击New μVision Project -> 创建一个.uvprojx文件(名称根据自己喜好命名)。
    在这里插入图片描述

  • 二.选择CPU型号:在Select Device for Target ‘Target 1’…中,点击STM32F1 Series,再点击STM32F103VE。

如果这里没有出现你想要的 CPU 型号,或者一个型号都没有,说明你的KEIL5没有添加device库,KEIL5 不像 KEIL4 那样自带了很多 MCU 的型号, KEIL5 需要自己添加。

在这里插入图片描述

  • 三.添加文件:添加 startup_stm32f10x_hd.s文件(启动文件),创建 main.c文件(定义一个SystemInit函数),创建 stm32f10x.h文件,并导入 main.c 中。

  • 四.新建文件:手动创建stm32f10x.h文件,用于存放寄存器映射的代码。(注:这个stm32f10x.h文件并非官方固件库中的文件)

在这里插入图片描述

  • 五.配置魔术棒选项卡:

    • 5.1 Target 中选中微库“Use MicroLib”,为的是在日后编写串口驱动的时候可以使用 printf 函数。
      在这里插入图片描述

    • 5.2 Target 中ARM Complier 选择 Use of complier version 5。

    • 5.3 Output 选项卡中把输出文件夹定位到我们工程目录下的 output 文件夹,如果想在编译的过程中生成 hex 文件,那么那 Create HEX File 选项勾上。
      在这里插入图片描述

    • 5.4 在 Listing 选项卡中把输出文件夹定位到我们工程目录下的 Listing 文件夹。
      在这里插入图片描述

  • 六.下载器配置:在仿真器连接好电脑和开发板且开发板供电正常的情况下,打开编译软件 KEIL,在魔术棒选项卡里面选择仿真器的型号。

    • 6.1 Debug 选项配置:
      在这里插入图片描述

    • 6.2 Utilities 选项配置:
      在这里插入图片描述

    • 6.3 Utilities 选项配置:选择目标板,具体选择多大的 FLASH 要根据板子上的芯片型号决定。 (F103-“指南者”选 512K。)在这里插入图片描述

      如果SWJ勾选不了,点击 Flash Download 旁边的Pack,将勾选上的Enable去掉。

      在这里插入图片描述

      这里面有个小技巧就是把 Reset and Run 也勾选上,这样程序下载完之后就会自动运行,否则需要手动复位。擦除的 FLASH 大小选择 Sectors 即可,不要选择 Full Chip,不然下载会比较慢。

  • 七.下载程序:如果前面步骤都成功了,接下来就可以把编译好的程序下载到开发板上运行。下载程序不需要其他额外的软件,直接点击 KEIL 中的 LOAD 按钮即可。
    在这里插入图片描述

2 使用寄存器点亮LED灯

在写这一节程序的时候,只需要一份资料:《STM32F10X-中文参考手册》。

2.1 如何点亮STM32的LED灯

对于51而言,想要点亮一盏灯:

// 假设LED链接到芯片的P0.0口,MCU给低电平点亮

#include <reg51.h>

sbit LED = P0^0;

void main(void)
{
    LED = 0; //位操作
    
    P0 = 0XFE; // 总线操作
}

对于STM32,使用类似于51的写法:

  • 打开时钟:为了降低功耗,时钟全部复位为0(即关闭)。
  • 配置IO口的输出模式:STM32的IO口需要配置输入/输出模式。
  • 配置ODR寄存器:对某一位进行操作(打开或关闭)。
#include "stm32f10x.h"

int main(void)
{
	// 配置时钟
	* (unsigned int*) 0X40021018 |= (1<<3);
	
	
	// 配置IO口输出模式
	* (unsigned int*) 0X40010C00 |= (1<<4);
	
	
	// 配置GPIOB ODR
	* (unsigned int*) 0X40010C0C &= ~(1<<1);
}

void SystemInit(void)
{
	// 函数体为空,目的是为了骗过编译器不报错
}
  • 配置ODR寄存器:《2.3存储器映像》找到GPIOB的基地址 -> 《8.2.4端口输出数据寄存器》找到GPIO_ODR的地址偏移,相加得到GPIO_ODR寄存器地址。

  • 配置IO口输出模式:

    • 低寄存器控制低8位IO口的输入/输出模式;CNF0[1:0]与MODE0[1:0]共同控制PB0的模式、CNF1[1:0]与MODE1[1:0]共同控制PB1的模式…
    • 2.3存储器映像》找到GPIOB的基地址 -> 《8.2.1配置低寄存器》找到GPIO_CRL的地址偏移,相加得到GPIO_CRL寄存器地址。

请添加图片描述

  • 打开时钟:
    • 在《2存储器和总线构架》中由图1 系统结构可知:复位和时钟控制(RCC)挂在AHB系统总线上,GPIOB在APB2总线上。
    • 《2.3存储器映像》找到RCC的基地址 -> 《6.3.7APB2外设时钟使能寄存器》找到RCC_APB2ENR的地址偏移,相加得到RCC_APB2ENR寄存器地址。

在这里插入图片描述

请添加图片描述

2.2 练习

1.将三个LED灯一起点亮(呈白灯)。

#include "stm32f10x.h"

int main(void)
{
	// 配置时钟
	* (unsigned int*) 0X40021018 |= (1<<3);
	
	
	// 配置IO口输出模式 
	* (unsigned int*) 0X40010C00 |= (1<<4); // PB1
	* (unsigned int*) 0X40010C00 &= ~(1<<7);
	
	* (unsigned int*) 0X40010C00 |= (1<<0); // PB0
	* (unsigned int*) 0X40010C00 &= ~(1<<2);
	
	* (unsigned int*) 0X40010C00 |= (1<<20); // PB5
	* (unsigned int*) 0X40010C00 &= ~(1<<22);
	
	
	// 配置GPIOB ODR
	* (unsigned int*) 0X40010C0C &= ~(1<<1); // PB1 = 0
	* (unsigned int*) 0X40010C0C &= ~(1<<0); // PB0 = 0
	* (unsigned int*) 0X40010C0C &= ~(1<<5); // PB5 = 0
}

void SystemInit(void)
{
	// 函数体为空,目的是为了骗过编译器不报错
}
  • 对GPIO_CRL的第2位、第7位、第22位置0的原因:复位后这三位都是1。在置0后输出模式由通用开漏输出模式转换为通用推挽输出模式。

2.写一个简单的延迟函数,让LED灯闪烁

#include "stm32f10x.h"

void delay(void)
{
	int x, y;
	for(x = 1100; x>0; x--)
	{
		for(y = 1000; y>0; y--);
	}
}
	

int main(void)
{
	// 配置时钟
	* (unsigned int*) 0X40021018 |= (1<<3);
	
	
	// 配置IO口输出模式 
	* (unsigned int*) 0X40010C00 |= (1<<4); // PB1 Blue
	* (unsigned int*) 0X40010C00 &= ~(1<<7);
	
	* (unsigned int*) 0X40010C00 |= (1<<0); // PB0 Green
	* (unsigned int*) 0X40010C00 &= ~(1<<2);
	
	* (unsigned int*) 0X40010C00 |= (1<<20); // PB5 Red
	* (unsigned int*) 0X40010C00 &= ~(1<<22);
	
	
	// 配置GPIOB ODR
	while(1)
	{
		* (unsigned int*) 0X40010C0C &= ~(1<<1); // PB1 = 0
		delay();
		* (unsigned int*) 0X40010C0C |= (1<<1);
		delay();
	}
}

void SystemInit(void)
{
	// 函数体为空,目的是为了骗过编译器不报错
}
  • 上面的这段代码呈现的效果为:白灯与黄灯(红与绿混合为黄色)交替闪烁。
    • 原因:GPIOB_ODR复位值为0x0000 0000 ,而STM32上的LED灯为低电平触发,恰好使得红灯与绿灯常亮。
    • 要想让STM32上的LED灯呈现出蓝、绿、红三色交替闪烁的效果,需要在while循环前将GPIO_ODR相应的位置1。
#include "stm32f10x.h"

void delay(void)
{
	int x, y;
	for(x = 1100; x>0; x--)
	{
		for(y = 1000; y>0; y--);
	}
}
	

int main(void)
{
	// 配置时钟
	* (unsigned int*) 0X40021018 |= (1<<3);
	
	
	// 配置IO口输出模式 
	* (unsigned int*) 0X40010C00 |= (1<<4); // PB1 Blue
	* (unsigned int*) 0X40010C00 &= ~(1<<7);
	
	* (unsigned int*) 0X40010C00 |= (1<<0); // PB0 Green
	* (unsigned int*) 0X40010C00 &= ~(1<<2);
	
	* (unsigned int*) 0X40010C00 |= (1<<20); // PB5 Red
	* (unsigned int*) 0X40010C00 &= ~(1<<22);
	
	* (unsigned int*) 0X40010C0C |= (1<<1);
	* (unsigned int*) 0X40010C0C |= (1<<5);
	* (unsigned int*) 0X40010C0C |= (1<<0);
	
	
	// 配置GPIOB ODR
	while(1)
	{
		* (unsigned int*) 0X40010C0C &= ~(1<<1); // PB1 = 0
		delay();
		* (unsigned int*) 0X40010C0C |= (1<<1);
		delay();
	
		* (unsigned int*) 0X40010C0C &= ~(1<<0); // PB0 = 0
		delay();
		* (unsigned int*) 0X40010C0C |= (1<<0);
		delay();
	
		* (unsigned int*) 0X40010C0C &= ~(1<<5); // PB5 = 0
		delay();
		* (unsigned int*) 0X40010C0C |= (1<<5);
		delay();
	}
}

void SystemInit(void)
{
	// 函数体为空,目的是为了骗过编译器不报错
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值