基于标准外设库的LED流水灯
用标准外设库方式使用某个端口GPIOx端口管脚控制几个LED灯,轮流闪烁,间隔时长1秒
创建工程文件
下载标准库
链接: [https://www.st.com/en/embedded-software/stm32-standard-peripheral-libraries.html]
点击F1
点击Select version,选取3.6.0版本
点击ACCEPT,开始下载,然后解压,打开文件夹
创建一个新文件加,并在里面创建文件夹并命名
将对应的文件复制粘贴进新创建的文件夹
CMSIS->start:
Libraries,包含两个文件夹内容ins和src:
User,其中main.c文件由自己创建:
Doc中创建一个文本项目并命名:
Project用于存放Keil中建立的项目
在Keil中新建工程
打开Keil,选择New uVision Project
选择刚刚创建的文件夹中所创立的Project文件夹
选择STM32F103C8系列单片机
打开Project文件夹,接着,将工程模板的文件(User,Start,Library)拷贝到LED文件夹下面
接着,在Keil种新增文件组
依次对应命名
将LED文件夹下的文件分布添加到相应的文件夹下面
接着,点击魔术棒,点击C++ -> include path 添加文件路径(非常重要)
点击Includ Paths右边的省略号,点击New(Insert),点击省略号,选择前面拷贝过来的三个文件夹,Librarise,User,start
点击OK,保存即可
程序实现
创建main.c函数,保存至先前所创文件夹Project中,代码如下:
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001
Delay_ms(1000);
GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010
Delay_ms(1000);
GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100
Delay_ms(1000);
GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000
Delay_ms(1000);
GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000
Delay_ms(1000);
GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000
Delay_ms(1000);
GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000
Delay_ms(1000);
GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000
Delay_ms(1000);
//GPIO_Write(GPIOA, ~0x0010); //0000 0000 0000 1000
//Delay_ms(2000);
}
}
创建delay.c和delay.h文件,保存至先前所创Project文件夹中,并共用一个文件夹delay
代码如下:
delay.c:
#include "stm32f10x.h"
//Delay.c
/**
* @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);
}
}
delay.h:
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f10x.h" // Device header
//Delay.h
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
#endif
将三个文件加入Source Group1
保存编译
可见,程序通过了Keil的编译,0错误,0警告。
烧录进单片机
实物按照示意图连接
在Keil中点击Download按钮(在此之前应当确保实物连接正确并且已经正确下载安装正确的驱动)
结果如下:
在这里插入图片描述
LED灯的亮/灭周期是通过软件循环延时完成的,其准确周期大致是多少
修改debug,按照图片进行修改
点击Debug进行调试
选择示波器
选择想要查看的引脚
显示方法改为bit显示,设置好之后,逻辑分析仪左侧会出现刚才设置的三个IO口,点击运行,执行一段时间后,点击停止按钮查看波形,把光标移动到逻辑分析仪显示波形的区域,上下滚动滑轮,就可以放大和缩小波形,波形如下:
分析:
可以直观地计算波形的宽度:移动光标的位置到某一个点,单击鼠标左键就会把这个点设置为起始点,然后移动光标到另一个位置就可以看到很多的信息,包括时间还有两点之间的时间差,也就是宽度。
观察下图每次变化的时间,可知没隔约1秒波形变化,每次都是两个高电平,一个低电平,对应一个灯亮,两个灯灭,可知时序正确,高低电平转换周期实际约1s,与预想的一致。