嵌入式软件--stm32 DAY 2

大家学习嵌入式的时候,多多学习用KEIL写代码,虽然作为编译器,大家常用vscode等常用工具关联编码,但目前keil仍然是主流工具之一,学习掌握十分必要。

1.再次创建项目

1.1编译器自动生成文件

1.2初始文件

这样下次创建新项目时,只需复制上一个项目,删除自动生成的文件,后根据自我需求进行修改。

重新打开工程后,需要重新配置,重新配置后才会生成文件。

2.再做项目

2.1需求

在第一个项目中,我们点亮了黄灯。接下来点亮蓝灯和绿灯。

2.2准备工作

2.2.1原理图查接线

由原理图可知,LED负极端给一个低电平就可以点亮。得出有效条件:低电平有效

2.2.2有效信息写代码

我们知道,所有外设都基本挂在系统总线上,APB1 APB2.从总线上找GPIO

他们都属于GPIOA同一组时钟。

配置PA1为输出,看寄存器CRL.PA0是后面的四位,那PA1就是前面的四位。

通用推挽输出的配置通常需要将 CNF 设置为 00(推挽输出),而 MODE 根据所需的速度选择,比如 2MHz、10MHz 或 50MHz。例如,对于 50MHz 的速度,MODE 位应设置为 11。因此,对应的 CRL 位需要设置为 0011,即十进制的 3,也就是0x 30

最后几位应该是1101,对应16进制D。所以0xfffd。

蓝灯就会亮起。黄灯之所以不亮是因为如果没有延迟,是观察不到的,它的程序反应速度很快。

绿灯对应引脚PA8。因为8-15的引脚不在低寄存器里,需要看高寄存器。也就是CRH的最低四位

基地址+偏移地址。*(uint32 *)(0x4001 0800+0x04)=0x03

输出低电平,偏移量0x0c.给ODR8一个0.也就是0xfeff.

这样绿灯就会亮起。

看到这里,也就明白了,让三灯同时亮起。

也就是ODR端口数据寄存器配置为0xfefc。

端口配置寄存器CRL,就让低8位为00110011,其他全是0,也就是0x33.

这就是电灯案例的标准库寄存器写法,但是不是有些难看?

寄存器写法的步骤也无非就是开启GPIO时钟,配置端口寄存器输入输出,配置输入输出数据。

先找到引脚的起始地址,再找寄存器对应偏移量,加一起就可以找到寄存器操作地址,还需要强转成32位指针。可不可以不需要这些地址?

我们可以选择优化!

2.3代码优化

不知道大家发现没,我们并没有用到Start里面的.h文件。并没有引入各种额外文件。

如果简化的话,就需要引入额外文件。将一些地址加以宏定义,就会好看许多。

2.3.1 改进1 使用宏定义改写寄存器地址

引入文件

时钟配置也可以

RCC->APB2ENR=4;

注意stm32f10x.h文件里面集成了很多寄存器和引脚的宏定义。只有引用他才能宏替换地址。

优点:这样比地址好看很多,只要记住模块名和寄存器名称,就能配置。

但是目前缺陷也很明显。例如RCC->APB2ENR=4,不仅打开了GPIOA时钟,也将其他的模块关闭了。我们应该在不影响其他模块的前提下,打开GPIOA时钟。

C语言里面讲过位运算,只改想要的位,不改其他位。

2.3.2 使用位运算对某一位进行操作

跟0作位于,一定为0;跟1作位或,一定为1;

置0,与0位于,置一,与1位或.

2.3.3 改进2 使用位运算实现只改变某一位的值。

RCC->APB2ENR=4 4即0x0100,只要让第三位为1,其他保持不变。那就只要和一个第三位为1,其他为0的数作位或即可。也就是与(1<<2)做位或。

RCC->APB2ENR|=(1<<2)即可。

配置PA0为输出,GPIOA->CRL=0x03; 0011,cnF0=00,mode=11,前两位为0,后两位是1,其他位不受影响。这样才能保证PA0为输出。

GPIOA->CRL|=(1<<0);

GPIOA->CRL|=(1<<1);

