CC3220学习笔记---点亮LED PinMux版

2023-12-30 20:40

本文主要是介绍CC3220学习笔记---点亮LED PinMux版,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上节课使用了driverlib API来实现了LED灯的点亮,在实际开发中,不可能这样写程序,效率太低。这时就需要把硬件的各种行为抽象出来,帮助开发人员更容易地,更符合人类思维的方式进行操作。

首先理解CC3220 SDK源码的架构,下面是目录结构:


一共这五个文件夹,展开后:


  • 【devices】目录下的是最底层驱动,它直接跟硬件打交道。ROM内存放的API就是这一块,上篇日志我们使用的就是这里的函数。
  • 【drivers】目录则是在最底层API的基础上进行包装,抽象出MCU的各种行为,方便开发人员使用。这里打个比方吧。比如接电话这个行为可分解为如下步骤:电话铃响-->接通电话-->通话-->挂电话。电话铃响、接通电话、通话、挂电话这些单独的动作组合在一起才成为“接电话”这个行为。drivers层的作用就是把devices层的单独动作组合成具体行为,供开发者使用。
  • 【boards】从文件命名来看drivers层针对的是CC32XX系列的MCU,应该就是现有的CC3220、CC3220S、CC3220SF三款。三款功能绝大部分相同,只有少数差异,那么drivers层包含的仅为这几款MCU的相同部分的功能。另外,我们知道,大部分引脚是可以复用的。每个人拿到相同的芯片做的事情不一样,从而设计的开发板并不相同,甚至天差地别。所以这时就需要boards这一层,专门针对特定的开发板,在drivers层的基础上做进一步抽象,以方便开发人员使用。所以这一层文件的命名都以开发板为前缀,它也仅针对特定开发板使用。

今天,我们使用【drivers】层库函数来实现LED灯点亮。首先得分析GPIO相关部分源码。

一、GPIO_PinConfig
首先打开【drivers】根目录下的【GPIO.h】文件,首先找到这个声明:
/*!*  @brief  GPIO pin configuration settings**  The upper 16 bits of the 32 bit PinConfig is reserved*  for pin configuration settings.**  The lower 16 bits are reserved for device-specific*  port/pin identifications*/
typedef uint32_t GPIO_PinConfig;
一个引脚的名称、分组、GPIO配置信息都被包含在了这个32位整数GPIO_PinConfig里面了。它的高16位用于存放GPIO配置信息,而低16位用于存放引脚标识。下面分别讲解:

1、引脚标识
打开 【drivers】-->【gpio】下的GPIOCC32XX.h文件,找到下述代码:
//引脚为空
#define GPIOCC32XX_EMPTY_PIN 0x0000 
//GPIO A0 port下的8个引脚
#define GPIOCC32XX_GPIO_00 0x0001 
#define GPIOCC32XX_GPIO_01 0x0002 
#define GPIOCC32XX_GPIO_02 0x0004 
#define GPIOCC32XX_GPIO_03 0x0008 
#define GPIOCC32XX_GPIO_04 0x0010 
#define GPIOCC32XX_GPIO_05 0x0020 
#define GPIOCC32XX_GPIO_06 0x0040 
#define GPIOCC32XX_GPIO_07 0x0080 
//GPIO A1 port下的8个引脚
#define GPIOCC32XX_GPIO_08 0x0101 
#define GPIOCC32XX_GPIO_09 0x0102 
#define GPIOCC32XX_GPIO_10 0x0104 
#define GPIOCC32XX_GPIO_11 0x0108 
#define GPIOCC32XX_GPIO_12 0x0110 
#define GPIOCC32XX_GPIO_13 0x0120 
#define GPIOCC32XX_GPIO_14 0x0140 
#define GPIOCC32XX_GPIO_15 0x0180 
//GPIO A2 port下的8个引脚
#define GPIOCC32XX_GPIO_16 0x0201 
#define GPIOCC32XX_GPIO_17 0x0202 
#define GPIOCC32XX_GPIO_18 0x0204 
#define GPIOCC32XX_GPIO_19 0x0208 
#define GPIOCC32XX_GPIO_20 0x0210 
#define GPIOCC32XX_GPIO_21 0x0220 
#define GPIOCC32XX_GPIO_22 0x0240 
#define GPIOCC32XX_GPIO_23 0x0280 
//GPIO A3 port下的8个引脚
#define GPIOCC32XX_GPIO_24 0x0301 
#define GPIOCC32XX_GPIO_25 0x0302 
#define GPIOCC32XX_GPIO_26 0x0304 
#define GPIOCC32XX_GPIO_27 0x0308 
#define GPIOCC32XX_GPIO_28 0x0310 
#define GPIOCC32XX_GPIO_29 0x0320 
#define GPIOCC32XX_GPIO_30 0x0340 
#define GPIOCC32XX_GPIO_31 0x0380 
可以看到32个GPIO引脚都对应有一个数字,这个数字的低8位中的每一位正好表示了这个引脚的编号。第9、10位则表示引脚所在端口。 GPIO_PinConfig的低16位存放的就是此信息。

