原创:转载请标注引用地址

如何定义 led1对应于PA8  呢

:对于我一开始学习的方法::

#include "main.h"

#define led1      GPIO_Pin_8        //管脚宏定义   PA8

//=================================================================================================
//函数名称: GPIO_Configuration    
//输入参数: void
//输出参数: void
//函数功能: 所用到的GPIO的初始化
//日    期: 2017-11-13
//作    者: GXTon
//=================================================================================================

void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);     //使能PORTA时钟   
    
    //下面是用于测试的小灯的设置
    GPIO_InitStructure.GPIO_Pin = led1;                                     //PA8
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);

}

在主函数中:

void main(void)

{

//一系列的初始化

.........

.........
    GPIO_Configuration();

while(1)

{

GPIO_SetBits(GPIOA,led1);            //点亮灯

Delay_ms(1000);

GPIO_ResetBits(GPIOA,led1);       //灭掉灯

Delay_ms(1000);

}

}

/////////////////////////////////////////////////////////////////////////////////////////////////

上面的程序是经常用的,但是总感觉不太顺利,尤其是每次要换板子

,也就是对应的小灯在新的板子上换了引脚:

如把  led1==PA8  改成  led1==PB10

对应的引脚总要改三个地方::   点亮一个小灯也就需要下面三个函数,

也就是说你要移植一个程序,就要改动用到函数的每一个部分,

这根本就不是很好的程序

1: #define led1      GPIO_Pin_8        //管脚宏定义   PA8    ---->改为GPIO_Pin_10

2:void GPIO_Configuration(void)                                      ---->需要改时钟,改赋值处

3:GPIO_SetBits(GPIOA,led1);            //点亮灯                  ---->需要改为GPIO_SetBits(GPIOB,led1);

下面对这三部分进行改造,

第一部分不用define,而用结构体,,,用结构体的好处是,,可以用一个变量 struct led1,来代表很多变量,,,,因为一个结构体里面有好多元素,,,可以认为结构体是define的升级版

第二部分GPIO_Configuration(void),,要改进它,,它不在是传入void,,而是传入结构体 这样就可以和第一部分关联起来了

也许不用传入变量,直接在里面引入结构体的元素就行

第三部分GPIO_SetBits(GPIOA,led1),,也是把传入的参数:GPIOA,led1   这里是两个参数,我们就改成传入一个结构体的两个元素.

经过这样的改编,第二部分和第三部分都和第一部分的结构体扯上了关系,那么我们以后一直程序的时候,就只需要改编第一部分的

结构体就行了,,这样第二部分和第三部分就会有相应的变动传入,,大大简化了,,移植的步骤

///////////////////////////////////////////////////////////////////////////////////////////////////

也许我们可以定义一个新的函数,让它来包含所有的函数,,然后把硬件小灯这里的led1设置成为一种

结构体,,

结构体里面包含了小灯的引脚组(A或者B...)

结构体里也包含了小灯的引脚号(8引脚或者10引脚...)

结构体里可以包含引脚连接的标号(led1或者TX,,RX..CLK,,DIO)

结构体里可以包含小灯的各种动作,使用一个函数指针,指向对应函数实现的,不过没有试过(一直亮,一直灭,闪烁)

结构体里可以包含小灯在这个状态的时间(闪烁时,,,处于关闭的时间变量   处于发光的时间是变量)

////////////////////////////////////////////////////////////////////////////////////////////////

下面我试着实现以下

下面是结构体,

struct LED                                //为什么它只能在这里定义,在main.c中却是不能呢
{
    GPIO_TypeDef* GPIOx;         //引脚分组, 如A管脚或B管脚
    uint16_t GPIO_Pin;               //引脚号,   PA8里的  8   或者 PB10里的  10

uint32_t RCC_APB2Periph   //引脚挂接在哪个时钟下面
    int ON_T;
    int OFF_T;
    int TIME;
    u8 ZT;           //状态,off/on
    u8 led_enable;  //这个是防止重新进入的,因为led的处理没有必要每次都进入,只需要运行一次进入即可
    int cnt;         //这个是用来计数的,计算闪亮了多少次
    int cntt;         //这个是计数停止的界限
    u8 sjxd;         //需不需要限定时间
    
};    这个是个模具,,用它来扣蛋糕,,蛋糕的名字叫led1,led2或者led3...

对GPIO_Configuration  函数的改造

//=================================================================================================
//函数名称: GPIO_Configuration    
//输入参数: struct LED *led     //这个是一个结构体,里面包含了小灯的所有信息,,,我也在犹豫,,,要不要传进所有的信息,,,还是只传入结构体内的部分变量就好
//输出参数: void
//函数功能: 所用到的GPIO的初始化
//日    期: 2017-11-13
//作    者: GXTon
//=================================================================================================

void GPIO_Configuration(struct LED *led)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(led->RCC_APB2Periph   ,ENABLE);     //使能PORTA时钟   
    
    //下面是用于测试的小灯的设置
    GPIO_InitStructure.GPIO_Pin = led->GPIO_Pin;                                 //PA8
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(led->GPIOx,&GPIO_InitStructure);

}

对于点亮小灯的函数改造

GPIO_SetBits(led->GPIOx, led->GPIO_Pin);  //亮

当然这只是一部分,小灯不只会亮,还会灭,也能闪,,所以要改造涉及的所有函数

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

不一定要统一所有外设,,灯能亮,,但是马达还能亮吗?显然不能,,,,,外设也是分类的

我们的程序不一定要把灯和马达都搞到一个结构体里,,,可以设置两个结构体嘛