GPIOA->CRL&=~(1<<3);

GPIOA->CRL&=~(1<<4);

PA0输出低电平,ODR最后一位为0,其他位不改变。

GPIOA->ODR&=~(1<<0);

led1 黄灯就会亮。

这种写代码方法只需要记住模块和寄存器,后续还要记住第几位,需要查手册。

2.3.4 改进3 使用宏定义改变每一位的表示

时钟开启可以改进:RCC->APB2ENR|=(1<<2)

改进后:RCC->APB2ENR|=RCC_APB2ENR_IOPAENR

大家要熟悉这种写法,以后寄存器写法的代码都是这种风格。完全靠宏定义取代了地址的写法,这个主推!!!

3.GPIO整体概述

GPIO引脚就是通用输入输出引脚。存在意义便是用程序控制他们的输入或输出。

3.1 与GPIO相关寄存器

3.2 8种工作模式

3.3推挽输出总结

3.4 开漏输出

3.5 推挽输出和开漏输出的选择

使用推挽:

1.驱动能力需求较高的场合

2.高速信号传输

3.无需共用信号线的场合

使用开漏:

1.多个设备共用信号线

2.不同电压系统之间的接口

3.需要外部上拉电阻来确定逻辑高电平的场合

3.6复用输出模式

复用输出信号来自片上外设(芯片中各种外设模块)

通用开漏,连ODR。

复用开漏,那条线打到片上外设,选哪个模块,配置哪个

复用功能(AF),端口必须配置成复用输出。

看下图,输入模式下,输出完全不导通。

浮空输入,上拉下拉都断开。还想上下拉的话,外部接上拉电阻或下拉电阻。

总结:

模拟输入耗电极小,肖特基触发器关闭。

输入模式就不用分通用还是复用了,都是外部输入来的。

4.GPIO寄存器

每组GPIO端口,都有7个相关寄存器。

配置寄存器和数据寄存器几乎是配置GPIO必用的,必须背会。

上下拉输入都是10 00,那么就用ODR这一位来区分。下拉ODR配0,上拉ODR配1.

0-7引脚用端口配置低寄存器来配,8-15引脚用端口高寄存器来配。

复位值16进制,每一位都是4,0100,对应浮空输入,断掉上下拉电阻的开关,最省电。

输入数据寄存器IDR,16位,一个引脚对应1位。

BS0为1,间接ODR0为1;BR0为1,间接导致OER0为0.如果同时启动BSy和BRy,只有BS起作用。

LCK0直接对ODR0进行锁定。锁定之后在下次端口位复位前不改配置。

5.Keil+VSCode优化开发体验

为了让页面更好看,联想能力更强。就用keil负责与32的联接烧录,VSCode复制写代码。

VSCode我之前在C语言的教程中,安装过,这里不再阐述,关于汉化和C/C++的扩展插件也下载好。

关键插件:Keil Assistant

5.1 下载安装VScode

6.GPIO应用案例:流水灯

需求:在三个LED灯上实现流水灯效果。

注意点:加入延时效果(定时器)。

6.1软件设计

之前我们有过点灯的案例,启动文件和用户文件已经配好,那么可以直接复制使用。将文件的名字和工程名字改过来就可以了。删掉无关文件和目录(编译器自动生成)。

点开工程,完成一系列必要的配置。连上硬件和S-TINK.

之后确定即可。

在VScode里面打开.

导入文件,后写代码

配置GPIOA时钟,再把三个GPIO引脚配成通用推挽输出。记住位或置一,位于置零。

然后我们想想,初始状态得让他们全关灯,然后一个一个亮,前一个亮,后一个就得灭。

我们需要定义延时函数。

我们这个芯片可以用系统滴答定时器。每滴答一次-1.那么多长时间滴答一次?

CPU主频72MHZ,所以一秒钟72M次滴答,1/72M 秒滴答一次。

这样就可以实现流水灯了。

cpp 复制代码
#include "stm32f10x.h"
//定义延时函数
void delay_ms(u16 ms);
void delay_us(u16 us);
void delay_s(u16 s);

