IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F103寄存器方式点亮LED流水灯 -> 正文阅读

[嵌入式]STM32F103寄存器方式点亮LED流水灯

一、学习STM32芯片

1、存储器映射

存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址
的过程就称为存储器映射

下图为STM32F10xxx中内置外设的起始地址。

2、以GPIOx为例讲解相关寄存器

将已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。

在这里插入图片描述

(1)、找到GPIOx的地址,通过上图可看到GPIOA的地址为0x40010800

在这里插入图片描述
(2)GPIO端口低寄存器
在这里插入图片描述
这是存储数据的地址。方法为端口起始地址+偏移地址。所以GPIOA_CRL的储存数据的位置为0x40010800+0x00=0x40010800。
每个寄存器含有32位,每4位用来设置1个GPIO引脚功能。GPIOx_CRL/GPIOx_CRH 两个寄存器共含有64位,因此可完成对GPIO015的设定。其中GPIOx_CRL用于设置GPIO07引脚,GPIOx_CRH用于设置GPIO8~15引脚。

(3)GPIO端口配置高寄存器
在这里插入图片描述
推挽输出:可以输出高,低电平,连接数字器件;推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。
开漏输出:输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行,适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)。

GPIOA_CRH=0xFFFFFFF0;//清调PA8原来的设置,同时屏蔽其它端口,不影响其他端口的设置
GPIO_CRH|=0x00000003//PA8推挽输出

十六进制中的3换成二进制00 11 前两位00表示推挽输出,后两位11表示输出频率50Mhz。
(4)GPIO端口输入数据寄存器
在这里插入图片描述

 // 读取 GPIOB 端口的 16 位数据值
  uint16_t temp;
 temp = GPIOB->IDR;

(5)GPIO端口输出数据寄存器
在这里插入图片描述
该地址偏移为:0x0C。 低16位有效,每一个位对应一个IO,控制引脚输出状态。ODR寄存器可读可写:既能控制管脚为高电平,也能控制管脚为低电平。
(6)GPIO端口位设置/清除寄存器
在这里插入图片描述
BSRR 只写寄存器:[color=Red]既能控制管脚为高电平,也能控制管脚为低电平。对寄存器高 16bit 写1 对应管脚为低电平,对寄存器低16bit写1对应管脚为高电平。写 0 ,无动作。
(7)开启外设时钟

 开启 GPIOB 端口 时钟
 RCC_APB2ENR |= (1<<3);

由于 STM32的 外设很多,为了降低功耗,每个外设都对应着一个时钟,在芯片刚
上电的时候这些时钟都是被关闭的,如果想要外设工作,必须把相应的时钟打开。
(8)GPIO端口初始化
以GPIOB为例。

// 开启 GPIOB 端口时钟
GPIOB_CRL &= ~( 0x0F<< (4*4));
 // 配置 PB4 为通用推挽输出,速度为 10M
GPIOB_CRL |= (1<<4*4); 
 // PB4 输出 低电平
GPIOB_ODR |= (0<<4);

二、寄存器实现LED灯点亮

1、代码编写

(1)C语言


