【嵌入式04】用寄存器HAL库完成LED流水灯程序
目录
一、原理学习
1、寄存器映射原理
2、GPIO端口的初始化设置步骤
二、LED流水灯
1、程序设计思路
2、寄存器方式编程实现
3、HAL库编程实现
4、软件仿真
三、总结
四、参考链接
一、原理学习
1、寄存器映射原理
地址映射
GPIO_TypeDef * GPIOx; //定义一个 GPIO_TypeDef 型结构体指针 GPIOx
GPIOx = GPIOA; //把指针地址设置为宏 GPIOA 地址
GPIOx->CRL = 0xffffffff; //通过指针访问并修改 GPIOA_CRL 寄存器
寄存器映射
我们知道,存储器本身没有地址,给存储器分配地址的过程叫存储器映射,那什么叫寄存器映射?寄存器到底是什么?
说到映射大家可能就会想到函数映射,脑海里会有一个画面:左边一个集合中的某个元素“射”出一条带箭头的直线指向右边的集合的某个元素。
其实外围设备的内存映射原理是一样的,只不过左边的集体变成了CPU,右边的集合变成了外围设备,那条带箭头的线就是连接CPU和外设地址引脚的地址总线。
存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射。
要知道,一个开发板的CPU地址引脚并不是所有的都与内存元器件相连的,如果该板上有外设(如一块独立显卡),那么CPU就需要分出一些引脚来与该外设的地址引脚相连,相当于将一部分内存寻址的空间分给了外设,那不相当于CPU分出去地址寻址空间为空?
事实并非如此,一般的外设为了加快处理速度都有自己的片内RAM(比如说显存,你也知道显存对显卡性能的重要性),分出去的地址空间也就与片内RAM物理连接起来,这样CPU就能像访问内存一样去访问外设的片内RAM,这也就是所谓的内存映射。
在存储器的区域单元中,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
2、GPIO端口的初始化设置步骤
时钟配置
原因:因为耗电量,stm32功能强大,能做很多事,但与之同时带来的消耗也越严重,此做法降低了功耗,续航持久。
时钟控制名字叫做RCC,属于AHB总线。GPIOB属于APB2。
GPIO模式
GPIO的工作模式主要有八种:4种输入方式,4种输出方式。分别为输入浮空,输入上拉,输入下拉,模拟输入;
输出方式为开漏输出,开漏复用输出,推挽输出,推挽复用输出。
(1)GPIO_Mode_AIN 模拟输入 (应用ADC模拟输入,或者低功耗下省电)
(2)GPIO_Mode_IN_FLOATING 浮空输入 (浮空就是浮在半空,可以被其他物体拉上或者拉下,可以用于按键输入)
(3)GPIO_Mode_IPD 下拉输入 (IO内部下拉电阻输入)
(4)GPIO_Mode_IPU 上拉输入 (IO内部上拉电阻输入)
(5)GPIO_Mode_Out_OD 开漏输出(开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行)
(6)GPIO_Mode_Out_PP 推挽输出 (推挽就是有推有拉电平都是确定的,不需要上拉和下拉,IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的 )
(7)GPIO_Mode_AF_OD 复用开漏输出(片内外设功能(I2C的SCL,SDA))
(8)GPIO_Mode_AF_PP 复用推挽输出 (片内外设功能TX1,MOSI,MISO.SCK.SS)
GPIO 8 种工作模式
typedef enum
{GPIO_Mode_AIN = 0x0, // 模拟输入GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入GPIO_Mode_IPD = 0x28, // 下拉输入GPIO_Mode_IPU = 0x48, // 上拉输入GPIO_Mode_Out_OD = 0x14, // 开漏输出GPIO_Mode_Out_PP = 0x10, // 推挽输出GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出GPIO_Mode_AF_PP = 0x18 // 复用推挽输出
} GPIOMode_TypeDef;
输入和输出
输入模式
浮空输入模式:浮空输入状态下,IO 的电平状态是不确定的,完全由外部输入决定,如果在该引脚悬空的情况下,读取该端口的电平是不确定的。可做KEY按键识别。
上下拉输入模式:内部设有上拉和下拉电阻,当外部电路为低电平,IO口设为下拉模式,当外部电路为低电平,IO口设为上拉模式。
模拟输入:用作内部ADC输入或DAC输出,预防干扰。
输出模式
推挽输出模式:(最常用)
开漏输出模式:(不常用)
推挽、开漏复用模式:当GPIO口被用作第二功能时,需要配置,端口重映射AFIO。
GPIO初始化步骤
第一步:使能GPIOx口的时钟
第二步:指明GPIOx口的哪一位,这一位的速度大小以及模式
第三步:调用GPIOx初始化函数进行初始化
第四步:调用GPIO-SetBits函数,进行相应位的置位
实例
对单个GPIO口的初始化:
GPIO_InitTypeDef GPIO_InitStructure;
第一步:使能GPIOA的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);第二步:设置GPIOA参数:输出OR输入,工作模式,端口翻转速率
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_6| GPIO_Pin_7| GPIO_Pin_8; //设定要操作的管脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz第三步:调用GPIOA口初始化函数,进行初始化。
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA第四步:调用GPIO-SetBits函数,进行相应为的置位。
GPIO_SetBits(GPIOA,GPIO_Pin_0); //输出高
对于多个GPIO口的初始化如下
GPIO_InitTypeDef GPIO_InitStructure;
第一步:使能GPIOA,GPIOE的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);第二步:设置GPIOA,GPIOE参数:输出OR输入,工作模式,端口翻转速率
第三步:调用GPIOA口初始化函数,进行初始化。
第四步:调用GPIO-SetBits函数,进行相应为的置位。把第二、三、四步合并分别设置GPIOA和GPIOE
先设置GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 第四个口,PA4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOA,&GPIO-InitST); //根据设定参数初始化GPIOA
GPIO_SetBits(GPIOA,GPIO_Pin_4); //输出高再设置GPIOE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // 第三个口,PE3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOE,&GPIO-InitST); //根据设定参数初始化GPIOE
GPIO_SetBits(GPIOE,GPIO_Pin_3); //输出高
二、LED流水灯
以 STM32最小系统核心板STM32F103C8T6+面板板+3只红绿蓝LED 搭建电路,使用GPIOA-5、GPIOB-9、GPIOC-14这3个端口控制LED灯,轮流闪烁,间隔时长1秒。
1、程序设计思路
工程文件模板的建立
新建工程LED文件,工程名为LED,因为之后实验采用C8T6板,因此这里选择STM32F103C8
之后弹出的添加库文件窗口Manage Run-Time Environment,在这个界面,我们可以添加自己需要的组件,从而方便构建开发环境,不过这里我们不做介绍。选择Cancel即可。
流水灯原理
本次实验采用三个灯实现,亮灯状态用1表示,灭灯状态用0表示。
初始状态为0 0 0,
状态一为1 0 0
状态二为0 1 0
状态三为0 0 1
状态三结束后继续进入状态一,一直循环达到流水灯效果。
2、寄存器方式编程实现
#include "stm32f10x.h"
//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)
//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
#define GPIOA_ODR *((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)
#define GPIOB_ODR *((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
#define GPIOC_ODR *((unsigned volatile int*)0x4001100C)//延时函数void Delay(){u32 i=0;for(;i<5000000;i++);}int main(void){ RCC_APB2ENR|=1<<2|1<<3|1<<4; //APB2-GPIOA、GPIOB、GPIOC外设时钟使能GPIOA_CRL&=0xFFF0FFFF; //设置位 清零GPIOA_CRL|=0x00020000; //PA5推挽输出GPIOA_ODR&=~(1<<5); //设置初始灯为灭GPIOB_CRL&=0xFF0FFFFF; //设置位 清零GPIOB_CRL|=0x00200000; //PB9推挽输出GPIOB_ODR&=~(1<<9); //设置初始灯为灭GPIOC_CRH&=0xF0FFFFFF; //设置位 清零GPIOC_CRH|=0x02000000; //PC14推挽输出GPIOC_ODR&=~(1<<14); //设置初始灯为灭while(1){//A灯GPIOA_ODR|=1<<5; //PA5高电平Delay();GPIOA_ODR&=~(1<<5); //PA5低电平,因为是置0,所以用按位与//B灯GPIOB_ODR|=1<<9; //PB9高电平Delay();GPIOB_ODR&=~(1<<9); //PB9低电平,因为是置0,所以用按位与//C灯GPIOC_ODR|=1<<14; //PC14高电平Delay();GPIOC_ODR&=~(1<<14); //PC14低电平,因为是置0,所以用按位与}
}
3、HAL库编程实现
(1)安装STM32CubeMX
CubeMX可在官网下载
打开安装好的STM32CubeMX;点击HELP->Manage embedded software packages :;会跳出来一个选择型号界面 勾选上你要安装的HAL库, 点击“Install Now” 直到安装成功。 如下图:
(2)安装HAL库
STM32 HAL固件库是Hardware Abstraction Layer的缩写,中文名称是:硬件抽象层。HAL库是ST公司为STM32的MCU最新推出的抽象层嵌入式软件,为更方便的实现跨STM32产品的最大可移植性。HAL库的推出,可以说ST也慢慢的抛弃了原来的标准固件库,这也使得很多老用户不满。但是HAL库推出的同时,也加入了很多第三方的中间件,有RTOS,USB,TCP / IP和图形等等。
和标准库对比起来,STM32的HAL库更加的抽象,ST最终的目的是要实现在STM32系列MCU之间无缝移植,甚至在其他MCU也能实现快速移植。
并且从16年开始,ST公司就逐渐停止了对标准固件库的更新,转而倾向于HAL固件库和 Low-layer底层库的更新,停止标准库更新,也就表示了以后STM32CubeMX配置HAL/LL库是主流配置环境;
打开安装好的STM32CubeMX
点击HELP->Manage embedded software packages :
会跳出来一个选择型号界面 勾选上你要安装的HAL库, 点击“Install Now” 直到安装成功。 如下图:
(3)新建项目
创建新项目 点ACCESS TO MCU SELECTOR
在part name里选择自己的芯片,点击信息栏中的具体芯片信息选中,点击start project:
点击system core,进入SYS,在debug下选择serial wire:
配置时钟,进入上面的rcc,有两个时钟,一个是hse和lse,我们要用是GPIO接口,而这些接口都在APB2里,接下来观察时钟架构,APB2总线的时钟由hse控制,同时在这个界面得把PLLCLK右边选上:
将hse那里设为Crystal/Ceramic Resonator:
接下来就是点击相应的引脚设置输出寄存器了,就是output那一项,一共选了三个,是PA5,PB9,PC14:
点击project manager,配置好自己的路径和项目名,然后IDE那项改为MDK-ARM:
进入 code generate界面,选择生成初始化.c/.h文件,后面点击generate code,选择open project,然后就到KEIL5了:
4、软件仿真
打开.uvprojx文件(或者在上一步选择open project)
将下面代码放入主函数中(替代里面的内容)
替换代码
SystemClock_Config();//系统时钟初始化MX_GPIO_Init();//gpio初始化while (1){ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);//PA5亮灯HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC14熄灯HAL_Delay(1000);//延时1sHAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);//PA5熄灯HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9亮灯HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC14熄灯HAL_Delay(1000);//延时1sHAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);//PA5熄灯HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC14亮灯HAL_Delay(1000);//延时1s}
}
观察GPIO端口的输出波形
Target界面中,选择跟正确的晶振大小,我使用的是72MHz的外部晶振。这个选项在软件仿真中起到很重要的作用,如果选择错误,那么波形一定是错误的,因为时间不准确。
Debug页的设置:
点击Debug,进入调试界面:
选择逻辑分析仪:
选择要观察的引脚:
①点击Setup Logic Analyzer
②添加要观察的引脚:
相关设置
运行程序:
观察波形:
引脚为低电平的灯亮,高电平的灯不亮,高低电平转换周期(LED闪烁周期)为1s左右。
三、总结
学习和理解STM32F103系列芯片的地址映射和寄存器映射原理;了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。在单独使用keil写流水灯的时候,自己要写的相关语句比较多,用STMCubeMX+keil+hal库实现点灯比较容易。
四、参考链接
http://t.csdn.cn/tpojg
http://t.csdn.cn/dfCVT
http://t.csdn.cn/ShtuY
【嵌入式04】用寄存器HAL库完成LED流水灯程序相关推荐
- 用寄存器HAL库完成LED流水灯程序
重庆交通大学信息科学与工程学院 <嵌入式系统开发>课程 作业报告(第4周) 班 级: 通信工程2001 姓名-学号 : 阎桂董-632007030622 实验项目名称: 作业题目 实验项目 ...
- STM32Cubemx的安装及用寄存器HAL库完成LED流水灯程序
目录 一.STM32CubeMx安装 (一)简介 (二)下载地址 1.官方下载地址 2.网盘下载地址 二.STM32CubeMX安装过程 三.HAL库安装 四.HAL库实现LED流水灯 (一)新建项目 ...
- 用寄存器HAL库完成LED流水灯程序以及通过MDK5模拟示波器观察波形
文章目录 前言 一.相关寄存器配置介绍 1.相关寄存器配置介绍 二.使用寄存器点亮LED灯 1.工程模板的建立 2.配置GPIO端口 3.主要函数 4.编译生成HEX文件 5.电路搭建 三.STM32 ...
- 用寄存器HAL库完成LED流水灯程序
STM32的地址映射.寄存器映射原理以及GPIO端口的初始化设置三步骤 (一)STM32F103系列芯片的地址映射及寄存器映射原理 1.STM32F103C8T6简要介绍 ● STM32F103C8 ...
- 【嵌入式基础】用C语言编程、寄存器实现LED流水灯程序;stm32CubeMX+Keil使用HAL库点亮流水灯
本文主要介绍STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置步骤.利用C语言编程和寄存器点亮流水灯以及stm32CubeMX+Keil使用HAL库点灯 目录 一.STM3 ...
- STM32F03寄存器方式点亮LED流水灯
STM32F03寄存器方式点亮LED流水灯 文章目录 STM32F03寄存器方式点亮LED流水灯 一.题目内容 二.STM32F03系列芯片的地址映射和寄存器映射映射原理:了解GPIO端口的初始化设置 ...
- STM32F103寄存器方式点亮LED流水灯
实验要求:以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED 搭建电路,使用GPIOB.GPIOC.GPIOD这3个端口控制LED灯,轮流闪烁,间隔时长1秒.1)写出 ...
- pic单片机流水灯循环右移c语言,PIC单片机LED流水灯程序
PIC 单片机 LED流水灯程序 ;************************************************************* include ;*********** ...
- led流水灯c语言数组程序,LED流水灯程序 一维数组写法
LED流水灯程序 一维数组写法 /*********** (C) COPYRIGHT 201 2************ * 程序作者: 蓝雨(QQ:983931459 ,Email:chenheng ...
最新文章
- C++编程语言之Lambda函数与表达式
- 代码单元测试工具:gmock
- Windows 8.1 新增控件之 Hyperlink
- auto.js停止所有线程_Java多线程编程基础知识 概念介绍,以及线程状态
- 【报告分享】2019年中国互联网企业战投发展白皮书.pdf(附154页pdf下载链接)...
- Atitit.导出excel报表的设计与实现java .net php 总结
- 放弃幻想,全面拥抱Transformer:自然语言处理三大特征抽取器(CNN/RNN/TF)比较
- Linux下二维码生成工具:QRencode
- docker安装和基本命令
- 关于字符串中length与length()的区别
- 如何把一篇Word文档里的所有换行符去掉?
- 网络爬虫-爬取有效机构查询网(CNAS)全量数据
- java对银行卡号、手机号码、身份证号码进行脱敏
- JS可选链操作符 (?.)
- 算法和设计模式(面经)
- 甘肃省陇南市谷歌卫星地图下载
- 一、服务端渲染技术NUXT
- ESXI 系统密码登录失败登录不上
- 优思学院|浅谈六西格玛培训
- DJBCTF2021-WEB-虎山行
热门文章
- 怎样将收藏的网址导入到搜狗账号中
- 有10名学生,每个学生的数据要求包括学号、姓名。3门课的成成绩,从键盘输入10个学生数据,要求打印出3门课总平均成绩以及最高分学生的数据(包括学号、姓名、三门课成绩、平均分数)。C++。
- w10计算机怎么恢复出厂设置路由器,win10无线路由器设置步骤图_win10重置路由器后怎么设置...
- V-SLAM重读(3):SVO代码阅读和调试修改
- 京东金融APP被曝侵犯隐私
- fatal: bad boolean config value ‘“false”‘ for ‘http.sslverify
- Java多线程socket网络协议传输
- com.baomidou.mybatisplus.core.exceptions.MyBatisPlusException: java.net.UnknownHostException
- Hibernate 参数查询
- 自制操作系统日志——第二十五天