N32905音视频学习笔记-GPIO

目录

准备工作:

1.N32905 GPIO简介

2.硬件设计

3.软件设计

3.1内核配置

3.2 GPIO应用程序分析

4.编译

5.烧录运行

准备工作:

wifi音视频开发板一块

 

1.N32905 GPIO简介

N32905共有192个GPIO,分6组分别为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOG,每组有32个GPIO。

实现流水灯只需两步就可以完成,首先在内核配置中选择支持GPIO,然后编写GPIO用户程序既可。应用程序是通过ioctl系统调用完成对底层硬件的操作。

ioctl是应用程序对设备控制的函数,通常用于设置设备的一些参数,例如串口的传输波特率、马达的转速等等,当然也可以控制GPIO。

函数原型:int ioctl(int fd, ind cmd, …)

输入参数:1.fd:用户程序打开设备时使用open函数返回的文件标示符;

              2.cmd:用户程序对设备的控制命令;

返回值:0:成功;

             -1:出错;

如果驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。

2.硬件设计

底板上的LED1、LED2、LED3、LED4分别与核心板的GPA[0]、GPA[2]、GPA[5]、GPA[6]直接相连,其电路连接如下图1.2.1所示。

图2.1 LED与N32905电路连接图

3.软件设计

3.1内核配置

命令行输入./build spiramfs,按enter键就开始编译内核,内核生成路径在/duckbill/N32905/BSP/image/Kernel.bin。

3.2 GPIO应用程序分析

代码路径:/duckbill/N32905/BSP/applications/gpio/gpio-led/gpio.c。

/*
 * LED application Program
	引脚对应关系
	LED1 ------> GPA0
	LED2 ------> GPA2
	LED3 ------> GPA5
	LED4 ------> GPA6
	输出LED高电平灭,低电平亮 
 *
 */
#include <unistd.h> 
#include <fcntl.h>
#include <stdio.h> 
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>

#define GPIO_SETOUT_HIGH	1       //GPIO输出高电平
#define GPIO_SETOUT_LOW		0		//GPIO输出低电平
#define GPIO_SETDIR_OUT		1		//设置GPIO输出
#define GPIO_SETDIR_IN		0		//设置GPIO输入

// GPIO ioctl command
#define GPIO_IOCTRL_OPEN	1       //打开IOCTL接口
#define GPIO_IOCTRL_SETDIR	2		//设置GPIO方向
#define GPIO_IOCTRL_SETOUT	3		//设置GPIO输出的值
#define GPIO_IOCTRL_GETIN	4		//获取GPIO输入的值


#define DEF_CTRL_DEVICE		"/dev/gpio"     //GPIO设备文件名,即文件节点

//N32905共有5组GPIO,分别为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE.
typedef enum
{
	eDRVGPIO_GPIOA	= 0x00,
	eDRVGPIO_GPIOB	= 0x10,
	eDRVGPIO_GPIOC	= 0x20,
	eDRVGPIO_GPIOD	= 0x30,
	eDRVGPIO_GPIOE	= 0x40
} E_DRVGPIO_PORT;

//每组GPIO下有16个GPIO引脚,从PIN0到PIN15.
typedef enum
{
	eDRVGPIO_PIN0	= 0x0001,
	eDRVGPIO_PIN1	= 0x0002,
	eDRVGPIO_PIN2	= 0x0004,
	eDRVGPIO_PIN3	= 0x0008,
	eDRVGPIO_PIN4	= 0x0010,
	eDRVGPIO_PIN5	= 0x0020,
	eDRVGPIO_PIN6	= 0x0040,
	eDRVGPIO_PIN7	= 0x0080,
	eDRVGPIO_PIN8	= 0x0100,
	eDRVGPIO_PIN9	= 0x0200,
	eDRVGPIO_PIN10	= 0x0400,
	eDRVGPIO_PIN11	= 0x0800,
	eDRVGPIO_PIN12	= 0x1000,
	eDRVGPIO_PIN13	= 0x2000,
	eDRVGPIO_PIN14	= 0x4000,
	eDRVGPIO_PIN15	= 0x8000,
} E_DRVGPIO_BIT;

//结构体S_GPIO_PARAM表示每个GPIO的属性,包含命令、端口、引脚、值。
typedef struct  _S_GPIO_PARAM
{
	int cmd;
	int	port;
	int pin;
	int val;
} S_GPIO_PARAM;

//定义GPIO文件标示符
int s_fdGPIO=0;

//通过ioctl控制GPIO
int CtrlPinsIO(int cmd, int port, int pin, int val)
{
	S_GPIO_PARAM param;
	
	param.cmd	= cmd;
	param.port	= port;
	param.pin	= pin;
	param.val	= val;
	
	if(ioctl(s_fdGPIO, cmd, (void*)&param) < 0)
		printf("CtrlPinsIO:cmd=%d failed!\n", cmd);

	return param.val;
}

