题目要求:假设你手中已有 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED,并搭建了电路,分别GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。

文章目录

  • 一、程序设计
    • (一)配置时钟效能
    • (二)配置为通用输出
  • 二、C语言 寄存器方式实现编程
    • (一)启动文件
    • (二)创建项目
    • (三)代码编写
    • (四)修改参数
    • (五)编译调试
    • (六)波形图观察
  • 三、安装STM32CubeMX软件+HAL库实现编程
    • (一)安装JRE、STM32CubeMX、HAL库
    • (二)完成初始化实现编程
    • (三)观察GPIO端口的输出波形
  • 四、总结
  • 五、参考文献

一、程序设计

stm32点灯是通过使能外设GPIO时钟,发出指令给外设GPIO,外设GPIO收到指令后,着手配置自己的寄存器,然后给IO口模式,从而实现各种功能。其过程大致如下:
CPU给指令→GPIO收到指令→配置内部寄存器→配置IO口模式→控制LED灯亮灭

(一)配置时钟效能

因为默认的时钟都是关闭的,所以在配置STM32之前必须先配置时钟。
时钟控制叫做RCC,是属于AHB总线的,我们使用的GPIOA/B/C端口都是属于APB2。

以GPIOA口为例,GPIO端口A的地址从0x4001 0800开始,从手册中可以得知复位和时钟控制RCC的地址从0x4002 1000开始,再找到APB2的外设时钟使能寄存器,可以看出其偏移地址为0x18,所以APB2的地址就是0x4002 1018。
根据手册可以知道IO端口B时钟使能是RCC_APB2ENR的位2,将RCC_APB2ENR位的2赋值为1,就能开启GPIOA时钟

#define RCC_AP2ENR ((unsigned volatile int)0x40021018)
RCC_AP2ENR|=1<<2; //APB2-GPIOA外设时钟使能

(二)配置为通用输出

