失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 嵌入式系统开发07——STM32F103C8T6下C语言寄存器方式实现LED流水灯

嵌入式系统开发07——STM32F103C8T6下C语言寄存器方式实现LED流水灯

时间:2020-08-24 13:06:19

相关推荐

嵌入式系统开发07——STM32F103C8T6下C语言寄存器方式实现LED流水灯

本文主要描述如何使用STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿黄LED搭建电路,并通过GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚来控制控制LED灯轮流闪烁。

目录

一、题目要求二、设计思路三、STM简介四、实现过程1、时钟配置2、输入输出模式设置、最大速率设置3、代码实现3.1 创建工程文件3.2 添加启动代码3.3 代码编写3.4 编译调试 4、硬件连接5、实现效果 五、总结

一、题目要求

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

1)写出程序设计思路,包括GPIOx端口的各寄存器地址和详细参数;

2)用C语言寄存器方式编程实现。

二、设计思路

需要在STM32F103C8T6上面通过初始化GPIO来实现点亮LED灯。

外设实现的功能可能是完全不同的,但是,多数情况下,我们在设计程序的时候不需要考虑外设具体如何怎样实现功能,只需要给外设接在哪里、高电平有效还是低电平有效。因此,完成题目要求的时候,只需要找到GPIOA-5、GPIOB-9、GPIOC-14的地址,然后通过GPIO的初始化,控制寄存器将片外引脚(我们称之为IO口)拉低拉高, 输出高低电平,以控制LED亮灭。

点灯是所有学单片机的人都应该学会的一项技能。C51单片机和 stm32 点灯类似。

51单片机的点灯是,通过控制寄存器将片外引脚(我们称之为IO口)拉低拉高,输出高低电平,以控制LED亮灭。

其过程:单片机给指令->控制寄存器->给IO口电平->控制LED亮灭stm32的点灯则是,通过使能外设GPIO时钟,发出指令给外设GPIO,外设GPIO收到指令后,着手配置自己的寄存器,然后给IO口模式,让其实现各种功能。其过程:CPU给指令->GPIO收到指令->配置内部寄存器->配置IO口模式(注意是模式)->控制LED亮灭

STM32开发板中包含较多寄存器,实现流水灯操作,需要对相应的引脚进行操作,对相应的引脚进行时钟配置、输入输出模式设置、最大速率设置。

于是利用 STM32F103C8T6 实现流水灯,要经过以下步骤:

时钟配置输入输出模式设置最大速率设置烧录程序运行

三、STM简介

STM32,ST 是意法半导体,M 是 Microelectronics 的缩写,32 表示32 位,合起来理解STM32就是指 ST 公司开发的 32 位微控制器。

STM32 本质上来说是一个微控制器,自带了各种常用通信接口,比如 USART、I2C、SPI 等,可连接非常多的传感器,可以控制很多的设备。现实生活中,我们接触到的很多电器产品都有 STM32 的身影,比如智能手环,微型四轴飞行器,平衡车、移动 POST 机,智能电饭锅,3D 打印机等等。

STM32 有很多系列,可以满足市场的各种需求,从内核上分有 Cortex-M0、M3、M4和 M7 这几种,每个内核又大致分为主流、高性能和低功耗。

单纯从学习的角度出发,可以选择 F1和 F4,F1代表了基础型,基于 Cortex-M3内核,主频为 72MHZ,F4 代表了高性能,基于 Cortex-M4 内核,主频 180M。

STM32F103C8T6芯片介绍

STM32F103C8T6 是一款基于ARM Cortex-M 内核 STM32系列 的 32位 的微控制器,程序存储器容量是 64KB,需要电压 2V~3.6V,工作温度为 -40°C ~ 85°C。具体参数如下:

四、实现过程

1、时钟配置

找到时钟使能寄存器映射基地址

找到端口偏移地址以及对应端口所在位置

外设时钟使能寄存器,偏移量为0x18,起始地址0x4002 1000,该寄存器地址为0x4002 1018使能对应端口时钟

查询数据手册可发现,外设时钟使能寄存器,设偏移量为0x18,起始地址0x4002 1000,该寄存器地址为0x4002 1018

#define RCC_AP2ENR*((unsigned volatile int*)0x40021018) #时钟使能寄存器

手册RCC_APB2ENR,位3是IOPBEN,名字是IO端口B时钟使能,就是我们想要的。把RCC_APB2ENR的位3赋值为1,就是开启GPIOB时钟

RCC->APB2ENR|=1<<2;//APB2-GPIOA外设时钟使能RCC->APB2ENR|=1<<3;//APB2-GPIOB外设时钟使能RCC->APB2ENR|=1<<4;//APB2-GPIOC外设时钟使能//这两行代码可以合为 RCC_APB2ENR|=1<<3|1<<4;