int  main(void)
{
	int rec=0,cnt1=0,cnt2=0;
	int key_down=0;
	//打开设备文件,若小于0则打开失败。
	if((s_fdGPIO = open(DEF_CTRL_DEVICE, O_RDWR)) < 0)
	{
		printf("Failed to open %s!\n", DEF_CTRL_DEVICE);
		return 0;
	}
	
//初始化GPA0、GPA2、GPA5、GPA6为输出高电平,LED1-LED4全灭.
CtrlPinsIO(GPIO_IOCTRL_OPEN, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, 0);  			//打开GPA0
CtrlPinsIO(GPIO_IOCTRL_SETDIR, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETDIR_OUT);  //设置GPA0为输出
CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETOUT_HIGH); //设置GPA0输出高电平
	
CtrlPinsIO(GPIO_IOCTRL_OPEN, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, 0);                //打开GPA2
CtrlPinsIO(GPIO_IOCTRL_SETDIR, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETDIR_OUT);  //设置GPA2为输出
CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETOUT_HIGH); //设置GPA2输出高电平
	
CtrlPinsIO(GPIO_IOCTRL_OPEN, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, 0);  			 //打开GPA5
CtrlPinsIO(GPIO_IOCTRL_SETDIR, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETDIR_OUT);  //设置GPA5为输出
CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETOUT_HIGH); //设置GPA5输出高电平
	
CtrlPinsIO(GPIO_IOCTRL_OPEN, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, 0);					 //打开GPA6
CtrlPinsIO(GPIO_IOCTRL_SETDIR, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETDIR_OUT);  //设置GPA6为输出
CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETOUT_HIGH); //设置GPA6输出高电平
	while(1)
	{	
		//LED1亮
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETOUT_LOW);	//设置GPA0输出低电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETOUT_HIGH);//设置GPA2输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETOUT_HIGH);//设置GPA5输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETOUT_HIGH);//设置GPA6输出高电平	
		usleep(500000);  //延时500ms
		
		//LED2亮
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETOUT_HIGH);//设置GPA0输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETOUT_LOW); //设置GPA2输出低电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETOUT_HIGH);//设置GPA5输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETOUT_HIGH);//设置GPA6输出高电平		
		usleep(500000);	//延时500ms
		
		//LED3亮
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETOUT_HIGH);//设置GPA0输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETOUT_HIGH);//设置GPA2输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETOUT_LOW); //设置GPA5输出低电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETOUT_HIGH);//设置GPA6输出高电平		
		usleep(500000);	//延时500ms
		
		//LED4亮
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETOUT_HIGH);//设置GPA0输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETOUT_HIGH);//设置GPA2输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETOUT_HIGH);//设置GPA5输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETOUT_LOW);	//设置GPA6输出低电平
		usleep(500000);	//延时500ms
		
		//LED3亮
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETOUT_HIGH);//设置GPA0输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETOUT_HIGH);//设置GPA2输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETOUT_LOW); //设置GPA5输出低电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETOUT_HIGH);//设置GPA6输出高电平		
		usleep(500000);	//延时500ms
		
		//LED2亮
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN0, GPIO_SETOUT_HIGH);//设置GPA0输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN2, GPIO_SETOUT_LOW); //设置GPA2输出低电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN5, GPIO_SETOUT_HIGH);//设置GPA5输出高电平
		CtrlPinsIO(GPIO_IOCTRL_SETOUT, eDRVGPIO_GPIOA, eDRVGPIO_PIN6, GPIO_SETOUT_HIGH);//设置GPA6输出高电平		
		usleep(500000);	//延时500ms	
	}	
	close(s_fdGPIO);	//关闭设备文件
}

main函数一开始首先打开设备文件open(DEF_CTRL_DEVICE, O_RDWR),对linux操作系统而言,一切设备即文件,应用程序通过设备文件就可以操作底层驱动了。通过调用系统函数ioctl控制LED,依次循环点亮LED1-LED4,最后关闭设备文件。

4.编译

在ubuntu下切换路径至/duckbill/N32905/applications/gpio/gpio-led。

执行make,编译生成可执行文件led_demo,led_demo将会自动拷贝至例程文件系统目录 /duckbill/N32905/usr/TEST_mini905/mkFilesys下。

执行例程文件系统TEST_mini905/test_mini905/目录下的脚本mkjffs2.sh,生成我们所需的jffs2文件系统。

5.烧录运行

N32905音视频开发板与电脑之间连接好usb电源线(也充当下载线)、usb转串口线,将拨码开关S1拨向Rec位,按下自锁开关K1,开发板通电,N32905进入烧录模式。

①烧录loader:Image Type 选择System Image,Image Name选择SpiLoader_905.bin,点击Burn烧录。

②烧录内核:Image No:设置1,Image Name选择Kernel.bin,Image Type 选择Execute,Image execute address设置0,Image start bank设置4,点击Burn烧录。

③烧录文件系统:Image No:设置2,Image Name选择TEST_mini905.jffs2.summary,Image Type 选择Data,Image execute address设置0,Image start bank设置30,点击Burn烧录。

 

烧录完成后将拨码开关S1拨向Nor位,板子重新通电,N32905进入正常启动模式,等待系统运行起来。

在串口超级终端输入./led_demo,将会看到LED1-LED4依次循环点亮,流水灯就实现了。

 

 

猜你喜欢

转载自blog.csdn.net/chenzhe805/article/details/81610738