2、GPIO配置信息
回到 【GPIO.h】文件,找到GPIO_PinConfig声明之后的代码:
/*!*  Internally used configuration bit access macros.*/
#define GPIO_CFG_IO_MASK           0x00ff0000
#define GPIO_CFG_IO_LSB            16
#define GPIO_CFG_OUT_TYPE_MASK     0x00060000
#define GPIO_CFG_OUT_TYPE_LSB      17
#define GPIO_CFG_IN_TYPE_MASK      0x00060000
#define GPIO_CFG_IN_TYPE_LSB       17
#define GPIO_CFG_OUT_STRENGTH_MASK 0x00f00000
#define GPIO_CFG_OUT_STRENGTH_LSB  20
#define GPIO_CFG_INT_MASK          0x07000000
#define GPIO_CFG_INT_LSB           24
#define GPIO_CFG_OUT_BIT           19
/*!*  \defgroup GPIO_PinConfigSettings 宏,用于配置GPIO引脚*  @{*/
/*GPIO_PinConfig 输出配置宏*/
#define GPIO_CFG_OUTPUT            (((uint32_t) 0) << GPIO_CFG_IO_LSB) /* 输出. */
#define GPIO_CFG_OUT_STD           (((uint32_t) 0) << GPIO_CFG_IO_LSB) 
#define GPIO_CFG_OUT_OD_NOPULL     (((uint32_t) 2) << GPIO_CFG_IO_LSB) /* 开漏 */
#define GPIO_CFG_OUT_OD_PU         (((uint32_t) 4) << GPIO_CFG_IO_LSB) /* 开漏/上拉 */
#define GPIO_CFG_OUT_OD_PD         (((uint32_t) 6) << GPIO_CFG_IO_LSB) /* 开漏/下拉 */#define GPIO_CFG_OUT_STR_LOW       (((uint32_t) 0) << GPIO_CFG_OUT_STRENGTH_LSB) /* 驱动强度:低 */
#define GPIO_CFG_OUT_STR_MED       (((uint32_t) 1) << GPIO_CFG_OUT_STRENGTH_LSB) /* 驱动强度:中 */
#define GPIO_CFG_OUT_STR_HIGH      (((uint32_t) 2) << GPIO_CFG_OUT_STRENGTH_LSB) /* 驱动强度:高 */#define GPIO_CFG_OUT_HIGH          (((uint32_t) 1) << GPIO_CFG_OUT_BIT) /* 输出 1 */
#define GPIO_CFG_OUT_LOW           (((uint32_t) 0) << GPIO_CFG_OUT_BIT) /* 输出 0 */
/* GPIO_PinConfig 输入配置宏*/
#define GPIO_CFG_INPUT             (((uint32_t) 1) << GPIO_CFG_IO_LSB) /* 输入 */
#define GPIO_CFG_IN_NOPULL         (((uint32_t) 1) << GPIO_CFG_IO_LSB) /* 无内部上拉/下拉 */
#define GPIO_CFG_IN_PU             (((uint32_t) 3) << GPIO_CFG_IO_LSB) /* 内部上拉 */
#define GPIO_CFG_IN_PD             (((uint32_t) 5) << GPIO_CFG_IO_LSB) /* 内部下拉 */
/* GPIO_PinConfig 中断配置宏*/
#define GPIO_CFG_IN_INT_NONE       (((uint32_t) 0) << GPIO_CFG_INT_LSB)    /* 无中断 */
#define GPIO_CFG_IN_INT_FALLING    (((uint32_t) 1) << GPIO_CFG_INT_LSB)    /* 下降沿触发 */
#define GPIO_CFG_IN_INT_RISING     (((uint32_t) 2) << GPIO_CFG_INT_LSB)    /* 上升沿触发 */
#define GPIO_CFG_IN_INT_BOTH_EDGES (((uint32_t) 3) << GPIO_CFG_INT_LSB)    /* 上升下降沿触发 */
#define GPIO_CFG_IN_INT_LOW        (((uint32_t) 4) << GPIO_CFG_INT_LSB)    /* 低电平触发 */
#define GPIO_CFG_IN_INT_HIGH       (((uint32_t) 5) << GPIO_CFG_INT_LSB)    /* 高电平触发 */
高16位存放的就是以上信息,每个位都对应有一个功能,位功能图我就不画了,了解大概原理即可。

