stm32F103C8T6标准库流水灯1——输出模式

目录

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流水灯

相关推荐
三佛科技-134163842122 小时前
FT838NB1-RT_5W(5V1A)原边反馈(5级能效)典型应用电路分析
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
森利威尔电子-4 小时前
森利威尔SL3075 脚位完全兼容 TPS54560 65V降压恒压芯片5A电流能力
单片机·嵌入式硬件·集成电路·芯片·电源芯片
蓝天居士4 小时前
INA226芯片资料(2)
嵌入式硬件·芯片资料
阿达King哥5 小时前
LIN总线
嵌入式硬件
神一样的老师5 小时前
【兆易创新GD32VW553开发板试用】 BSP 从 GitHub 下载与编译指南
单片机·github·rt-thread
VBsemi-专注于MOSFET研发定制5 小时前
协作机器人螺丝锁付系统功率MOSFET选型方案——高效、精准与安全驱动系统设计指南
单片机·安全·机器人
風清掦6 小时前
【江科大STM32学习笔记-11】SPI通信协议 - 11.2 软件SPI读写W25Q64
笔记·stm32·单片机·嵌入式硬件·学习
LCG元6 小时前
STM32实战:基于STM32F103的智能饮水机温度控制
stm32·单片机·嵌入式硬件
EVERSPIN6 小时前
MCU单片机FOC汽车水泵方案
单片机·嵌入式硬件·mcu·汽车·mcu单片机