一、设计思路
需要在 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 实现流水灯,要经过以下步骤:
时钟配置 输入输出模式设置 最大速率设置 烧录程序 运行
二、寄存器地址和参数
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位变为0010 GPIOA->ODR|=1<<5; //设置PA5初始灯为灭 GPIOB_CRH&=0xFF0FFFFF; //设置位清零 GPIOB_CRH|=0x00000020; //PB9推挽输出,把第7、6、5、4变为0010 GPIOB->ODR|=0x1<<9; //设置初始灯为灭 GPIOC_CRH&=0xFF0FFFFF; //设置位清零 GPIOC_CRH|=0x02000000; //PC14推挽输出,把第27、26、25、24变为0010 GPIOC->ODR|=0x1<<14; //设置初始灯为灭
-
-
三、代码实现
新建LED文件夹 —> 点击 Project 下的 New uVision Project —> 输入文件名 LED
选择 STM32F103C8
将启动文件拷贝到 LED 工程文件夹下:
点击 Target1→Source Group1→双击→设置打开文件类型为 Asm Source file→选择 startup_stm32f10x_md.s→点击 Add,如下图所示:
在界面左侧的 Project 栏,打开 Target1,鼠标右键单击 Source Group1, 选择 Add New Item to Group ‘Source Group 1’…添加main.c文件
//--------------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_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 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位变为0010 GPIOB_CRH&=0xFF0FFFFF; //设置位清零 GPIOB_CRH|=0x00000020; //PB9推挽输出,把第7、6、5、4变为0010 GPIOC_CRH&=0xFF0FFFFF; //设置位清零 GPIOC_CRH|=0x02000000; //PC14推挽输出,把第27、26、25、24变为0010 GPIOA_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); } }
打开魔术棒,如下图所示勾选 Create HEX File
硬件连接
实验结果