2、输入输出模式设置、最大速率设置

本次实验采用通用推挽输出模式,最高输出时钟频率2Mhz。分别用到GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上三个引脚。其中A4属于端口配置低寄存器偏移地址为0x00,B9、C14属于端口配置高寄存器偏移地址为0x04。

找到GPIOx端口基地址

配置对应引脚寄存器,基地址+偏移量

故而配置如下:

//----------------GPIOA配置寄存器 -----------------------#define GPIOA_CRL*((unsigned volatile int*)0x40010800)//----------------GPIOB配置寄存器 -----------------------#define GPIOB_CRH*((unsigned volatile int*)0x40010C04)//----------------GPIOC配置寄存器 -----------------------#define GPIOC_CRH*((unsigned volatile int*)0x40011004)

设置输出模式为推挽输出,输出速度为2Mhz

例:将GPIOB-9配置成推挽输出模式,且最大速度为2MHz

首先,其为GPIOB9端口,其属于端口配置高寄存器模块,则由上图可知,CNF9和MODE9位为0,其余位为F,即:GPIOB_CRH&=0xFFFFFF0F;又因其为推挽输出模式,且最大速度为2MHz,所以4位寄存器的配置就是CNF9【00】MODE9【10】,0010换成十进制数就是2,即:GPIOB_CRH|=0x00000020

GPIOA_CRL&=0xFFF0FFFF;//设置位清零GPIOA_CRL|=0X00200000;//PA5推挽输出,把第23、22、21、20位变为0010GPIOA->ODR|=1<<5;//设置PA5初始灯为灭GPIOB_CRH&=0xFF0FFFFF;//设置位清零GPIOB_CRH|=0x00000020;//PB9推挽输出,把第7、6、5、4变为0010GPIOB->ODR|=0x1<<9;//设置初始灯为灭GPIOC_CRH&=0xFF0FFFFF;//设置位清零GPIOC_CRH|=0x02000000;//PC14推挽输出,把第27、26、25、24变为0010GPIOC->ODR|=0x1<<14;//设置初始灯为灭

3、代码实现

3.1 创建工程文件

新建test2文件夹 —> 点击Project下的New uVision Project—> 输入文件名test2

因为之后实验采用STM32F103C8T6板,因此这里选择STM32F103C8

创建项目出现弹窗,勾选CORE项,点击OK完成创建

3.2 添加启动代码

要实现LED流水灯,还需要添加启动代码,以及.c 文件等。

C8T6使用的启动文件startup_stm32f10x_md.s,startup_stm32f10x_md.s是一个启动文件,里面是使用汇编语言写好的基本程序,当STM32芯片上电启动的时候,首先会执行这里的汇编程序,从而建立起来C 语言的运行环境,所以我们把这个文件称为启动文件。C8T6是中容量的arm芯片,启动文件的大致作用如下:

初始化堆栈指针 SP初始化程序计数器指针 PC设置堆、栈的大小设置中断向量表的入口地址配置外部 SRAM 作为数据存储器调用 SystemInit() 函数配置 STM32 的系统时钟设置 C 库的分支入口 "__main” (最终用来调用 main 函数)

startup_stm32f10x_hd.s文件是由ST官方提供的,该文件可以从KEIL5安装目录中找到,也可以从STV3.5库里面找到,找到该文件后吧启动文件添加到工程里面即可。不同型号的芯片以及不同编译环境使用的汇编文件是不一样的,但功能相同。

keilMDK4中只有STM32F10x.s文件。

在《STM32不完全手册里面》,所有的例程都采用了一个叫STM32F10x.s的启动文件,里面定义了STM32的堆栈大小以及各种中断的名字及入口函数名称,还有启动相关的汇编代码。

STM32F10x.s是MDK提供的启动代码,从其里面的内容看来,它只定义了3个串口,4个定时器。实际上STM32的系列产品有5个串口的型号,也只有有2个串口的型号,定时器也是,最多的有8个定时器。比如,如果你用的STM32F103ZET6,而启动文件用的是STM32F10x.s的话,你可以正常使用串口1 ~ 3的中断,而串口4和5的中断,则无法正常使用。又比如,你TIM1 ~ 4的中断可以正常使用,而5~8的,则无法使用。

所以STM32F10x.s并不能适用所有的STM32型号,这样,我们就得对不同型号的STM32,选择不同的启动文件。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

我们开发板使用的是STM32F103C8T6,FLASH容量为64K,属于中等容量产品,而STM32F10x.s刚刚好是满足中等容量型号的启动文件,所以我们使用STM32F10x.s是不会有问题的,但是更便于理解,这里还是使用startup_stm32f10x_md.s。而如果你的是小容量或者大容量的STM32,则相应的选择startup_stm32f10x_ld.sstartup_stm32f10x_hd.s即可。