由于STM32的每个IO端口都需要4个位来配置,所以一个32位的寄存器最大只能配置8个IO端口。STM32中,用端口配置低寄存器(GPIOx_CRL)来配置引脚Px0-Px7,用端口配置高寄存器(GPIOx_CRH)来配置引脚Px8-Px15。
以本次实验用到的PA5为例,使用的寄存器为GPIOA_CRL。
如下图所示,偏移地址为0x00,意思是在基地址的基础上再加0x00,所以对于GPIOA来说就是0x4001 0800。配置PA5需要的寄存器是低位的寄存器GPIOA_CRL,其地址是0x4001 0800,找到需要操作的寄存器后,将其配置为通用输出。
将LED灯点亮需要输出低电平,所以我们需要找到端口输出数据寄存器,将第5位输出为0。(此处中文版端口输出数据寄存器地址偏移为0Ch,而英文版为0x0C

#define GPIOA_CRL * ((unsigned volatile int*)0x40010800)
#define GPIOA_ODR * ((unsigned volatile int*)0x4001080C)
GPIOA_CRL&=0xFF0FFFFF; //设置位清零
GPIOA_CRL|=0X00200000; //PA5推挽输出
GPIOA_ODR|=1<<5; //设置PA5初始灯为灭




GPIOA的基本配置如上,其它口的配置可查询手册如上即可,再加上延迟函数即可实现流水灯。

二、C语言 寄存器方式实现编程

(一)启动文件

1.启动文件简介

启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:

1、初始化堆栈指针SP=_initial_sp
2、初始化PC 指针=Reset_Handler
3、初始化中断向量表
4、配置系统时钟
5、调用C 库函数_main 初始化用户堆栈,从而最终调用main 函数去到C 的世界

2.启动文件的选择

ST提供的3个启动文件,分别适用于不同容量的STM32芯片。
这三个文件为:
startup_stm32f10x_ld.s
startup_stm32f10x_md.s
startup_stm32f10x_hd.s
其中,ld.s适用于小容量 产品;md.s适用于中等容量产品;hd适用于大容量产品;
这里的容量是指FLASH的大小判断方法如下:
小容量:FLASH≤32K
中容量:64K≤FLASH≤128K
大容量:256K≤FLASH
所以,大家需要根据自己所用的STM32芯片选择不同的.s文件。
此处查阅《STM32F103中文教程及参考手册》可知,C8T6的Flash容量为128K,属于中容量,因此这里采用 startup_stm32f10x_md.s作为启动文件。

(二)创建项目

1.打开Keil,创建项目:

2.选择STM32F103C8开发板,点击"OK":

3.右键点击Source Group1,然后选中Add New item to ‘Group…’,添加"C File (.c)"文件Text1:

5.添加启动文件

(三)代码编写

//--------------APB2使能时钟寄存器------------------------
#define RCC_AP2ENR  *((unsigned volatile int*)0x40021018)//----------------GPIOA配置寄存器 ------------------------
#define GPIOA_CRL   *((unsigned volatile int*)0x40010800)
#define   GPIOA_ODR *((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 ------------------------
#define GPIOB_CRH   *((unsigned volatile int*)0x40010C04)
#define   GPIOB_ODR *((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH   *((unsigned volatile int*)0x40011004)
#define   GPIOC_ODR *((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_ODR=0x0<<5;       //PA5低电平GPIOB_ODR=0x1<<9;       //PB9高电平GPIOC_ODR=0x1<<14;      //PC14高电平
}
void B_LED_LIGHT(){GPIOA_ODR=0x1<<5;       //PA5高电平GPIOB_ODR=0x0<<9;       //PB9低电平GPIOC_ODR=0x1<<14;      //PC14高电平
}
void C_LED_LIGHT(){GPIOA_ODR=0x1<<5;       //PA5高电平GPIOB_ODR=0x1<<9;       //PB9高电平GPIOC_ODR=0x0<<14;      //PC14低电平
}
//------------------------主函数--------------------------
int main()
{int j=100;RCC_AP2ENR|=1<<2;            //APB2-GPIOA外设时钟使能RCC_AP2ENR|=1<<3;         //APB2-GPIOB外设时钟使能RCC_AP2ENR|=1<<4;           //APB2-GPIOC外设时钟使能//这两行代码可以合为 RCC_AP2ENR|=1<<3|1<<4;GPIOA_CRL&=0xFF0FFFFF;       //设置位 清零GPIOA_CRL|=0X00200000;      //PA5推挽输出GPIOA_ODR|=1<<5;           //设置PA5初始灯为灭GPIOB_CRH&=0xFFFFFF0F;      //设置位 清零GPIOB_CRH|=0x00000020;      //PB9推挽输出GPIOB_ODR|=0x1<<9;         //设置初始灯为灭GPIOC_CRH&=0xF0FFFFFF;     //设置位 清零GPIOC_CRH|=0x02000000;      //PC14推挽输出GPIOC_ODR|=0x1<<14;           //设置初始灯为灭while(j){    A_LED_LIGHT(); Delay_ms(1000000);B_LED_LIGHT();Delay_ms(1000000);C_LED_LIGHT();Delay_ms(1000000);}
}
void SystemInit(){}

(四)修改参数

1.生成HEX文件,运行程序时生成的相关的hex文件用于烧录到开发板上

2.改为相关芯片

(五)编译调试

1.进行编译时出现了以下错误:

出现该错误的原因是因为工程中包含了不止一个启动文件导致的。
这时需要在工程环境里找到Startup的驱动,将该驱动的去掉,具体步骤如下图所示:


修改后重新编译即可:
2.调试时出现以下问题:


解决方法如下:



重新调试即可:

(六)波形图观察

1.在上述步骤调试过程中,点击下图图标后,点击Logic Analyzer

2.添加要观察的引脚,Display Type需要修改为Bit,输入引脚有三种方法,以PA5口为例:
①观测PA5口输入(PORTA&0x00000020)>>5;
②直接输入PORTA.5回车即可得到上述格式;
③输入PORTA回车后,点击Current Logic Analyzer Signals后在Shift Right中输入5。

3.相关设置

4.运行程序,观察波形图


引脚为低电平的灯亮,高电平的不亮。根据上面两个图可以观察到,PB9端口的灯在1.125159秒开始亮,在2.250163秒的时候熄灭,LED灯闪烁周期约为1秒。