//--------------APB2使能时钟寄存器------------------------
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)
//----------------GPIOB配置寄存器 ------------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)
//----------------GPIOA配置寄存器 ------------------------
#define GPIOA_CRL		*((unsigned volatile int*)0x40010800)
#define	GPIOA_ODR		*((unsigned volatile int*)0x4001080C)
//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH		*((unsigned volatile int*)0x40011004)
#define	GPIOC_ODR		*((unsigned volatile int*)0x4001100C)
//-------------------简单的延时函数-----------------------
void delay( )
{
unsigned long x;
 for(x=0;x<5000000;x++);
 	//用自减的方式粗略延时
}
//------------------------主函数--------------------------
int main()
{
 RCC_APB2ENR|=1<<4;          //APB2-GPIOC外设时钟使能
 RCC_APB2ENR|=1<<3;			//APB2-GPIOB外设时钟使能	
 RCC_APB2ENR|=1<<2;			//APB2-GPIOA外设时钟使能
 //这两行代码可以合为 RCC_APB2ENR|=1<<3|1<<6;
 GPIOB_CRL&=0xFFFF0FFF;		//设置位 清零	
 GPIOB_CRL|=0x02000000;		//PB5推挽输出
 GPIOB_ODR|=1<<6;			//设置初始灯为灭
 
 GPIOA_CRL&=0xFF0FFFFF;		//设置位 清零
 GPIOA_CRL|=0x00200000;   	//PA5推挽输出
 GPIOA_ODR|=1<<5;			//设置初始灯为灭	
 
 GPIOC_CRH&=0xF0FFFFFF;		//设置位 清零
 GPIOC_CRH|=0x02000000;   	//PC14推挽输出
 GPIOC_ODR|=1<<14;			//设置初始灯为灭	
 
 
 while(1)
 {
     GPIOC_ODR|=1<<14;		//PC14高电平
 	delay();
 	GPIOC_ODR&=~(1<<14);		//PC14低电平	
 	delay();
 	
 	GPIOB_ODR|=1<<6;		//PB5高电平
  	delay();
 	GPIOB_ODR&=~(1<<6);		//PB5低电平,因为是置0,所以用按位与
 	delay();
 	
 	
 		GPIOA_ODR|=1<<5;		//PA5高电平
 	delay();
 	GPIOA_ODR&=~(1<<5);		//PA5低电平	
 	delay();
 }

unsigned int *pRCC_APB2ENR = (unsigned int *)0x40021018;

在编译器看来0x40021018只是一个普通的变量,是一个立即数,要想让编译器也认为是指针,我们的强行类型转换,把它转成指针,即(unsigned int *)0x40021018;,然后再对这个指针进行 *操作。
1、按位操作
上述C语言中有许多按位操作,按位操作的作用是可以优化代码,让代码简单易懂。
在这里插入图片描述

X=10100000的低4位置1 ,用 X | 0000 1111 = 1010 1111即可得到。
PBn就改为GPIOB->CRL |= 0x2<<(n*4);第n个引脚输出0。
<<左移运算符,RCC -> AHB1ENR |= 1<<2;1<<2 应该读作1向左移动2位,即AHB1ENR寄存器的第2位置1。
设X=10101110, 取X的低4位,用 X & 0000 1111 = 0000 1110 即可得到;所以GPIOB_ODR&=~(1<<6);先左移为1000000再取反为0111111再进行&为0111111再赋值给GPIOB_ODR为低电平。

(2)汇编语言

    AREA MYDATA, DATA
	
 AREA MYCODE, CODE
	ENTRY
	EXPORT led

led
	;使能A,B,C
    ldr r0, =0x40021018
    ldr r1, =0x0000001c
    str r1, [r0]                


	;配置端口A4
	ldr r0, =0x40010800
    ldr r1, [r0]
    bic r1, r1, #0x000f0000
    orr r1, r1, #0x00010000
    str r1, [r0]

	;配置端口B5
    ldr r0, =0x40010c00
    ldr r1, [r0]
    bic r1, r1, #0x00f00000
    orr r1, r1, #0x00100000
    str r1, [r0]
	
	;配置端口C14
	ldr r0, =0x40011004
    ldr r1, [r0]
    bic r1, r1, #0x0f000000
    orr r1, r1, #0x01000000
    str r1, [r0]

	;初始为A4亮灯
	ldr r0, =0x4001080c
    ldr r1, =0x00000010
    str r1, [r0]

	ldr r0, =5000000;频率
    ldr r1, =0
	
;循环亮灯	
blink
    add r1, r1, #1
    cmp r1, r0
    blt blink
	
	;A4灭
	ldr r1, =0x4001080c
    ldr r2, [r1]
    eor r2, r2, #0x00000010
    str r2, [r1]
	
	;B5亮
	ldr r1, =0x40010c0c
    ldr r2, [r1]
    eor r2, r2, #0x00000020
    str r2, [r1]
	
	ldr r1, =0

blink1	
	add r1, r1, #1
    cmp r1, r0
    blt blink1
	
	;B5灭
	ldr r1, =0x40010c0c
    ldr r2, [r1]
    eor r2, r2, #0x00000020
    str r2, [r1]
	
	;C14亮
	ldr r1, =0x4001100c
    ldr r2, [r1]
    eor r2, r2, #0x00004000
    str r2, [r1]
	

	ldr r1, =0

blink2
	add r1, r1, #1
    cmp r1, r0
    blt blink2
	
	;C14灭
	ldr r1, =0x4001100c
    ldr r2, [r1]
    eor r2, r2, #0x00004000
    str r2, [r1]
	
	;A4亮
	ldr r1, =0x4001080c
    ldr r2, [r1]
    eor r2, r2, #0x00000010
    str r2, [r1]
	

	ldr r1, =0
    b blink
	
	END

2、STM32接线

根据程序中的GPIO的输出接口进行接线,GPIOA_ODR|=1<<5接A5口,GPIOB_ODR|=1<<6;接B6口,GPIOC_ODR|=1<<14 ;接C14口。TXD接A10口,RXD接A9口,电源接3.3v。接线过程中记得查看流水灯是否接地,并检查连接是否有遗漏。连接图如下:
在这里插入图片描述

3、实验结果

1、生成.hex文件,使用软件烧录程序
此步骤可参考我上篇文章:STM32串口下载程序
在此步骤可能会出现一些问题,在烧录时一直连接不到芯片,是因为接线问题不稳定,连接不上。所以最好采用公母接头的线进行接线,在烧录过程一定要检查连线是否有问题,它可能导致后续观察不到实验结果。
2、实验视频
(1)仿真器
在这里插入图片描述
(2)流水灯视频
在这里插入图片描述

三、实验总结

通过本次实验,我明白了stm32的点灯过程是通过使能外设GPIO时钟,发出指令给外设GPIO,外设GPIO收到指令后,着手配置自己的寄存器,然后给IO口模式。对于寄存器操作,在上学期的单片机原理中学过但是已经全部忘记了,寄存器数据储存操作对于我这个新手来说有点困难,我学习了很久查了很多资料,从最开始的GPIO端口的学习再到后面编写代码时的优化问题。该实验我还进行了一次仿真在连接的硬件。keil的仿真过程也是文明需要学习的,只有仿真没有错误硬件的显示才会没有错误。实验途中遇到了很多问题,在老师和同学的帮助下都一一解决了,对于STM32的流水灯实验是我们了解STM32的开始,随着我们实验难度的加深,对STM32芯片的使用也更加熟悉。

四、参考文献

【1】STM32中文参考手册
【2】寄存器讲解
【3】零死角玩转STM32-F103指南者

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-24 15:04:06  更:2021-10-24 15:04:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:18:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码