一、使用寄存器点亮LED灯
1.建立相关文件
新建总文件夹用来存放本次工程的所有程序,然后再建CORE、HARDWARE、OBJ、FWLIB、SYSTEM、USER这六个文件夹。
1.1.建立工程 打开 Keil uVision5 软件,点击菜单栏的Project -> New uVision Project 新建一个工程,将其保存到USER文件夹中: 芯片型号选择STM32F103C8(根据自有的芯片选择 1.3.添加项目所需要的分组以及文件 右击Target 1,选择Manage Project Items… 创建Groups名字,点击右边的Add Files…按钮添加相应的文件
2.配置GPIO端口
GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。 GPIO端口的初始化设置三步骤:
时钟配置 输入输出模式设置 最大速率设置 2.1.配置时钟使能 为什么配置时钟?为了省电,默认的时钟都是关闭的。配置STM32的任何资源前,都必须首先使能时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
2.2.初始化结构体 库函数中提供了一个结构体来配置GPIO端口的输入输出模式设置 、 最大速率设置等。 定义的结构体如下:
typedef struct
{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
这个结构体中包含了初始化 GPIO 所需要的信息,包括引脚号、工作模式、输出速率。 设计这个结构体的思路是:初始化 GPIO 前,先定义一个这样的结构体变量,根据需要配置 GPIO 的模式,对这个结构体的各个成员进行赋值,然后把这个变量作为“GPIO 初始化函数”的输入参数,该函数能根据这个变量值中的内容去配置寄存器,从而实现 GPIO 的初始化。 2.3.配置输入输出模式 配置 端口位为通用推挽输出,速度为2M
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
3.主要函数
3.1.led.c函数
#include "led.h"
#include "delay.h"
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10 ;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14 ;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIO_InitStruct);
}
void LED_R_TOGGLE(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_4);
delay_ms(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
}
void LED_G_TOGGLE(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_10);
delay_ms(500);
GPIO_ResetBits(GPIOB,GPIO_Pin_10);
}
void LED_Y_TOGGLE(void)
{
GPIO_SetBits(GPIOC, GPIO_Pin_14);
delay_ms(500);
GPIO_ResetBits(GPIOC,GPIO_Pin_14);
}
3.2.delay.c函数
#include "delay.h"
#if SYSTEM_SUPPORT_OS
#include "includes.h"
#endif
static u8 fac_us=0;
static u16 fac_ms=0;
#if SYSTEM_SUPPORT_OS
#ifdef OS_CRITICAL_METHOD
#define delay_osrunning OSRunning
#define delay_ostickspersec OS_TICKS_PER_SEC
#define delay_osintnesting OSIntNesting
#endif
#ifdef CPU_CFG_CRITICAL_METHOD
#define delay_osrunning OSRunning
#define delay_ostickspersec OSCfg_TickRate_Hz
#define delay_osintnesting OSIntNestingCtr
#endif
void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD
OS_ERR err;
OSSchedLock(&err);
#else
OSSchedLock();
#endif
}
void delay_osschedunlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD
OS_ERR err;
OSSchedUnlock(&err);
#else
OSSchedUnlock();
#endif
}
void delay_ostimedly(u32 ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
OS_ERR err;
OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);
#else
OSTimeDly(ticks);
#endif
}
void SysTick_Handler(void)
{
if(delay_osrunning==1)
{
OSIntEnter();
OSTimeTick();
OSIntExit();
}
}
#endif
void delay_init()
{
#if SYSTEM_SUPPORT_OS
u32 reload;
#endif
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SystemCoreClock/8000000;
#if SYSTEM_SUPPORT_OS
reload=SystemCoreClock/8000000;
reload*=1000000/delay_ostickspersec;
fac_ms=1000/delay_ostickspersec;
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;
SysTick->LOAD=reload;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
#else
fac_ms=(u16)fac_us*1000;
#endif
}
#if SYSTEM_SUPPORT_OS
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD;
ticks=nus*fac_us;
tcnt=0;
delay_osschedlock();
told=SysTick->VAL;
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;
}
};
delay_osschedunlock();
}
void delay_ms(u16 nms)
{
if(delay_osrunning&&delay_osintnesting==0)
{
if(nms>=fac_ms)
{
delay_ostimedly(nms/fac_ms);
}
nms%=fac_ms;
}
delay_us((u32)(nms*1000));
}
#else
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us;
SysTick->VAL=0x00;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL =0X00;
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;
SysTick->VAL =0x00;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL =0X00;
}
#endif
4.电路搭建
5.用串口下载程序
其中实验用到的STM32 开发板用的 USB 转串口的驱动芯片是 CH340,要使用串口得先在电脑中安装 USB 转串口驱动—CH340 版本,下载链接详见前面。
如果 USB 转串口驱动安装成功,USB 线跟板子连接没有问题,在计算机->管理->设备管理器->端口中可识别到串口。
开始编译后的下载成功后的提示如下图,则说明HEX文件已经成功被烧录到芯片中。
6.实验结果
因技术问题不会上传视频,正在改进。
二、总结
实践操作成功让led灯闪烁,获得了巨大的成就感,在一些操作还是难以一个人实现,需要努力学习。
三、参考文献
https://blog.csdn.net/athen21/article/details/84070379 https://blog.csdn.net/weixin_42827999/article/details/101699674 https://blog.csdn.net/geek_monkey/article/details/86291377
|