二、GPIOCC32XX_Config
继续GPIOCC32XX.h文件:
typedef struct GPIOCC32XX_Config {GPIO_PinConfig  *pinConfigs; //引脚GPIO配置GPIO_CallbackFxn  *callbacks;uint32_t numberOfPinConfigs;uint32_t numberOfCallbacks;uint32_t intPriority;
} GPIOCC32XX_Config;
GPIOCC32XX_Config是更高一层的GPIO配置,注意加粗那一行,就是上面讲的32位引脚配置整数。这里再加上回调函数和中断优先级。

翻到GPIOCC32XX.h文件头部注释,上面有详细介绍如何使用gpio。简而言之,就是需要在Border.c文件中提供三个数据:
  1. GPIO_PinConfig数组
  2. GPIO_CallbackFxn数组
  3. GPIOCC32XX_Config结构体
这里我就不细说了,因为有神器自动生成。下面还需要介绍两个方法。

三、GPIO_init()
上面讲的三个数据提供完成后,就可以使用GPIO_init()方法对gpio进行初始化了。看看它的源码,GPIOCC32XX.c文件中:
void GPIO_init()
{unsigned int i, j;#if DebugP_ASSERT_ENABLEDinitCalled = true;
#endiffor (i = 0; i < NUM_PORTS; i++){for (j = 0; j < NUM_PINS_PER_PORT; j++){gpioCallbackInfo[i].pinIndex[j] = CALLBACK_INDEX_NOT_CONFIGURED;}}/** Configure pins and create Hwis per static array content*/for (i = 0; i < GPIOCC32XX_config.numberOfPinConfigs; i++){if (!(GPIOCC32XX_config.pinConfigs[i] & GPIO_DO_NOT_CONFIG)){GPIO_setConfig(i, GPIOCC32XX_config.pinConfigs[i]);}if (i < GPIOCC32XX_config.numberOfCallbacks){if (GPIOCC32XX_config.callbacks[i] != NULL){/* create Hwi as necessary */GPIO_setCallback(i, GPIOCC32XX_config.callbacks[i]);}}}Power_registerNotify(&powerNotifyObj,PowerCC32XX_ENTERING_LPDS | PowerCC32XX_AWAKE_LPDS,powerNotifyFxn, (uintptr_t) NULL);
}
注意加粗的GPIO_setConfig()方法,追踪下去,代码太长,我就不贴完了,这里只贴关键几句:
/* Configure the GPIO pin */
MAP_GPIODirModeSet(portBase, pinMask, direction);
MAP_PinConfigSet(pin, strength, pinType);/* Set output value */
if (direction == GPIO_DIR_MODE_OUT)
{MAP_GPIOPinWrite(portBase, pinMask,((pinConfig & GPIO_CFG_OUT_HIGH) ? 0xFF : 0));
}
加粗部分都是上篇日志我们使用过的ROM API。

四、GPIO_write()
最终点亮LED灯还得写GPIO。所以还需介绍GPIO_write()函数,还是在GPIOCC32XX.c文件中。
void GPIO_write(uint_least8_t index, unsigned int value)
{uintptr_t  key;uint32_t   output;PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfPinConfigs);DebugP_assert((GPIOCC32XX_config.pinConfigs[index] & GPIO_CFG_INPUT) ==GPIO_CFG_OUTPUT);key = HwiP_disable();/* Clear output from pinConfig */GPIOCC32XX_config.pinConfigs[index] &= ~GPIO_CFG_OUT_HIGH;if (value){output = config->pin;/* Set the pinConfig output bit to high */GPIOCC32XX_config.pinConfigs[index] |= GPIO_CFG_OUT_HIGH;}else{output = value;}MAP_GPIOPinWrite(getPortBase(config->port), config->pin, output);HwiP_restore(key);DebugP_log3("GPIO: port 0x%x, pin 0x%x wrote 0x%x",getPort(config->port), config->pin, value);
}
真正写GPIO那句代码我加粗了,上篇日志调用过。另外需要注意的是看源码可知,index参数表示的是对应gpio引脚在数组中的索引号。等下在写程序的时候这里需要格外注意。

TI Pin Mux Tool
下面来介绍一个编程神器:Pin Mux Tool,它用于配置开发板功能。根据我们所选的功能自动生成主板配置代码。安装略。

