RIOT 技术笔记-04 RIOT操作系统中 CC2538的编译和GPIO
1、首先我们还是把riot/examples文件夹中的helloworld例程复制到riot的根目录下(可以建一个文件夹来存放,我建的文件夹是“”mjy-cc2538“”),然后把复制的文件夹改个名称吧,比如led什么的。
2、打开复制并改好名字的文件夹。我们可以看见3个文件 main.c 、makefile和readme.md。首先我们打开makefile文件。如下图所示
这里先插句话,推荐大家使用一款软件notepad。因为在ubuntu中修改文件很麻烦,关键词没法高亮,很容易出错。推荐先把文件拖出来,然后用notepad编辑,然后再放回ubuntu中编译。
上面的图片中我们看见最开始的 “APPLICATION” 这个的含义是工程的名称。我们可以在这里任意选择自己想定义的名称。"BOARD ?="的意思是选择的硬件平台,我改成了cc2538dk,必须是这个哦。这两个地方修改完之后,makefile就可以了。
然后再把makefile文件放回到ubuntu中。打开终端进入该文件夹然后输入 “make” 然后回车就可以编译了。如果在makefile中,BOARD 没有改成cc2538dk,make编译的命令就是 “make BOARD=cc2538dk” 。
如图中所示,这样就初步编译成功了。之后的例程都基本上按照这样修改初始文件。
CC2538的GPIO
GPIO的应用也就是流水灯的控制了。这个是每个单片机工程师都想知道的第一个问题。
首先我们先在riot/cpu/cc2538/
我们可以看见riot提供了完整cc2538的gpio函数。因此要使用gpio也是非常简单了。我们可以看见上图中的很多函数。
相信能看这个的都应该懂stm32。stm32的gpio使用流程是,初始化gpio,然后就可以对gpio进行操作了。因为cc2538的内核也是arm的,因此,对于gpio的使用,可以通过几个函数就能完成。流程如下。
(1)、初始化端口,我们先看这个函数 int gpio_init(gpio_t dev, gpio_mode_t mode);
初始化函数有两个参数:
gpio_t dev 我们可以在riot\drivers\include\periph\gpio.h 中找到gpio_t 。他的定义是 typedef unsigned int gpio_t;
gpio_mode_t mode 我们可以在riot\drivers\include\periph\gpio.h中 。看见如下定义
typedef enum
{
GPIO_IN , /**< configure as input without pull resistor */
GPIO_IN_PD, /**< configure as input with pull-down resistor */
GPIO_IN_PU, /**< configure as input with pull-up resistor */
GPIO_OUT, /**< configure as output in push-pull mode */
GPIO_OD, /**< configure as output in open-drain mode without pull resistor */
GPIO_OD_PU /**< configure as output in open-drain mode with pull resistor enabled */
} gpio_mode_t;
在riot\cpu\cc2538\include\cc2538_gpio.h 中我们可以看到cc2538中,只给我们提供了5种模式。下面所示:
#define IOC_OVERRIDE_OE 0x00000008 /**< Output Enable */
#define IOC_OVERRIDE_PUE 0x00000004 /**< Pull Up Enable */
#define IOC_OVERRIDE_PDE 0x00000002 /**< Pull Down Enable */
#define IOC_OVERRIDE_ANA 0x00000001 /**< Analog Enable */
#define IOC_OVERRIDE_DIS 0x00000000 /**< Override Disabled */
因此,如果我们要初始化PC0端口为上拉输出模式那么我们应该这么用: gpio_init( GPIO_PC0, IOC_OVERRIDE_PUE); 具体其中一个参数为什么使用GPIO_PC0,这个和上面的gpio_t dev有什么联系呢?我们下面介绍。
(2)、端口使用
对于流水灯,我们使用的是推挽模式。其直接应用函数有3个。
void gpio_set(gpio_t dev); //拉高
void gpio_clear(gpio_t dev); //拉低
void gpio_toggle(gpio_t dev); //反转
这里有个问题,端口的使用的时候,只有一个参数的时候,怎么去确定 P几 和pin几?对于这个问题,我们打开文件riot\cpu\cc2538\include\cc2538_gpio.h
下面截取一小片段看看。
GPIO_PA0 = GPIO_PXX_TO_NUM(PORT_A, 0), /**< PA0 */
GPIO_PA1 = GPIO_PXX_TO_NUM(PORT_A, 1), /**< PA1 */
GPIO_PA2 = GPIO_PXX_TO_NUM(PORT_A, 2), /**< PA2 */
GPIO_PA3 = GPIO_PXX_TO_NUM(PORT_A, 3), /**< PA3 */
GPIO_PA4 = GPIO_PXX_TO_NUM(PORT_A, 4), /**< PA4 */
GPIO_PA5 = GPIO_PXX_TO_NUM(PORT_A, 5), /**< PA5 */
GPIO_PA6 = GPIO_PXX_TO_NUM(PORT_A, 6), /**< PA6 */
同一个文件中另外再找到
#define GPIO_PXX_TO_NUM(port_num, bit_num) ( ((port_num) << GPIO_PORT_SHIFT) | (bit_num) )
再找到
#define GPIO_PORT_SHIFT 3
再找到
enum
{
PORT_A = 0,
PORT_B = 1,
PORT_C = 2,
PORT_D = 3,
};
比如我们想定义PD4这个端口。那么
GPIO_PD3 = GPIO_PXX_TO_NUM(PORT_D, 4), /**< PD3 */
下面我们开始计算了 :
1,PORT_D=3;二进制是0000 0011
2,然后根据 ( ((port_num) << GPIO_PORT_SHIFT) | (bit_num) )这个,我们要左移3位。那么0000 0011就变成了 0001 1000。
3,然后再与4或运算,也就是 0001 1000 和0000 0100或运算 得到 0001 1100 。转成10进制也就是28。
4,因此我们得到了 GPIO_PD4 = 28。那么可以这么算每组gpio有8个io后,D是第四组,前三组共24个io了,PD4是第四组的第4个io口,24+4=28。因此28可以代表PD4。riot\cpu\cc2538\periph\gpio.c的最前面有一点说明,自己去找找。
5,void gpio_set(gpio_t dev);我们就可以用作 gpio_set(GPIO_PD4 );
因此我们使用void gpio_set(gpio_t dev);这些函数的时候,里面的参数直接使用GPIO_PXX就好,没必要去计算了。当然为什么28能够代替PD4,那就自己去找找吧,这个类似stm32中的偏移地址,也就是基地址+偏移地址=端口地址。自己去找找吧。。。。
然后我们就可以使用了。比如
gpio_set(GPIO_PC0); //拉高
gpio_clear(GPIO_PC0); //拉低
gpio_toggle(GPIO_PC0); //反转
到此,gpio的使用就介绍到这里,对于gpio的其他模式,大家可以取试试,后面就不多做介绍。
(3)、cc2538继续流水灯
我们继续本帖最上面的话题,复制好了文件和修改makefile后,我们就可以打开main文件了。看下图中main文件,不想写了,太麻烦了。。。。。
然后放回ubuntu中,再编译,在bin文件里面找到 下载文件就可以下载了。。
只能看看静态图片了。3个灯,运行正常,一闪一闪的。
————————————————
版权声明:本文为CSDN博主「莫九玉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mx1252111/java/article/details/52694076