目录
- 1.Readme文件介绍
- 2.keil5一些配置
- 3.函数封装
- 4.粗略的延时
-
- [4.1 us调试](#4.1 us调试)
- [4.2 ms调试](#4.2 ms调试)
- [4.3 s调试](#4.3 s调试)
- 5.C99选项问题
- 6.代码程序
- 7.实验现象
1.Readme文件介绍
首先先建立一个记事本,命名readme,用来描述我们的硬件信息,功能介绍,引脚分配等等一些信息情况。
/***************************************************************************************************************/
【】程序介绍
-工程名称 :点亮LED灯之标准库写法版
-实验平台 :野火 STM32FC8T6-STM开发板
【 !】功能介绍:
控制GPIO引脚输出高低电平控制LED灯的亮灭,实现点灯的效果
【 !】实验操作:
1.编译并下载程序到开发板即可观察现象;
2.可以观察红、绿、蓝灯依次点亮然后再一起闪灭。
/****************************************************************************************************************/
【*】引脚分配
LED_R->LED1->PA1 核心板板载LED灯低电平亮
LED_G->LED2->PA2 核心板板载LED灯低电平亮
LED_B->LED3->PA3 核心板板载LED灯低电平亮
/****************************************************************************************************************/
【*】程序描述:
<main.c>
1.初始化LED和KEY对应的GPIO,初始化LED和KEY端口
2.控制LED的亮灭
/****************************************************************************************************************/

2.keil5一些配置

--locale=english
核心作用是强制指定编译器的区域/语言环境为英文,解决中文系统下的编译异常问题。
3.函数封装
我们将一些初始化配置,封装一个函数里面去
我们定义一个函数:void LED_GPIO_Config(void)
命名采用驼峰命名法,高低高,
LED --- 灯
GPIO --- 端口
Config ---- 配置

将这框着的部分都是用来配置端口的准备工作,单独用一个函数封装起来
c
//基础配置
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA 端口时钟
GPIO_SetBits(GPIOA, GPIO_Pin_1); //设置PA1端口初始化1 让LED灭
GPIO_SetBits(GPIOA, GPIO_Pin_2); //设置PA2端口初始化1 让LED灭
GPIO_SetBits(GPIOA, GPIO_Pin_3); //设置PA3端口初始化1 让LED灭
// 配置引脚:选择GPIOA的Pin1
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
// 配置输出速度:50MHz
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置引脚:选择GPIOA的Pin2
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
// 配置输出速度:50MHz
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
//GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置引脚:选择GPIOA的Pin3
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
// 配置输出速度:50MHz
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
//GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}

吧准备工作全部封装在函数里面,并且函数写在main下面,我们在main上面加一个函数的声明,在main里面去调用该函数。
开灯/关灯函数封装
原先我们调用函数
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
用来将指定的IO口位置进行,置0用来开灯
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
用来将指定的IO口位置进行,置1用来关灯
现在我们分别用两个函数单独吧开灯和关灯进行封装起来
开灯
void LED_GPIO_ON(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
关灯
void LED_GPIO_OFF(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

c
//开灯
void LED_GPIO_ON(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_ResetBits(GPIOx, GPIO_Pin);
}
//关灯
void LED_GPIO_OFF(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_SetBits(GPIOx, GPIO_Pin);
}

在main上面进行函数声明,以及在main里面进行函数调用,从而执行开灯和关灯的事情。
代码:
c
/**
******************************************************************************
* @file main.c
* @author 作者
* @version v1.0
* @date 2026.4.3
* @brief 点亮LED灯标准库写法
******************************************************************************
* @attention
*
* 版权声明
*
******************************************************************************
*/
#include "stm32f10x.h"
void LED_GPIO_Config(void);
void LED_GPIO_ON(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void LED_GPIO_OFF(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
int main (void)
{
LED_GPIO_Config();
while(1)
{
//开灯
LED_GPIO_ON(GPIOA, GPIO_Pin_1);
LED_GPIO_ON(GPIOA, GPIO_Pin_2);
LED_GPIO_ON(GPIOA, GPIO_Pin_3);
//关灯
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
}
}
//基础配置
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA 端口时钟
GPIO_SetBits(GPIOA, GPIO_Pin_1); //设置PA1端口初始化1 让LED灭
GPIO_SetBits(GPIOA, GPIO_Pin_2); //设置PA2端口初始化1 让LED灭
GPIO_SetBits(GPIOA, GPIO_Pin_3); //设置PA3端口初始化1 让LED灭
// 配置引脚:选择GPIOA的Pin1
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
// 配置输出速度:50MHz
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置引脚:选择GPIOA的Pin2
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
// 配置输出速度:50MHz
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
//GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置引脚:选择GPIOA的Pin3
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
// 配置输出速度:50MHz
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
//GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
//开灯
void LED_GPIO_ON(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_ResetBits(GPIOx, GPIO_Pin);
}
//关灯
void LED_GPIO_OFF(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_SetBits(GPIOx, GPIO_Pin);
}
4.粗略的延时
c
void Rough_Delay(__IO uint32_t ncount)
{
for (uint32_t i = 0; i < ncount; i++)
{
__nop();
}
}
c
int main (void)
{
LED_GPIO_Config();
while(1)
{
//开灯
LED_GPIO_ON(GPIOA, GPIO_Pin_1);
LED_GPIO_ON(GPIOA, GPIO_Pin_2);
LED_GPIO_ON(GPIOA, GPIO_Pin_3);
Rough_Delay(1);
//关灯
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
Rough_Delay(1);
}
}
程序这里用__IO类型意思是:
让编译器不会觉得空循环语句不会被编译器删除,保证它会执行
如果不加__IO这个语句,编译器可能觉得,我自己空循环n次,觉得这个不是很重要的语句,导致可能不执行,但是我想要通过for循环自己循环次数达到延时效果,必须让编译器执行,所以需要加一个__IO类型,告诉编译器必须执行觉得没用的for循环。

通过Debug调试在延时上面一行语句执行的时间是0.00135200s,起始的时间

当我执行完成中间nop指令的时候,跳到下一行,当前的时间是0.00135950,然后用0.00135950 - 0.00135200得到0.0000075s相当于7.5us
4.1 us调试
c
void Rough_Delay(__IO uint32_t ncount)
{
for (uint32_t i = 0; i < ncount; i++)
{
__nop();
}
}
void Rough_Delay_Us(__IO uint32_t ncount)
{
Rough_Delay(ncount);
}
c
int main (void)
{
LED_GPIO_Config();
while(1)
{
//开灯
LED_GPIO_ON(GPIOA, GPIO_Pin_1);
LED_GPIO_ON(GPIOA, GPIO_Pin_2);
LED_GPIO_ON(GPIOA, GPIO_Pin_3);
Rough_Delay_Us(1);
//关灯
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
Rough_Delay_Us(1);
}
}

起始时间:0.00146500s

终止时间是0.00147460s
0.00146500s - 0.00147460s得到0.0000096s,大概就是9.6us,也就是说我在main函数那里调用us函数,1个us,大概执行的时间是9.6us
如果我设置100

起始的时间是0.00138380s

终止的时间是0.00148240s - 0.00138380 = 0.0000986s,相当于98.6us
相对而言比较准确
4.2 ms调试
c
void Rough_Delay_Ms(__IO uint32_t time)
{
Rough_Delay(time * 1000);
}
int main (void)
{
LED_GPIO_Config();
while(1)
{
//开灯
LED_GPIO_ON(GPIOA, GPIO_Pin_1);
LED_GPIO_ON(GPIOA, GPIO_Pin_2);
LED_GPIO_ON(GPIOA, GPIO_Pin_3);
Rough_Delay_Ms(1);
//关灯
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
Rough_Delay_Ms(1);
}
}
1ms测试

起始时间0.00140340s

终止时间:0.0023122s
0.0023122s - 0.00140340s = 0.0009088s,相当于0.90ms,接近1ms,相对准确
100ms测试

起始时间:0.00137160s

终止时间:0.0913804s
0.0913804s - 0.00137160s = 0.0900088s,相当于90ms,接近100ms,相对准确
4.3 s调试
c
//s
void Rough_Delay_S(__IO uint32_t time)
{
Rough_Delay(time * 1000 * 1000);
}
int main (void)
{
LED_GPIO_Config();
while(1)
{
//开灯
LED_GPIO_ON(GPIOA, GPIO_Pin_1);
LED_GPIO_ON(GPIOA, GPIO_Pin_2);
LED_GPIO_ON(GPIOA, GPIO_Pin_3);
Rough_Delay_S(1);
//关灯
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
Rough_Delay_S(1);
}
}
1s测试

起始时间:0.00136840s

终止时间:0.9013773s
0.9013773s - 0.00136840s = 0.9000089s,相当于0.9s,接近于1s,相对准确
100s测试

起始时间:0.00136180s

终止时间:90.0013707s
90.0013707s - 0.00136180s = 90.0000089s,相当于90s,接近100s,相对准确。
最终我们写了3个延时的函数,分别是us,ms,s
c
void Rough_Delay(__IO uint32_t ncount)
{
for (uint32_t i = 0; i < ncount; i++)
{
__nop();
}
}
//us
void Rough_Delay_Us(__IO uint32_t time)
{
Rough_Delay(time);
}
//ms
void Rough_Delay_Ms(__IO uint32_t time)
{
Rough_Delay(time * 1000);
}
//s
void Rough_Delay_S(__IO uint32_t time)
{
Rough_Delay(time * 1000 * 1000);
}
5.C99选项问题

点开魔术棒,在C/C++选项勾选了C99

如果我们不勾选C99,像这种代码会直接报错,如果不是C99标准,就是我们在使用变量的时候,先要定义才能使用

需要这样写,就是吧我们要使用的变量先全部定义好后,才能去使用,不能像for那一样,在里面边定义边使用。
当我们勾选C99选项后,就不会出现这些问题,就没有要求,当我们使用变量的时候不需要在最前面位置定义,也可以在语句中间去定义都可以,如果没有勾选C99,就规定,定义变量需要放在语句的最前面,不能在语句的中间去定义。
6.代码程序
c
/**
******************************************************************************
* @file main.c
* @author 作者
* @version v1.0
* @date 2026.4.3
* @brief 流水灯标准库写法
******************************************************************************
* @attention
*
* 版权声明
*
******************************************************************************
*/
#include "stm32f10x.h"
void LED_GPIO_Config(void);
void LED_GPIO_ON(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void LED_GPIO_OFF(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void Rough_Delay(__IO uint32_t ncount);
void Rough_Delay_Us(__IO uint32_t ncount);
void Rough_Delay_Ms(__IO uint32_t time);
void Rough_Delay_S(__IO uint32_t time);
int main (void)
{
uint32_t time_temp = 5000;
LED_GPIO_Config();
while(1)
{
//只开R灯
LED_GPIO_ON(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_2);
LED_GPIO_OFF(GPIOA, GPIO_Pin_3);
Rough_Delay_Ms(time_temp);
//只开G灯
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_ON(GPIOA, GPIO_Pin_2);
LED_GPIO_OFF(GPIOA, GPIO_Pin_3);
Rough_Delay_Ms(time_temp);
//只开B灯
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_2);
LED_GPIO_ON(GPIOA, GPIO_Pin_3);
Rough_Delay_Ms(time_temp);
for (uint32_t i = 0; i < 3; i++)
{
//全开
LED_GPIO_ON(GPIOA, GPIO_Pin_1);
LED_GPIO_ON(GPIOA, GPIO_Pin_2);
LED_GPIO_ON(GPIOA, GPIO_Pin_3);
Rough_Delay_Ms(time_temp);
//全关
LED_GPIO_OFF(GPIOA, GPIO_Pin_1);
LED_GPIO_OFF(GPIOA, GPIO_Pin_2);
LED_GPIO_OFF(GPIOA, GPIO_Pin_3);
Rough_Delay_Ms(time_temp);
}
}
}
//基础配置
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA 端口时钟
GPIO_SetBits(GPIOA, GPIO_Pin_1); //设置PA1端口初始化1 让LED灭
GPIO_SetBits(GPIOA, GPIO_Pin_2); //设置PA2端口初始化1 让LED灭
GPIO_SetBits(GPIOA, GPIO_Pin_3); //设置PA3端口初始化1 让LED灭
// 配置引脚:选择GPIOA的Pin1
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
// 配置输出速度:50MHz
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置引脚:选择GPIOA的Pin2
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
// 配置输出速度:50MHz
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
//GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置引脚:选择GPIOA的Pin3
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
// 配置输出速度:50MHz
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// 配置工作模式:推挽输出
//GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
//开灯
void LED_GPIO_ON(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_ResetBits(GPIOx, GPIO_Pin);
}
//关灯
void LED_GPIO_OFF(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_SetBits(GPIOx, GPIO_Pin);
}
void Rough_Delay(__IO uint32_t ncount)
{
for (uint32_t i = 0; i < ncount; i++)
{
__nop();
}
}
//us
void Rough_Delay_Us(__IO uint32_t time)
{
Rough_Delay(time);
}
//ms
void Rough_Delay_Ms(__IO uint32_t time)
{
Rough_Delay(time * 1000);
}
//s
void Rough_Delay_S(__IO uint32_t time)
{
Rough_Delay(time * 1000 * 1000);
}
7.实验现象
STM32C8T6流水灯