按照上面的解释,最为普通的工程,STM32F10x.s文件是够用的,但是在复杂的工程中,还是建议ST库文件的几个启动文件。

这里上传这几个启动文件:

链接:/s/1tYK8A6og03rPp51ZTrVBBw

提取码:plt3

将启动文件拷贝到test2工程文件夹下:

点击Target1→Source Group1→双击→设置打开文件类型为 Asm Source file→选择 startup_stm32f10x_md.s→点击 Add,如下图所示:

3.3 代码编写

在界面左侧的Project栏,打开Target1,鼠标右键单击Source Group1, 选择Add New Item to Group ‘Source Group 1’…

添加 test2.c文件

编写代码

//--------------APB2使能时钟寄存器------------------------#define RCC_APB2ENR*((unsigned volatile int*)0x40021018)//----------------GPIOA配置寄存器 ------------------------#define GPIOA_CRL*((unsigned volatile int*)0x40010800)#defineGPIOA_ODR*((unsigned volatile int*)0x4001080C)//----------------GPIOB配置寄存器 ------------------------#define GPIOB_CRH*((unsigned volatile int*)0x40010C04)#defineGPIOB_ODR*((unsigned volatile int*)0x40010C0C)//----------------GPIOC配置寄存器 ------------------------#define GPIOC_CRH*((unsigned volatile int*)0x40011004)#defineGPIOC_ODR*((unsigned volatile int*)0x4001100C)//函数声明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<10000;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(){RCC_APB2ENR|=1<<2;//APB2-GPIOA外设时钟使能RCC_APB2ENR|=1<<3;//APB2-GPIOB外设时钟使能RCC_APB2ENR|=1<<4;//APB2-GPIOC外设时钟使能//也可以写成 RCC_APB2ENR|=1<<3|1<<4;GPIOA_CRL&=0xFFF0FFFF;//设置位清零GPIOA_CRL|=0X00200000;//PA5推挽输出,把第23、22、21、20位变为0010GPIOB_CRH&=0xFF0FFFFF;//设置位清零GPIOB_CRH|=0x00000020;//PB9推挽输出,把第7、6、5、4变为0010GPIOC_CRH&=0xFF0FFFFF;//设置位清零GPIOC_CRH|=0x02000000;//PC14推挽输出,把第27、26、25、24变为0010GPIOA_ODR |= (1<<5); GPIOB_ODR |= (1<<9);//设置灯的初始状态为灭GPIOC_ODR |= (1<<14); while(1){A_LED_LIGHT();Delay_ms(60);B_LED_LIGHT();Delay_ms(60);C_LED_LIGHT();Delay_ms(60);}}

3.4 编译调试

打开魔术棒,如下图所示勾选Create HEX File

ST-Link/v2驱动安装

链接:/s/1oazATTwP9eGdjANB4FmEng

提取码:plt3

点击.exe文件进行安装

STM32F103C8T6通过ST-Link连接到电脑USB接口上

ST-LinkC8T6之间通过杜邦线按照下图连接:

点击 魔术棒,在Debug下勾选Use:ST-Link Debugger

点击Setting,若此时 C8T6 通过St-link成功连接到了电脑上,就可以看到下图信息;点击确定-> OK,保存设置

点击编译

将程序烧录到C8T6

此时可能会弹出以下信息:

点击确定就行了

烧录成功后红灯长亮

4、硬件连接

使用杜邦线将 A5、B9、C14连接到LED的负极(短脚),将开发板的3.3V输出通过杜邦线连接到LED的正极(长脚)

5、实现效果

建议重新烧录一次,然后按一下开发板上的reset

效果如下:

C8T6实现LED流水灯

五、总结

本次主要使用STM32F103C8T6核心板,通过电路搭建实现LED灯轮流闪烁。通过本次实验进一步加深了我对GPIO寄存器的认识与运用,也让我学会了如何配置GPIO。本次实验不难,但是由于刚刚接触到GPIO的初始化以及配置,导致实验的时间拉的很长,希望通过不断学习可以提高自己的动手能力和解决问题的能力。

参考列表:

1.STM32启动文件:startup_stm32f10x_hd.s等启动文件的简单描述

2.STM32F103C8T6寄存器方式借助面包板点亮LED流水灯详解

3.stm32cubeMX使用HAL库点亮LED流水灯

4.stm32寄存器实现流水灯

5.STM32F103C8T6实现流水灯

如果觉得《嵌入式系统开发07——STM32F103C8T6下C语言寄存器方式实现LED流水灯》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。