三、安装STM32CubeMX软件+HAL库实现编程

(一)安装JRE、STM32CubeMX、HAL库

1.安装JRE
由于STM32CubeMX软件是基于JAVA环境运行的,所以需要安装JRE(Java Runtime Environment)才能使用,安装链接如下:
https://www.java.com/en/download/manual.jsp

点击安装:

安装完成点击关闭:

2.安装STM32CubeMX
下载地址(官网中文):
https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-configurators-and-code-generators/stm32cubemx.html#get-software

选择版本进行下载(需要提供邮箱账号,根据邮件的网址进行下载):


点击“NEXT”:

勾选“I accept the……”然后点击“NEXT”:

勾选"I have read ……",点击“NEXT”:

点击“NEXT”:

点击“Done":

3.安装HAL库

①打开STM32CubeMX.exe

②点击"Help"打开“Manage embedded software packages"(打开以后未出现安第三步骤的内容时,点击“Refresh”等待即可):

③根据持有的芯片类型选择对应芯片类型、对应固件类型版本,然后点击"Install"等待即可:

(二)完成初始化实现编程

1.在STM32CubeMX中新建项目

2.在Commercial Part Number中选择芯片类型,然后点击 Start Project,具体步骤如下所示:

3.点击System Core,进入SYS,在Debug下选择serial wire:

4.配置时钟,在Clock Configuration中选中PLLCLK

进入RCC中,在HSE中设置为Crystal/…

5.接下来就是点击相应的引脚设置输出寄存器,即output那一项,一共选择3个,为PA5、PB9、PC14


6.点击project manager,配置好自己的路径(注意:不要出现中文和空格否则后续步骤中将出现报错,如第七步)和项目名,然后IDE改为MDK-ARM

7.进入code generate界面,选择初始化.c/.h文件,然后点击generate code

在点击generate code后出现以下报错,原因是因为上述步骤中路径中出现了中文(空格也不行),重新修改路径即可


此处直接修改路径但未成功,因此重新操作上述步骤,最终成功,点击Open Project,然后就会进入KEIL

8.添加代码,代替在main.c文件中主函数内容:

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);//延时1s
HAL_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);//延时1s
HAL_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端口的输出波形

1.在Target界面中选择正确的晶振大小,如果选择错误,则波形错误,时间不准确

2.Debug页设置:

3.编译

4.调试

5.观察GPIO端口的输出波形(操作可参考本文上述寄存器实现编程的波形图观察步骤)

引脚为低电平时灯亮,高电平时灯不亮,上图以端口PA5为例,可以看出LED灯闪烁周期为1秒

四、总结

对比寄存器方式实现流水灯和STM32CubeMX+KEIL+HAL库实现流水灯的代码编写部分,可以明显看出后者代码编写的少一点,运用后者更容易实现流水灯仿真。运用STM32CubeMX+KEIL+HAL库能自动生成代码,只需要加入主函数代码即可,能够有效减少代码编写的烦恼。

五、参考文献

http://t.csdn.cn/rBbz4
https://blog.csdn.net/weixin_43778388/article/details/122136509
https://blog.csdn.net/Hxm1998/article/details/113066766
https://blog.csdn.net/darkchipman0/article/details/115455332
http://t.csdn.cn/SLkcJ