打开Pin Mux Tool,在Device栏选择CC3220SF,如下图所示:

然后点击【Start】按钮。在窗体左边【GPIO】栏点击3次【+】号,添加三个GPIO。由于我们只操作三盏灯,所以只使用三个GPIO。添加完成后效果如下图所示:

 将MyGPIO3的【GPIO Pins】改为64,并将每个GPIO的Active改为Output,效果如下图所示:

窗体右边,单击【Download File】按钮,下载CC3220SF_LAUNCHXL.c文件和CC3220SF_LAUNCHXL.h文件。

接下来打开CC3220SF_LAUNCHXL.c文件,得手动修改一下。找到

前面说了,这个顺序很重要,关系到后面的调用,把这个顺序调整一下,改为:

GPIO_PinConfig gpioPinConfigs[] =
{/* output pins with callbacks */GPIOCC32XX_GPIO_09 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,GPIOCC32XX_GPIO_10 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,GPIOCC32XX_GPIO_11 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
};

接下来打开 CC3220SF_LAUNCHXL.h文件,找到以下代码


我们看到,有两个按钮,没有我们加进去的LED灯。这里需要自己手动修改,但现在不改也不会影响到等下写的程序。

PinMux版跑马灯
终于可以开始写程序了。
1、复制 上篇日志中做好的【demo_gpio_lib】程序,粘贴为【demo_gpio_PinMux】项目。在新项目上右键选中【Add Files】菜单,将刚才生成的CC3220SF_LAUNCHXL.c文件和CC3220SF_LAUNCHXL.h文件加进项目。

2、将main_tirtos.c文件中的代码替换为:
#include <ti/drivers/GPIO.h>
#include <ti/drivers/gpio/GPIOCC32XX.h>void delay(int temp)
{int i = 0;for (i = 0; i < temp; i++);
}int main(void)
{GPIO_init();while(1){GPIO_write(2, 0); //灭绿灯GPIO_write(0, 1); //亮红灯delay(0xfffff);GPIO_write(0, 0); //灭红灯GPIO_write(1, 1); //亮黄灯delay(0xfffff);GPIO_write(1, 0); //灭黄灯GPIO_write(2, 1); //亮绿灯delay(0xfffff);}
}
Debug程序,跑马灯亮,有了PinMux神器,写程序还是挺方便的。
这里需要注意,GPIO_write()函数中的第一个参数表示gpio口在gpioPinConfigs[]数组中的索引号;第二个参数0表示灭灯,1表示亮灯。

程序是写完了,也能运行了。不过代码看上去不太有范啊!GPIO_write()函数中的两个冰冷的数字无任何意义,让人无法读懂。继续改造!

PinMux版跑马灯程序改进
1、在项目上右键选中【New】-->【File】菜单,新建一个【Board.h】文件。也可从之前导入的timerled项目中拷贝一个过来。
2、输入如下代码:
#ifndef __BOARD_H
#define __BOARD_H#ifdef __cplusplus
extern "C" {
#endif#include "CC3220SF_LAUNCHXL.h"#define LED_ON            CC3220SF_LAUNCHXL_GPIO_LED_ON
#define LED_OFF           CC3220SF_LAUNCHXL_GPIO_LED_OFF
#define RED_LED           (0)
#define YELLOW_LED        (1)
#define GREEN_LED         (2)#ifdef __cplusplus
}
#endif#endif /* __BOARD_H */
保存。

3、将main_tirtos.c文件的代码更改为:
#include <ti/drivers/GPIO.h>
#include <ti/drivers/gpio/GPIOCC32XX.h>
#include "Board.h"void delay(int temp)
{int i = 0;for (i = 0; i < temp; i++);
}int main(void)
{GPIO_init();while(1){GPIO_write(GREEN_LED, LED_OFF); //灭绿灯GPIO_write(RED_LED, LED_ON); //亮红灯delay(0xfffff);GPIO_write(RED_LED, LED_OFF); //灭红灯GPIO_write(YELLOW_LED, LED_ON); //亮黄灯delay(0xfffff);GPIO_write(YELLOW_LED, LED_OFF); //灭黄灯GPIO_write(GREEN_LED, LED_ON); //亮绿灯delay(0xfffff);}
}
4、现在这代码看上去就很舒服了。编译,运行,大功告成。
Board.h文件的作用为针对特定主板声明各种宏,增加程序可读性。

跑马灯系列总算写完,不容易,庆祝一下。弄完这一系列,对CC3220的整个驱动框架应该有一个大至的了解了。

这篇关于CC3220学习笔记---点亮LED PinMux版的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/553942

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件