int main(void)
{
	//1.时钟配置,开启GPIOA时钟
	
	RCC->APB2ENR|=RCC_APB2ENR_IOPAEN;

	//2.工作模式配置,PA0 PA1 PA8通用推挽输出  CNF=00,MODE=11
	GPIOA->CRL&=~GPIO_CRL_CNF0;
	GPIOA->CRL|=GPIO_CRL_MODE0;
	GPIOA->CRL&=~GPIO_CRL_CNF1;
	GPIOA->CRL|=GPIO_CRL_MODE1;
	GPIOA->CRH&=~GPIO_CRH_CNF8;
	GPIOA->CRH|=GPIO_CRH_MODE8;
	
	//3.初始全高电平,都置1
	
	GPIOA->ODR|=GPIO_ODR_ODR0;
	GPIOA->ODR|=GPIO_ODR_ODR1;
	GPIOA->ODR|=GPIO_ODR_ODR8;

	//4.在循环中依次点亮,延迟一段时间关闭

	
	while(1)
	{
		//点亮LED1
		GPIOA->ODR&=~GPIO_ODR_ODR0;
		//延时半秒
		delay_ms(500);
		//关闭LED1
		GPIOA->ODR|=GPIO_ODR_ODR0;
		//点亮LED2
		GPIOA->ODR&=~GPIO_ODR_ODR1;
		//延时半秒
		delay_ms(500);
		//关闭LED2
		GPIOA->ODR|=GPIO_ODR_ODR1;
		//点亮LED3
		GPIOA->ODR&=~GPIO_ODR_ODR8;
		//延时半秒
		delay_ms(500);
		//关闭LED3
		GPIOA->ODR|=GPIO_ODR_ODR8;
		
	}
	
}

void delay_us(u16 us)
{
	//设置系统定时器的初始计数值
	SysTick->LOAD=72 * us;
	//配置系统定时器
	SysTick->CTRL=0x05;
	//轮询等待计数值变为0,countflag-1
	while(!(SysTick->CTRL&SysTick_CTRL_COUNTFLAG))
	{

	}
//关闭定时器
SysTick->CTRL&=~SysTick_CTRL_ENABLE;
}

void delay_s(u16 s)
{
	while (s--)
	{
		delay_ms(1000);
	}
}

void delay_ms(u16 ms)
{
	while (ms--)
	{
		delay_us(1000);
	}
	
	
}

7.资料下载

stm32开发官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘123云盘为您提供stm32开发最新版正式版官方版绿色版下载,stm32开发安卓版手机版apk免费下载安装到手机,支持电脑端一键快捷安装https://www.123684.com/s/TQubTd-LcEtv?提取码:f2RP

相关推荐
cjy_Somnr12 小时前
keil5报错显示stm32的SWDIO未连接不能烧录
stm32·单片机·嵌入式硬件
Lay_鑫辰13 小时前
西门子诊断-状态和错误位(“轴”工艺对象 V1...3)
服务器·网络·单片机·嵌入式硬件·自动化
无垠的广袤15 小时前
【工业树莓派 CM0 NANO 单板计算机】本地部署 EMQX
linux·python·嵌入式硬件·物联网·树莓派·emqx·工业物联网
雲烟17 小时前
嵌入式设备EMC安规检测参考
网络·单片机·嵌入式硬件
泽虞17 小时前
《STM32单片机开发》p7
笔记·stm32·单片机·嵌入式硬件
田甲17 小时前
【STM32】 数码管驱动
stm32·单片机·嵌入式硬件
up向上up18 小时前
基于51单片机垃圾箱自动分类加料机快递物流分拣器系统设计
单片机·嵌入式硬件·51单片机
纳祥科技1 天前
Switch快充方案,内置GaN,集成了多个独立芯片
单片机
单片机日志1 天前
【单片机毕业设计】【mcugc-mcu826】基于单片机的智能风扇系统设计
stm32·单片机·嵌入式硬件·毕业设计·智能家居·课程设计·电子信息
松涛和鸣1 天前
从零开始理解 C 语言函数指针与回调机制
linux·c语言·开发语言·嵌入式硬件·排序算法