【嵌入式04.2】STM32F103C8T6的简易流水灯仿真(寄存器实现+STM32CubeMX实现)相关推荐

  1. 最小系统开发板——利用STM32F103C8T6实现LED流水灯

    WeChat:[嵌入式工程师成长日记] https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484101&idx=3&a ...

  2. [AT89C51 ]用汇编语言实现流水灯仿真(含keil与Proteus)

    前言:笔者发文主要是为了记录笔者单片机学习课程,可能实用性不多,大佬看着玩就行. 关键词:51单片机:AT89C51:流水灯仿真:初学 要求:使用AT89C51实现流水灯,使用汇编语言. 思路:用51 ...

  3. 基于STM32单片机流水灯仿真与程序设计

    STM32单片机流水灯仿真与程序设计 摘要 本次程序设计和仿真是基于Proteus和keil的环境对STM32F103系列单片机进行流水灯设计,通过配置STM32的GPIO工作模式,实现LED的点亮和 ...

  4. 【STM32 嵌入式课程实验】实验二 流水灯控制

    实验二 流水灯控制 2.1 系统功能 使用STM32板载的八个LED灯,实现流水灯功能. 2.2系统组成 由STM32开发板及板上的LED灯组成,STM32为STM32F103RB芯片的NANO版本, ...

  5. 【原创】基于ARM的流水灯仿真示例

    本设计使用的仿真工具是Proteus 7.4,IDE是ADS 1.2,芯片是LPC2134 在Proteus中的电路图如下图所示: 本设计使用的是周立功的LPC2131的工程模板.LPC2131的RA ...

  6. 基于51单片机的简易交通灯仿真代码讲解

    J028 51单片机简易交通灯易懂版_仿真+代码+报告讲解 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 目录标题 工作状态 仿真图 程序 倒计时的产生 红黄 ...

  7. c语言流水灯仿真程序设计框图,基于单片机c语言控制的流水灯程序设计及prtes仿真图.docx...

    基于单片机c语言控制的流水灯程序设计及prtes仿真图 89c51与8个发光二极管相连流水控制 一.不同花样的控制源程序代码: /*#include #define uchar unsigned ch ...

  8. 【C51单片机】流水灯(仿真)

    1.流水灯功能 所谓流水灯就是8个发光二极管(LED)轮流点亮,周而复始,实现多花样流水灯效果,如:8个发光二极管循环点亮(第①号灯亮.第②号灯亮--第⑧号灯亮,第①号灯亮.第②号灯亮--第⑧号灯亮, ...

  9. 单片机流水灯仿真实验

    一.首先先下载proteus8 (其他的版本也可以) 然后打开proteus: 然后点击funish即可出现一下图片内容: 二.拖出元器件 并且将元器件摆放完整 然后打开keil软件 将一下代码生成H ...

最新文章

  1. 关于Oracle中in,exists 与 not in, not exists
  2. ASP.NET CORE 入门教程(附源码)
  3. 【Java 虚拟机原理】Class 字节码二进制文件分析 六 ( 属性类型 | Code 属性 | 属性名称索引 | 属性长度 | 操作数栈最大深度 | 局部变量存储空间 | 字节码长度 )
  4. sqlserver中GUID的默认值设置
  5. php网站404页面302,404页面该怎么做?
  6. 集合习题之列出有限集合所有子集
  7. Spring Boot退出代码–创建自定义退出代码
  8. python 无头浏览器_Python对Selenium调用浏览器进行封装包括启用无头浏览器,及对应的浏览器配置文件...
  9. 主题列表,有时间整理成博客
  10. python脚本用类编写_跟老齐学Python之编写类之二方法
  11. Java练习 SDUT-2561_九九乘法表
  12. 天天生鲜项目需求分析——基于Django框架的天天生鲜电商网站项目系列博客(一)...
  13. 解决VS2015社区版无法下载许可证的问题
  14. 计算机视觉和模式识别领域企业论坛,第三届中国模式识别与计算机视觉大会(PRCV 2020)圆满举办...
  15. 卫星导航之如何画出常见的图形世界地图、多路径、天空图等
  16. (完美可行)小米设备一键激活XPOSED框架方法
  17. 【每日早报】2019/12/31
  18. 详解python中readlines函数的参数hint
  19. [ 物联网篇 ] 02 - Yocto Project (YP)快速入门
  20. APP页面的四种类型,你都知道吗?

热门文章

  1. This primary key of “id“ is primitive !不建议如此请使用包装类 in Class
  2. python星星万花筒_少儿编程分享:码趣君教你用Python编写推星星游戏(完)
  3. Java各中依赖包介绍
  4. 问题 D: 扑克牌排序(结构体)
  5. Drools 规则文件语法概述
  6. k-均值(k-means)及Matlab实现
  7. 关于吉他5种指型Mi-La-Re-Sol-Ti
  8. ch340t电路_ch340g电路图5v和3.3v供电电路
  9. 三态门的组成及工作原理
  10. mybatis日志配置