这样灯有灯的结构体,,马达有马达的结构体,,

也许会分的更细,,红灯有红灯的结构体,绿灯有绿灯的结构体,,黄灯有黄灯的结构体

编写程序前需要分类,,分好类之后按照类型创建结构体,过度的统一并不是好的事情

void LED_CL(struct LED *led,u8 ztbh,u8 sjxd, int cnt);  //处理led用于改变led状态时才去调用
void LED_ZT( struct LED *led);          //接收led结构体的状态,去执行

如何使stm32程序更好移植, 结构体相当于define的更多相关文章

  1. 结构体中使用#define定义宏

    struct  hostent {   char    *h_name;        /* official name of host */   char    **h_aliases;    /* ...

  2. 失落的C语言结构体封装艺术

    Eric S. Raymond <esr@thyrsus.com> 目录 1. 谁该阅读这篇文章 2. 我为什么写这篇文章 3.对齐要求 4.填充 5.结构体对齐及填充 6.结构体重排序 ...

  3. (转)失落的C语言结构体封装艺术

    目录1. 谁该阅读这篇文章 2. 我为什么写这篇文章 3.对齐要求 4.填充 5.结构体对齐及填充 6.结构体重排序 7.难以处理的标量的情况 8.可读性和缓存局部性 9.其他封装的技术 10.工具 ...

  4. 5、数组&字符串&结构体&共用体&枚举

    程序中内存从哪里来 三种内存来源:栈(stack).堆(heap).数据区(.date): 栈(stack) 运行自动分配.自动回收,不需要程序员手工干预: 栈内存可以反复使用: 栈反复使用后,程序不 ...

  5. C/C++编程笔记:C语言对齐问题【结构体、栈内存以及位域对齐】

    引言 考虑下面的结构体定义: 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始地址是0,则s的地址就是1,c2的地址是3,i的地址是4. 现在,我们编写一个简单的程序: 运行后输出: 为什么会这 ...

  6. .NET C#基础(5):结构体 - 高性能代码的基石

    0. 文章目的   本文面向有一定.NET C#基础知识的学习者,介绍C#中结构体定义.使用以及特点. 1. 阅读基础   了解C#基本语法   了解.NET中的栈与托管堆 2. 值类型 2.1 .N ...

  7. C语言入门(14)——结构体

    整数.字符.布尔值.浮点数这些数据类型都具有单一的值,这些可称为基本数据类型.但字符串是一个例外,它由很多字符组成,像这种由基本类型组成的数据类型称为复合数据类型,正如表达式和语句有组合规则一样,由基 ...

  8. 使用Delphi声明C++带函数的结构体实战 good

    在小组开发中,应用程序部分采用Delphi7,一些组件使用C++做.在今天将一个动态库的C++接口声明头文件转换为D7的Unit单元时,一切都很顺利,直到遇到下面这样一个另类的东西: typedef ...

  9. C语言结构体定义的几种方法

    什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类.结构体可以被声明为变量.指针或数组等,用以实现较复杂的数据 ...

随机推荐

  1. 搭建 Nginx 静态网站

    示例代码:/etc/nginx/nginx.conf user nginx;worker_processes auto;error_log /var/log/nginx/error.log;pid / ...

  2. kill&&pkill&&killall---删除执行中的程序

    命令功能: 发送指定的信号到相应进程.不指定型号将发送SIGTERM(15)终止指定进程.如果无法终止该程序可用“-KILL” 参数,其发送的信号为SIGKILL(9) ,将强制结束进程 使用ps命令 ...

  3. Flask框架简介

    Flask框架诞生于2010年,是Armin ronacher 用python语言基于Werkzeug工具箱编写的轻量级Web开发框架! Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展. ...

  4. D3.js加载csv和json数据

    1.加载数据的基本命令 D3提供了方法可以对不同的数据类型进行加载,比如d3.text(), d3.xml(), d3.json(), d3.csv(), 和d3.html(). <!DOCTY ...

  5. SQlite-数据库的访问实例(转)

    1.DBAdapter类: 1 package com.cnzcom.android.quickdial; import android.content.ContentValues; import a ...

  6. 移动mm 话费支付接入过程(ane)

    下面记录移动mm 话费支付接入的过程 1.强联网.弱联网差别.sdk是否有区分?用户体验部分由什么不同和差异? 差别在于强联网是网络通道(wifi/gprs/3g),弱联网是走短信通道,用户层面差异在 ...

  7. Ubuntu配置图形桌面LXDE和VNC、中文语言包、中文输入法

    Ubuntu配置图形桌面LXDE和VNC.中文语言包.中文输入法 http://www.lijiejie.com/ubuntu-vps-config-lxde-vnc/ LXDE是Ubuntu图形桌面 ...

  8. 3.lombok系列3:lombok的实验类特性

    转自:https://blog.csdn.net/54powerman/article/details/72516755 lombok除了已经推荐使用的基本功能,还维护了一个创新型的注解,有些功能有违 ...

  9. 前端面试题(JavaScript)

    (前端面试题大全,持续更新) 箭头函数特点?箭头函数和普通函数的区别 手写懒加载(考虑防抖和重复加载问题) 手写bind(为什么要加预参数,为什么要加new) apply, call, bind ne ...

  10. Codeforces Beta Round #24 D. Broken robot (打表找规律)

    题目链接: 点击我打开链接 题目大意: 给你 \(n,j\),再给出 \(m[0]\) 的坐标和\(a[0]-a[n-1]\) 的坐标. 让你输出 \(m[j]\) 的坐标,其中 \(m[i]\) 和 ...