基于寄存器地址&;标准外设库的LED流水灯
实验任务1
1.1设计延时函数
延时函数代码:void Delay_us(uint32_t xus) { SysTick->LOAD=72*xus; //重装定时器 SysTick->VAL=0x00; //清空计时器 SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器 While(!(SysTick->CTRL & 0x00010000)); //等待计数到0 SysTick->CTRL=0x00000004; //关闭定时器 }
//以上为核心延时代码
编写秒级延时函数代码:voidDelay_s(uint32_t xs) { while(xs--) { Delay_us(1000000); } }
1.2配置GPIO时钟
GPIOA/B/C的使能位代码实现: RCC_APB2ENR|=1<<2; RCC_APB2ENR|=1<<3; RCC_APB2ENR|=1<<4;
1.3配置引脚
GPIOx_CRL:配置引脚0-7的模式和速度
GPIOx_CRH:配置引脚8-15的模式和速度
每个引脚由寄存器中的4个位(CNFy【1:0】和MODEy【1:0】)进行控制,其中y表示引脚编号。
GPIOA/B/C的引脚配置地址分别为:
GPIOA:0X40010800+0=0x40010800
GPIOB:0X40010c00+4=0x40010c04
GPIOC:0X40011000+4=0X40011004
配置三个引脚的输出代码:`GPIOA_CRL&=0xFF0GFFFFF; //位清零
GPIOA_CRL|=0x00200000; //PA5推挽输出
GPIOB_CRH&=0xFFFFFF0F; //位清零
GPIOB_CRH|=0x00000020; //PB9推挽输出
GPIOC_CRH&=0xFF0FFFFF //位清零;
GPIOC_CRH|=0x00200000; //PC13推挽输出`
1.4配置引脚输出高低电平
GPIOA/B/C的引脚输出地址分别为:
GPIOA:0x40010800+C=0x4001080C
GPIOB:0x40010c00+C=0x40010c0C
GPIOC:0x40011000+C=0x4001100C
配置引脚代码:void LED_A_L() { GPIOA_ODR=0x0<<5; GPIOB_ODR=0x1<<9; GPIOC_ODR=0x1<<13; } void LED_B_L() { GPIOA_ODR=0x1<<5; GPIOB_ODR=0x0<<9; GPIOC_ODR=0x1<<13; } void LED_C_L() { GPIOA_ODR=0x0<<5; GPIOB_ODR=0x0<<9; GPIOC_ODR=0x0<<13; }
2.1用c语言寄存器方式编程实现代码
main代码:`#include "stm32f10x.h"
#include "Delay.h"
#define RCC_APB2ENR ((unsigned volatile int)0x40021018) //控制GPIOA/B/C的时钟开关
#define GPIOA_CRL ((unsigned volatile int)0x40010800)
#define GPIOA_ODR ((unsigned volatile int)0x4001080C) //配置GPIOA的0-7引脚
#define GPIOB_CRH ((unsigned volatile int)0x40010C04)
#define GPIOB_ODR ((unsigned volatile int)0x40010C0C) //配置GPIOB的8-15引脚
#define GPIOC_CRH ((unsigned volatile int)0x40011004)
#define GPIOC_ODR ((unsigned volatile int)0x4001100C) //配置GPIOC的8-15引脚
//函数声明
void LED_A_L(void);
void LED_B_L(void);
void LED_C_L(void);
//控制灯亮灭
void LED_A_L()
{
GPIOA_ODR=0x0<<5;
GPIOB_ODR=0x1<<9;
GPIOC_ODR=0x1<<13;
}
void LED_B_L()
{
GPIOA_ODR=0x1<<5;
GPIOB_ODR=0x0<<9;
GPIOC_ODR=0x1<<13;
}
void LED_C_L()
{
GPIOA_ODR=0x0<<5;
GPIOB_ODR=0x0<<9;
GPIOC_ODR=0x0<<13;
int main(){
RCC_APB2ENR|=1<<2;
RCC_APB2ENR|=1<<3;
RCC_APB2ENR|=1<<4;
GPIOA_CRL&=0xFF0GFFFFF; //位清零
GPIOA_CRL|=0x00200000; //PA5推挽输出
GPIOB_CRH&=0xFFFFFF0F; //位清零
GPIOB_CRH|=0x00000020; //PB9推挽输出
GPIOC_CRH&=0xFF0FFFFF //位清零;
GPIOC_CRH|=0x00200000; //PC13推挽输出
while(1)
{
LED_A_L();//LEDA亮
Delay_s(1); //延时1秒
LED_B_L(); //LEDB亮
Delay_s(1); //延时1秒
LED_C_L(); //PC13口亮
Delay(1); //延时1秒
}
}`
实验任务2
1.1先在工程总文件夹中创建User,Library和Startup三个文件夹,然后右键keil中的文件夹Source Group 1添加工程所需的这三个文件夹。
1.2分别在Library,Startup和User三个文件夹中添加必要的头文件和.c文件。
1.3在User文件夹中分别编写必要的LED.h,LED.C,main.c,Delay.h,Delay.c文件的程序。
LED.h代码:`#ifndef LED_H
define LED_H
void LED_Init(void); //声明配置GPIOA和GPIOB引脚,模式,速度的函数
void LED_Initt(void);//声明配置GPIOC引脚,模式,速度的函数
endif
LED.c的代码:
#include "stm32f10x.h" // Device header
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //配置GPIOA的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //配置GPIOB的时钟
GPIO_InitTypeDef GPIO_Initstructure; //定义GPIO端口的结构体
GPIO_Initstructure.GPIO_Mode=GPIO_Mode_Out_PP; //定义GPIO的输出形式是推挽输出
GPIO_Initstructure.GPIO_Pin=GPIO_Pin_0; //定义GPIO输出的引脚为引脚0
GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz; //定义GPIO输出速度为50MHz
GPIO_Init(GPIOA,&GPIO_Initstructure); //令GPIOA使用上述GPIO结构体定义
GPIO_Init(GPIOB,&GPIO_Initstructure); //令GPIOB使用上述GPIO结构体定义
}
void LED_Initt(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //配置GPIOC的时钟
GPIO_InitTypeDef GPIO_Initstructure; //定义GPIO端口的结构体
GPIO_Initstructure.GPIO_Mode=GPIO_Mode_Out_PP; //定义GPIO的输出形式是推挽输出
GPIO_Initstructure.GPIO_Pin=GPIO_Pin_13 | GPIO_Pin_15; //定义GPIO的输出引脚为引脚13和引脚15
GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz; //定义GPIO输出速度为50MHz
GPIO_Init(GPIOC,&GPIO_Initstructure); //令GPIOC使用上述GPIO结构体定义
}
Delay.h代码:
#ifndef __DELAY_H
define __DELAY_H
void Delay_us(uint32_t us); //声明微秒级延时器
void Delay_ms(uint32_t ms); //声明毫秒级延时器
void Delay_s(uint32_t s); //声明秒级延时器
endif
Delay.c代码:
#include "stm32f10x.h" // Device header
/**
- @brief 微秒级延时
- @param xus 延时时长,范围:0~233015
- @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD=72 *xus; //设置定时器重装值
SysTick->VAL=0x00; //清空当前计数值
SysTick->CTRL=0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
- @brief 毫秒级延时
- @param xms 延时时长,范围:0~4294967295
- @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
- @brief 秒级延时
- @param xs 延时时长,范围:0~4294967295
- @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--){
Delay_ms(1000);
}
}
main.c代码:
#include "stm32f10x.h" // Device header
include "LED.h"
include "Delay.h"
int main(void)
{
LED_Init();
LED_Initt();
while(1){
GPIO_ResetBits(GPIOC,GPIO_Pin_13); //设置PC13引脚值为0,此时LED0灯亮
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //设置A0引脚值为0,此时LED1灯亮
Delay_s(1); //延时1秒
GPIO_SetBits(GPIOA,GPIO_Pin_0); //设置A0引脚值为1,此时LED1灯灭
Delay_s(1); //延时1秒
GPIO_ResetBits(GPIOB,GPIO_Pin_0); //设置B0引脚值为0,此时LED2灯亮
Delay_s(1); //延时1秒
GPIO_SetBits(GPIOB,GPIO_Pin_0); //设置B0引脚值为1,此时LED2灯灭
Delay_s(1); //延时1秒
GPIO_ResetBits(GPIOC,GPIO_Pin_15); //设置C15引脚值为0,此时LED15灯亮
Delay_s(1); //延时1秒
GPIO_SetBits(GPIOC,GPIO_Pin_15); //设置C15引脚值为1,此时LED15灯灭
Delay_s(1); //延时1秒
}
}
`
1.4编译运行
编译成功:
2.1通过配置仿真图形设置得出仿真波形得出LED灯一轮的周期为6秒,时序状态正确,单个LED灯高低电平转换周期为5秒。